调整 UI 防御性编程

This commit is contained in:
SepComet 2026-03-17 08:34:38 +08:00
parent 415b92652d
commit f809af4e15
10 changed files with 285 additions and 41 deletions

1
.gitignore vendored
View File

@ -78,6 +78,7 @@ crashlytics-build.properties
/Assets/StreamingAssets /Assets/StreamingAssets
/Assets/StreamingAssets.meta /Assets/StreamingAssets.meta
/Assets/StreamingAssets
/UI参考 /UI参考
/AGENTS.md /AGENTS.md
/bin /bin

View File

@ -2,14 +2,18 @@
<UnityGameFramework> <UnityGameFramework>
<ResourceBuilder> <ResourceBuilder>
<Settings> <Settings>
<<<<<<< Updated upstream
<InternalResourceVersion>5</InternalResourceVersion> <InternalResourceVersion>5</InternalResourceVersion>
=======
<InternalResourceVersion>4</InternalResourceVersion>
>>>>>>> Stashed changes
<Platforms>33</Platforms> <Platforms>33</Platforms>
<AssetBundleCompression>1</AssetBundleCompression> <AssetBundleCompression>1</AssetBundleCompression>
<CompressionHelperTypeName>UnityGameFramework.Runtime.DefaultCompressionHelper</CompressionHelperTypeName> <CompressionHelperTypeName>UnityGameFramework.Runtime.DefaultCompressionHelper</CompressionHelperTypeName>
<AdditionalCompressionSelected>True</AdditionalCompressionSelected> <AdditionalCompressionSelected>True</AdditionalCompressionSelected>
<ForceRebuildAssetBundleSelected>False</ForceRebuildAssetBundleSelected> <ForceRebuildAssetBundleSelected>False</ForceRebuildAssetBundleSelected>
<BuildEventHandlerTypeName>StarForce.Editor.StarForceBuildEventHandler</BuildEventHandlerTypeName> <BuildEventHandlerTypeName>StarForce.Editor.StarForceBuildEventHandler</BuildEventHandlerTypeName>
<OutputDirectory>D:/Learn/GameLearn/UnityProjects/VampireLike/bin/AssetBundles</OutputDirectory> <OutputDirectory>C:/UnityProjects/VampireLike/bin/AssetBundles</OutputDirectory>
<OutputPackageSelected>True</OutputPackageSelected> <OutputPackageSelected>True</OutputPackageSelected>
<OutputFullSelected>True</OutputFullSelected> <OutputFullSelected>True</OutputFullSelected>
<OutputPackedSelected>True</OutputPackedSelected> <OutputPackedSelected>True</OutputPackedSelected>

View File

@ -1,6 +1,7 @@
using CustomEvent; using CustomEvent;
using Definition.Enum; using Definition.Enum;
using GameFramework.Event; using GameFramework.Event;
using UnityEngine;
using UnityGameFramework.Runtime; using UnityGameFramework.Runtime;
namespace UI namespace UI
@ -38,6 +39,7 @@ namespace UI
{ {
if (rawData == null) if (rawData == null)
{ {
Log.Error("DisplayItemInfoFormController.BuildContext() rawData is null.");
return null; return null;
} }
@ -92,20 +94,75 @@ namespace UI
} }
} }
private bool IsCurrentFormSender(object sender)
{
if (sender is DisplayItemInfoForm displayItemInfoForm)
{
return displayItemInfoForm == Form;
}
if (sender is Component component && Form != null)
{
return component.transform.IsChildOf(Form.transform);
}
return false;
}
#region Event Handlers #region Event Handlers
private void DisplayItemInfoLock(object sender, GameEventArgs e) private void DisplayItemInfoLock(object sender, GameEventArgs e)
{ {
if (!(e is DisplayItemInfoLockEventArgs)) return; if (!(e is DisplayItemInfoLockEventArgs))
{
return;
}
if (Context == null)
{
Log.Error("DisplayItemInfoFormController.DisplayItemInfoLock() Context is null.");
return;
}
if (Form == null)
{
Log.Error("DisplayItemInfoFormController.DisplayItemInfoLock() Form is null.");
return;
}
_locked = true; _locked = true;
} }
private void DisplayItemInfoHide(object sender, GameEventArgs e) private void DisplayItemInfoHide(object sender, GameEventArgs e)
{ {
if (!(e is DisplayItemInfoHideEventArgs args)) return; if (!(e is DisplayItemInfoHideEventArgs args))
{
return;
}
if (!args.Force && _locked && sender is not DisplayItemInfoForm) return; if (Context == null)
{
Log.Error("DisplayItemInfoFormController.DisplayItemInfoHide() Context is null.");
return;
}
if (Form == null)
{
Log.Error("DisplayItemInfoFormController.DisplayItemInfoHide() Form is null.");
return;
}
if (args.Force)
{
GameEntry.UIRouter.CloseUI(UIFormType.DisplayItemInfoForm);
_locked = false;
return;
}
if (_locked && !IsCurrentFormSender(sender) && sender is not DisplayItem)
{
return;
}
GameEntry.UIRouter.CloseUI(UIFormType.DisplayItemInfoForm); GameEntry.UIRouter.CloseUI(UIFormType.DisplayItemInfoForm);
_locked = false; _locked = false;

View File

@ -32,8 +32,15 @@ namespace UI
private static LevelUpFormContext BuildContext(LevelUpFormRawData rawData) private static LevelUpFormContext BuildContext(LevelUpFormRawData rawData)
{ {
if (rawData == null || rawData.Rewards == null) if (rawData == null)
{ {
Log.Error("LevelUpFormController.BuildContext() rawData is null.");
return null;
}
if (rawData.Rewards == null)
{
Log.Error("LevelUpFormController.BuildContext() rewards are null.");
return null; return null;
} }
@ -143,7 +150,7 @@ namespace UI
private void OnRefresh(object sender, GameEventArgs e) private void OnRefresh(object sender, GameEventArgs e)
{ {
if (!(sender is LevelUpForm)) if (sender != Form)
{ {
return; return;
} }
@ -158,6 +165,11 @@ namespace UI
private void OnLevelUpPropSelected(object sender, GameEventArgs e) private void OnLevelUpPropSelected(object sender, GameEventArgs e)
{ {
if (sender != Form)
{
return;
}
if (!(e is LevelUpPropSelectedEventArgs args)) if (!(e is LevelUpPropSelectedEventArgs args))
{ {
return; return;

View File

@ -2,7 +2,6 @@ using System.Collections.Generic;
using CustomEvent; using CustomEvent;
using Definition.DataStruct; using Definition.DataStruct;
using Definition.Enum; using Definition.Enum;
using Entity;
using CustomUtility; using CustomUtility;
using Entity.Weapon; using Entity.Weapon;
using GameFramework.Event; using GameFramework.Event;
@ -47,6 +46,7 @@ namespace UI
{ {
if (rawData == null) if (rawData == null)
{ {
Log.Error("ShopFormController.BuildContext() rawData is null.");
return null; return null;
} }
@ -171,8 +171,15 @@ namespace UI
private static void AppendDisplayItemContext(DisplayListAreaContext listContext, DisplayItemContext newItem) private static void AppendDisplayItemContext(DisplayListAreaContext listContext, DisplayItemContext newItem)
{ {
if (listContext == null || newItem == null) if (listContext == null)
{ {
Log.Error("ShopFormController.AppendDisplayItemContext() listContext is null.");
return;
}
if (newItem == null)
{
Log.Warning("ShopFormController.AppendDisplayItemContext() newItem is null.");
return; return;
} }
@ -243,8 +250,15 @@ namespace UI
private void RefreshGoodsItems(ShopRefreshResult result) private void RefreshGoodsItems(ShopRefreshResult result)
{ {
if (Context == null || result == null) if (result == null)
{ {
Log.Error("ShopFormController.RefreshGoodsItems() result is null.");
return;
}
if (Context == null)
{
Log.Error("ShopFormController.RefreshGoodsItems() Context is null.");
return; return;
} }
@ -253,6 +267,7 @@ namespace UI
if (Form == null) if (Form == null)
{ {
Log.Error("ShopFormController.RefreshGoodsItems() Form is null.");
return; return;
} }
@ -262,8 +277,15 @@ namespace UI
private void ApplyGoodsPurchased(ShopPurchaseResult result) private void ApplyGoodsPurchased(ShopPurchaseResult result)
{ {
if (Context == null || result == null) if (result == null)
{ {
Log.Error("ShopFormController.ApplyGoodsPurchased() result is null.");
return;
}
if (Context == null)
{
Log.Error("ShopFormController.ApplyGoodsPurchased() Context is null.");
return; return;
} }
@ -287,6 +309,104 @@ namespace UI
Form?.ApplyGoodsPurchased(result.GoodsIndex, result.DisplayItem); Form?.ApplyGoodsPurchased(result.GoodsIndex, result.DisplayItem);
} }
private bool IsCurrentFormEventSender(object sender)
{
if (sender is ShopForm shopForm)
{
return shopForm == Form;
}
if (sender is Component component && Form != null)
{
return component.transform.IsChildOf(Form.transform);
}
return false;
}
private bool TryGetWeaponInfoRawData(int index, Vector3 targetPos, out DisplayItemInfoFormRawData rawData)
{
rawData = null;
if (_rawData?.WeaponItems == null)
{
Log.Error("ShopFormController.TryGetWeaponInfoRawData() WeaponItems is null.");
return false;
}
if (Context == null)
{
Log.Error("ShopFormController.TryGetWeaponInfoRawData() Context is null.");
return false;
}
if (index < 0 || index >= _rawData.WeaponItems.Count)
{
Log.Error($"ShopFormController.TryGetWeaponInfoRawData() invalid weapon index: {index}.");
return false;
}
WeaponBase weapon = _rawData.WeaponItems[index];
if (weapon?.WeaponData == null)
{
Log.Error($"ShopFormController.TryGetWeaponInfoRawData() weapon data is null at index {index}.");
return false;
}
var weaponData = weapon.WeaponData;
rawData = new DisplayItemInfoFormRawData
{
TargetPos = targetPos,
Index = index,
IconAssetName = weaponData.IconAssetName,
Title = weaponData.Title,
Rarity = weaponData.Rarity,
TypeText = "武器",
Description = ItemDescUtility.CreateWeaponDescription(weaponData),
Price = Mathf.FloorToInt(weaponData.Price * Context.WeaponRecycleRate),
IsWeapon = true
};
return true;
}
private bool TryGetPropInfoRawData(int index, Vector3 targetPos, out DisplayItemInfoFormRawData rawData)
{
rawData = null;
if (_rawData?.PropItems == null)
{
Log.Error("ShopFormController.TryGetPropInfoRawData() PropItems is null.");
return false;
}
if (index < 0 || index >= _rawData.PropItems.Count)
{
Log.Error($"ShopFormController.TryGetPropInfoRawData() invalid prop index: {index}.");
return false;
}
PropItem propItem = _rawData.PropItems[index];
if (propItem == null)
{
Log.Error($"ShopFormController.TryGetPropInfoRawData() prop item is null at index {index}.");
return false;
}
rawData = new DisplayItemInfoFormRawData
{
TargetPos = targetPos,
Index = index,
IconAssetName = propItem.IconAssetName,
Title = propItem.Title,
Rarity = propItem.Rarity,
TypeText = "道具",
Description = ItemDescUtility.CreatePropDescription(propItem),
Price = 0,
IsWeapon = false
};
return true;
}
#endregion #endregion
#region Event Handlers #region Event Handlers
@ -350,32 +470,30 @@ namespace UI
private void DisplayItemShow(object sender, GameEventArgs e) private void DisplayItemShow(object sender, GameEventArgs e)
{ {
if (!(e is DisplayItemShowEventArgs args) || _rawData == null) return; if (!(e is DisplayItemShowEventArgs args))
DisplayItemInfoFormRawData rawData = new();
rawData.TargetPos = args.TargetPos;
rawData.Index = args.Index;
if (args.IsWeapon)
{ {
var weaponData = _rawData.WeaponItems[args.Index].WeaponData; return;
rawData.IconAssetName = weaponData.IconAssetName;
rawData.Title = weaponData.Title;
rawData.Rarity = weaponData.Rarity;
rawData.TypeText = "武器";
rawData.Description = ItemDescUtility.CreateWeaponDescription(weaponData);
rawData.Price = Mathf.FloorToInt(weaponData.Price * Context.WeaponRecycleRate);
rawData.IsWeapon = true;
} }
else
if (!IsCurrentFormEventSender(sender))
{ {
var propItem = _rawData.PropItems[args.Index]; return;
rawData.IconAssetName = propItem.IconAssetName; }
rawData.Title = propItem.Title;
rawData.Rarity = propItem.Rarity; if (_rawData == null)
rawData.TypeText = "道具"; {
rawData.Description = ItemDescUtility.CreatePropDescription(propItem); Log.Error("ShopFormController.DisplayItemShow() _rawData is null.");
rawData.Price = 0; return;
rawData.IsWeapon = false; }
DisplayItemInfoFormRawData rawData;
bool success = args.IsWeapon
? TryGetWeaponInfoRawData(args.Index, args.TargetPos, out rawData)
: TryGetPropInfoRawData(args.Index, args.TargetPos, out rawData);
if (!success)
{
return;
} }
GameEntry.UIRouter.OpenUI(UIFormType.DisplayItemInfoForm, rawData); GameEntry.UIRouter.OpenUI(UIFormType.DisplayItemInfoForm, rawData);
@ -383,10 +501,19 @@ namespace UI
private void WeaponRecycle(object sender, GameEventArgs e) private void WeaponRecycle(object sender, GameEventArgs e)
{ {
if (!(e is ShopWeaponRecycleEventArgs args)) return; if (!(e is ShopWeaponRecycleEventArgs args))
{
return;
}
if (sender is not DisplayItemInfoForm)
{
return;
}
if (_useCase == null || Context == null) if (_useCase == null || Context == null)
{ {
Log.Error("ShopFormController.WeaponRecycle() controller state is invalid.");
return; return;
} }

View File

@ -1,6 +1,7 @@
using CustomEvent; using CustomEvent;
using Definition.Enum; using Definition.Enum;
using GameFramework.Event; using GameFramework.Event;
using UnityEngine;
using UnityGameFramework.Runtime; using UnityGameFramework.Runtime;
namespace UI namespace UI
@ -34,6 +35,7 @@ namespace UI
{ {
if (rawData == null) if (rawData == null)
{ {
Log.Error("SelectRoleFormController.BuildContext() rawData is null.");
return null; return null;
} }
@ -107,17 +109,35 @@ namespace UI
public void UpdateShowRole(RolePropertyAreaContext rolePropertyAreaContext) public void UpdateShowRole(RolePropertyAreaContext rolePropertyAreaContext)
{ {
if (Context != null) if (Context == null)
{ {
Context.RolePropertyAreaContext = rolePropertyAreaContext; Log.Error("SelectRoleFormController.UpdateShowRole() Context is null.");
return;
} }
Context.RolePropertyAreaContext = rolePropertyAreaContext;
Form?.UpdateShowRole(rolePropertyAreaContext); Form?.UpdateShowRole(rolePropertyAreaContext);
} }
private bool IsCurrentFormEventSender(object sender)
{
if (sender is SelectRoleForm selectRoleForm)
{
return selectRoleForm == Form;
}
if (sender is Component component && Form != null)
{
return component.transform.IsChildOf(Form.transform);
}
return false;
}
private void OnMenuSelectRoleReturn(object sender, GameEventArgs e) private void OnMenuSelectRoleReturn(object sender, GameEventArgs e)
{ {
if (!(sender is SelectRoleForm) || !(e is MenuSelectRoleReturnEventArgs)) if (sender != Form || !(e is MenuSelectRoleReturnEventArgs))
{ {
return; return;
} }
@ -132,10 +152,22 @@ namespace UI
return; return;
} }
SelectRoleFormRawData rawData = _useCase != null ? _useCase.SelectRole(args.RoleId) : null; if (!IsCurrentFormEventSender(sender))
{
return;
}
if (_useCase == null)
{
Log.Error("SelectRoleFormController.OnMenuSelectRoleSelected() useCase is null.");
return;
}
SelectRoleFormRawData rawData = _useCase.SelectRole(args.RoleId);
SelectRoleFormContext context = BuildContext(rawData); SelectRoleFormContext context = BuildContext(rawData);
if (context == null) if (context == null)
{ {
Log.Error("SelectRoleFormController.OnMenuSelectRoleSelected() context build failed.");
return; return;
} }
@ -150,7 +182,18 @@ namespace UI
return; return;
} }
_useCase?.ConfirmSelectedRole(); if (!IsCurrentFormEventSender(sender))
{
return;
}
if (_useCase == null)
{
Log.Error("SelectRoleFormController.OnMenuSelectRoleConfirm() useCase is null.");
return;
}
_useCase.ConfirmSelectedRole();
} }
} }
} }

View File

@ -719,7 +719,7 @@ PrefabInstance:
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 11499388, guid: adb3eb1c35fcff14f89fba7b05c9d71c, type: 3} - target: {fileID: 11499388, guid: adb3eb1c35fcff14f89fba7b05c9d71c, type: 3}
propertyPath: m_FrameRate propertyPath: m_FrameRate
value: 60 value: 240
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 11499388, guid: adb3eb1c35fcff14f89fba7b05c9d71c, type: 3} - target: {fileID: 11499388, guid: adb3eb1c35fcff14f89fba7b05c9d71c, type: 3}
propertyPath: m_EditorLanguage propertyPath: m_EditorLanguage

Binary file not shown.