调整 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.meta
/Assets/StreamingAssets
/UI参考
/AGENTS.md
/bin

View File

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

View File

@ -1,6 +1,7 @@
using CustomEvent;
using Definition.Enum;
using GameFramework.Event;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace UI
@ -38,6 +39,7 @@ namespace UI
{
if (rawData == null)
{
Log.Error("DisplayItemInfoFormController.BuildContext() rawData is 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
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;
}
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);
_locked = false;
@ -113,4 +170,4 @@ namespace UI
#endregion
}
}
}

View File

@ -32,8 +32,15 @@ namespace UI
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;
}
@ -143,7 +150,7 @@ namespace UI
private void OnRefresh(object sender, GameEventArgs e)
{
if (!(sender is LevelUpForm))
if (sender != Form)
{
return;
}
@ -158,6 +165,11 @@ namespace UI
private void OnLevelUpPropSelected(object sender, GameEventArgs e)
{
if (sender != Form)
{
return;
}
if (!(e is LevelUpPropSelectedEventArgs args))
{
return;

View File

@ -2,7 +2,6 @@ using System.Collections.Generic;
using CustomEvent;
using Definition.DataStruct;
using Definition.Enum;
using Entity;
using CustomUtility;
using Entity.Weapon;
using GameFramework.Event;
@ -47,6 +46,7 @@ namespace UI
{
if (rawData == null)
{
Log.Error("ShopFormController.BuildContext() rawData is null.");
return null;
}
@ -171,8 +171,15 @@ namespace UI
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;
}
@ -243,8 +250,15 @@ namespace UI
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;
}
@ -253,6 +267,7 @@ namespace UI
if (Form == null)
{
Log.Error("ShopFormController.RefreshGoodsItems() Form is null.");
return;
}
@ -262,8 +277,15 @@ namespace UI
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;
}
@ -287,6 +309,104 @@ namespace UI
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
#region Event Handlers
@ -350,32 +470,30 @@ namespace UI
private void DisplayItemShow(object sender, GameEventArgs e)
{
if (!(e is DisplayItemShowEventArgs args) || _rawData == null) return;
DisplayItemInfoFormRawData rawData = new();
rawData.TargetPos = args.TargetPos;
rawData.Index = args.Index;
if (args.IsWeapon)
if (!(e is DisplayItemShowEventArgs args))
{
var weaponData = _rawData.WeaponItems[args.Index].WeaponData;
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;
return;
}
else
if (!IsCurrentFormEventSender(sender))
{
var propItem = _rawData.PropItems[args.Index];
rawData.IconAssetName = propItem.IconAssetName;
rawData.Title = propItem.Title;
rawData.Rarity = propItem.Rarity;
rawData.TypeText = "道具";
rawData.Description = ItemDescUtility.CreatePropDescription(propItem);
rawData.Price = 0;
rawData.IsWeapon = false;
return;
}
if (_rawData == null)
{
Log.Error("ShopFormController.DisplayItemShow() _rawData is null.");
return;
}
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);
@ -383,10 +501,19 @@ namespace UI
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)
{
Log.Error("ShopFormController.WeaponRecycle() controller state is invalid.");
return;
}

View File

@ -1,6 +1,7 @@
using CustomEvent;
using Definition.Enum;
using GameFramework.Event;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace UI
@ -34,6 +35,7 @@ namespace UI
{
if (rawData == null)
{
Log.Error("SelectRoleFormController.BuildContext() rawData is null.");
return null;
}
@ -107,17 +109,35 @@ namespace UI
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);
}
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)
{
if (!(sender is SelectRoleForm) || !(e is MenuSelectRoleReturnEventArgs))
if (sender != Form || !(e is MenuSelectRoleReturnEventArgs))
{
return;
}
@ -132,10 +152,22 @@ namespace UI
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);
if (context == null)
{
Log.Error("SelectRoleFormController.OnMenuSelectRoleSelected() context build failed.");
return;
}
@ -150,7 +182,18 @@ namespace UI
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}
- target: {fileID: 11499388, guid: adb3eb1c35fcff14f89fba7b05c9d71c, type: 3}
propertyPath: m_FrameRate
value: 60
value: 240
objectReference: {fileID: 0}
- target: {fileID: 11499388, guid: adb3eb1c35fcff14f89fba7b05c9d71c, type: 3}
propertyPath: m_EditorLanguage

Binary file not shown.