清理各个 Component 里的判断以及调用规范

This commit is contained in:
2026-09-14 18:35:02 +08:00
parent 5fbeec2476
commit 17ee268416
30 changed files with 769 additions and 1326 deletions
@@ -1,6 +1,5 @@
using UnityEngine;
using UnityGameFramework.Runtime;
using Object = UnityEngine.Object;
namespace SepCore.CameraModule
{
@@ -11,178 +10,52 @@ namespace SepCore.CameraModule
[DisallowMultipleComponent]
public class CameraModuleComponent : GameFrameworkComponent
{
[SerializeField] private CinemachineCameraController _cinemachineController;
[SerializeField] private bool _autoSearchController = true;
[SerializeField] private bool _logMissingControllerWarnings = true;
private ICameraController _controller;
private bool _hasLoggedMissingController;
public ICameraController Controller
{
get
{
ResolveController(false);
return IsControllerValid(_controller) ? _controller : null;
}
}
public bool HasController => Controller != null;
public Transform Target => Controller?.Target;
public CameraEffectSettings CurrentSettings => Controller?.CurrentSettings ?? CameraEffectSettings.Default;
protected override void Awake()
{
base.Awake();
ResolveController(false);
}
public void RegisterController(ICameraController controller)
{
if (!IsControllerValid(controller))
{
Log.Warning("CameraModuleComponent.RegisterController() controller is invalid.");
return;
}
_controller = controller;
_hasLoggedMissingController = false;
if (controller is CinemachineCameraController cinemachineController)
{
_cinemachineController = cinemachineController;
}
}
public void UnregisterController(ICameraController controller)
{
if (controller != null && !ReferenceEquals(_controller, controller))
{
return;
}
_controller = null;
_cinemachineController = null;
}
[SerializeField] private CinemachineCameraController _cinemachineController = null;
public void SetTarget(Transform target)
{
if (!EnsureController())
{
return;
}
if (!EnsureController()) return;
_controller.SetTarget(target);
_cinemachineController.SetTarget(target);
}
public void ApplySettings(CameraEffectSettings settings)
{
if (!EnsureController())
{
return;
}
if (!EnsureController()) return;
_controller.ApplySettings(settings);
_cinemachineController.ApplySettings(settings);
}
public void EnableEffect(CameraEffectType effect)
{
if (!EnsureController())
{
return;
}
if (!EnsureController()) return;
_controller.EnableEffect(effect);
_cinemachineController.EnableEffect(effect);
}
public void DisableEffect(CameraEffectType effect)
{
if (!EnsureController())
{
return;
}
if (!EnsureController()) return;
_controller.DisableEffect(effect);
_cinemachineController.DisableEffect(effect);
}
public bool IsEffectEnabled(CameraEffectType effect)
{
return EnsureController() && _controller.IsEffectEnabled(effect);
if (!EnsureController()) return false;
return _cinemachineController.IsEffectEnabled(effect);
}
private bool EnsureController()
{
ResolveController(_logMissingControllerWarnings);
return IsControllerValid(_controller);
}
private void ResolveController(bool logWarning)
{
if (IsControllerValid(_controller))
{
return;
}
if (_cinemachineController != null)
{
_controller = _cinemachineController;
_hasLoggedMissingController = false;
return;
return true;
}
if (!_autoSearchController)
{
LogMissingController(logWarning);
return;
}
_cinemachineController = GetComponentInChildren<CinemachineCameraController>(true);
if (_cinemachineController == null)
{
#if UNITY_2023_1_OR_NEWER
_cinemachineController = FindFirstObjectByType<CinemachineCameraController>(FindObjectsInactive.Include);
#else
_cinemachineController = FindObjectOfType<CinemachineCameraController>(true);
#endif
}
if (_cinemachineController != null)
{
_controller = _cinemachineController;
_hasLoggedMissingController = false;
return;
}
LogMissingController(logWarning);
}
private void LogMissingController(bool logWarning)
{
if (!logWarning || _hasLoggedMissingController)
{
return;
}
_hasLoggedMissingController = true;
Log.Warning(
"CameraModuleComponent requires a CinemachineCameraController. " +
"Assign one in Inspector or place one in the loaded scene.");
}
private static bool IsControllerValid(ICameraController controller)
{
if (controller == null)
{
return false;
}
if (controller is Object unityObject && unityObject == null)
{
return false;
}
return true;
Log.Error("CameraModuleComponent requires a CinemachineCameraController. Assign one in Inspector.");
return false;
}
}
}
@@ -11,11 +11,11 @@ namespace SepCore.DamageText
[SerializeField] private string _poolName = "DamageTextItem";
[SerializeField] private RectTransform _instanceRoot;
[SerializeField] private RectTransform _instanceRoot = null;
[SerializeField] private Canvas _canvas;
[SerializeField] private Canvas _canvas = null;
[SerializeField] private GameObject _damageTextItemPrefab;
[SerializeField] private GameObject _damageTextItemPrefab = null;
private IObjectPool<DamageTextItemObject> _damageTextItemPool;
@@ -30,11 +30,9 @@ namespace SepCore.DamageText
public void ShowDamage(Vector3 worldPosition, int damage)
{
if (damage <= 0 || _damageTextItemPool == null || _canvas == null) return;
if (damage <= 0) return;
DamageTextItem item = CreateDamageTextItem();
if (item == null) return;
item.Show(worldPosition, damage, _canvas, OnItemComplete);
_activeDamageTextItems.Add(item);
}
@@ -62,7 +60,6 @@ namespace SepCore.DamageText
private void OnItemComplete(DamageTextItem item)
{
if (item == null) return;
item.ResetItem();
_activeDamageTextItems.Remove(item);
_damageTextItemPool.Unspawn(item);
@@ -72,7 +69,6 @@ namespace SepCore.DamageText
{
_activeDamageTextItems.Clear();
_damageTextItemPool.Release();
_damageTextItemPool = null;
}
}
}
@@ -13,26 +13,17 @@ namespace SepCore.DamageText
private const float FadeDuration = 0.35f;
private static readonly Color NormalColor = new Color(1f, 0.32f, 0.23f, 1f);
[SerializeField] private RectTransform _cachedTransform;
[SerializeField] private RectTransform _cachedTransform = null;
[SerializeField] private CanvasGroup _canvasGroup;
[SerializeField] private CanvasGroup _canvasGroup = null;
[SerializeField] private TMP_Text _text;
[SerializeField] private TMP_Text _text = null;
private Sequence _sequence;
private Action<DamageTextItem> _onComplete;
private void Awake()
{
if (_cachedTransform == null) _cachedTransform = GetComponent<RectTransform>();
if (_canvasGroup == null) _canvasGroup = GetComponent<CanvasGroup>();
if (_text == null) _text = GetComponent<TMP_Text>();
}
public void Show(Vector3 worldPosition, int damage, Canvas canvas, Action<DamageTextItem> onComplete)
{
if (canvas == null || GameEntry.Scene.MainCamera == null) return;
_onComplete = onComplete;
gameObject.SetActive(true);
KillSequence();
@@ -53,7 +44,7 @@ namespace SepCore.DamageText
.SetEase(Ease.OutQuad));
_sequence.Join(_cachedTransform.DOPunchScale(new Vector3(0.15f, 0.15f, 0f), 0.18f, 6, 0.75f));
_sequence.Join(_canvasGroup.DOFade(0f, FadeDuration).SetDelay(FadeDelay));
_sequence.OnComplete(() => _onComplete?.Invoke(this));
_sequence.OnComplete(() => _onComplete(this));
}
public void ResetItem()
@@ -73,6 +64,7 @@ namespace SepCore.DamageText
private void KillSequence()
{
if (_sequence == null) return;
_sequence.Kill();
_sequence = null;
}
@@ -13,7 +13,7 @@ namespace SepCore.EnemyManager
{
public class EnemyManagerComponent : GameFrameworkComponent
{
private const string EnemyGroupName = "Enemy";
private string EnemyGroupName => GameEntry.Luban.Global.EnemyGroupName;
private EntityComponent _entity;
private EnemyRegistry _enemyRegistry;
@@ -21,8 +21,8 @@ namespace SepCore.EnemyManager
public IReadOnlyCollection<EntityBase> Enemies => _enemyRegistry.Enemies;
[SerializeField] private int _spawnEnemyMaxCount = 5000;
[SerializeField] private int _spawnDistanceFromPlayer = 20;
private int _spawnEnemyMaxCount;
private int _spawnDistanceFromPlayer;
private int _currentSpawnEnemyId;
private int _currentLevel;
@@ -61,12 +61,8 @@ namespace SepCore.EnemyManager
GameEntry.Event.Unsubscribe(HideEntityCompleteEventArgs.EventId, OnHideEntityComplete);
GameEntry.Event.Unsubscribe(ShowEntitySuccessEventArgs.EventId, OnShowEntitySuccess);
_spawnCts?.Dispose();
_spawnCts = null;
_enemyRegistry = null;
_spawnScheduler?.Reset();
_spawnScheduler = null;
_entity = null;
_spawnCts.Dispose();
_spawnScheduler.Reset();
}
public void OnInit(LevelConfig level, Player player)
@@ -78,7 +74,8 @@ namespace SepCore.EnemyManager
}
_isStopped = false;
_spawnEnemyMaxCount = GameEntry.Luban.Global.SpawnEnemyMaxCount;
_spawnDistanceFromPlayer = GameEntry.Luban.Global.SpawnDistanceFromPlayer / 1000;
_player = player.CachedTransform;
_spawnPositionStrategy = new RandomCircleSpawnStrategy(_spawnDistanceFromPlayer);
@@ -138,7 +135,7 @@ namespace SepCore.EnemyManager
var ct = _spawnCts.Token;
var (isCanceled, enemy) =
await _entity.ShowEnemyAsync(enemyData, cancellationToken: ct).SuppressCancellationThrow();
if (isCanceled || ct.IsCancellationRequested || enemy == null || !enemy.Available)
if (isCanceled || ct.IsCancellationRequested)
{
// 取消通常发生在 OnReset 期间,此时实体往往尚未出生,enemy 为 null 无法 hide。
// 真正的兜底在 OnShowEntitySuccess:停战后出生的敌人会被立即 hide。
@@ -150,6 +147,19 @@ namespace SepCore.EnemyManager
return;
}
if (enemy == null)
{
Log.Error("Can not spawn enemy '{0}' with entity id '{1}': entity logic is invalid.", enemyType,
entityId);
return;
}
// 未取消但实体已不可用,说明 OnShowEntitySuccess 已在停战窗口兜底 hide。
if (!enemy.Available)
{
return;
}
// await 恢复时若已停战,说明这是漏网的在途敌人,立即 hide,不注册。
if (_isStopped)
{
@@ -157,11 +167,7 @@ namespace SepCore.EnemyManager
return;
}
if (_player != null)
{
enemy.SetTarget(_player);
}
enemy.SetTarget(_player);
_enemyRegistry.Register(enemy);
}
@@ -20,22 +20,12 @@ namespace SepCore.HPBar
private void Start()
{
if (_hpBarInstanceRoot == null)
{
Log.Error("You must set HP bar instance root first.");
return;
}
_cachedCanvas = _hpBarInstanceRoot.GetComponent<Canvas>();
_hpBarItemObjectPool =
GameEntry.ObjectPool.CreateSingleSpawnObjectPool<HPBarItemObject>("HPBarItem", _instancePoolCapacity);
_activeHPBarItems = new List<HPBarItem>();
}
private void OnDestroy()
{
}
private void Update()
{
for (int i = _activeHPBarItems.Count - 1; i >= 0; i--)
@@ -54,14 +44,14 @@ namespace SepCore.HPBar
{
if (entity == null)
{
Log.Warning("Entity is invalid.");
Log.Error("Entity is invalid.");
return;
}
HPBarItem hpBarItem = GetActiveHPBarItem(entity);
if (hpBarItem == null)
{
hpBarItem = CreateHPBarItem(entity);
hpBarItem = CreateHPBarItem();
_activeHPBarItems.Add(hpBarItem);
}
@@ -77,11 +67,6 @@ namespace SepCore.HPBar
private HPBarItem GetActiveHPBarItem(EntityBase entity)
{
if (entity == null)
{
return null;
}
for (int i = 0; i < _activeHPBarItems.Count; i++)
{
if (_activeHPBarItems[i].Owner == entity)
@@ -93,7 +78,7 @@ namespace SepCore.HPBar
return null;
}
private HPBarItem CreateHPBarItem(EntityBase entity)
private HPBarItem CreateHPBarItem()
{
HPBarItem hpBarItem = null;
HPBarItemObject hpBarItemObject = _hpBarItemObjectPool.Spawn();
@@ -104,7 +89,7 @@ namespace SepCore.HPBar
else
{
hpBarItem = Instantiate(_hpBarItemTemplate);
Transform transform = hpBarItem.GetComponent<Transform>();
Transform transform = hpBarItem.transform;
transform.SetParent(_hpBarInstanceRoot);
transform.localScale = Vector3.one;
_hpBarItemObjectPool.Register(HPBarItemObject.Create(hpBarItem), true);
@@ -14,13 +14,13 @@ namespace SepCore.HPBar
private const float KeepSeconds = 0.4f;
private const float FadeOutSeconds = 0.3f;
[FormerlySerializedAs("m_HPBar")] [SerializeField] private Slider _hPBar = null;
[FormerlySerializedAs("m_HPBar")] [SerializeField] private Slider _hpBar = null;
private Canvas _parentCanvas = null;
private RectTransform _cachedTransform = null;
private CanvasGroup _cachedCanvasGroup = null;
private EntityBase _owner = null;
private int m_OwnerId = 0;
private int _ownerId = 0;
public EntityBase Owner => _owner;
@@ -38,11 +38,11 @@ namespace SepCore.HPBar
StopAllCoroutines();
_cachedCanvasGroup.alpha = 1f;
if (_owner != owner || m_OwnerId != owner.Id)
if (_owner != owner || _ownerId != owner.Id)
{
_hPBar.value = fromHPRatio;
_hpBar.value = fromHPRatio;
_owner = owner;
m_OwnerId = owner.Id;
_ownerId = owner.Id;
}
Refresh();
@@ -57,7 +57,7 @@ namespace SepCore.HPBar
return false;
}
if (_owner != null && Owner.Available && Owner.Id == m_OwnerId)
if (_owner != null && Owner.Available && Owner.Id == _ownerId)
{
Vector3 worldPosition = _owner.CachedTransform.position + Vector3.forward;
Vector3 screenPosition = GameEntry.Scene.MainCamera.WorldToScreenPoint(worldPosition);
@@ -78,7 +78,7 @@ namespace SepCore.HPBar
{
StopAllCoroutines();
_cachedCanvasGroup.alpha = 1f;
_hPBar.value = 1f;
_hpBar.value = 1f;
_owner = null;
gameObject.SetActive(false);
}
@@ -86,23 +86,12 @@ namespace SepCore.HPBar
private void Awake()
{
_cachedTransform = GetComponent<RectTransform>();
if (_cachedTransform == null)
{
Log.Error("RectTransform is invalid.");
return;
}
_cachedCanvasGroup = GetComponent<CanvasGroup>();
if (_cachedCanvasGroup == null)
{
Log.Error("CanvasGroup is invalid.");
return;
}
}
private IEnumerator HPBarCo(float value, float animationDuration, float keepDuration, float fadeOutDuration)
{
yield return _hPBar.SmoothValue(value, animationDuration);
yield return _hpBar.SmoothValue(value, animationDuration);
yield return new WaitForSeconds(keepDuration);
yield return _cachedCanvasGroup.FadeToAlpha(0f, fadeOutDuration);
}
@@ -114,7 +114,7 @@ namespace SepCore.UIRouter
private void RegisterSerializedBindings()
{
if (_controllerBindings == null || _controllerBindings.Count == 0)
if (_controllerBindings.Count == 0)
{
return;
}
@@ -122,28 +122,36 @@ namespace SepCore.UIRouter
HashSet<UIFormType> seen = new();
foreach (ControllerBinding binding in _controllerBindings)
{
if (binding == null || binding.UIFormType == UIFormType.Undefined ||
string.IsNullOrWhiteSpace(binding.ControllerTypeName))
bool hasFormType = binding.UIFormType != UIFormType.Undefined;
bool hasControllerTypeName = !string.IsNullOrWhiteSpace(binding.ControllerTypeName);
if (!hasFormType && !hasControllerTypeName)
{
continue;
}
if (!hasFormType || !hasControllerTypeName)
{
Log.Error("UIRouter binding is incomplete: UIFormType '{0}', controller type name '{1}'.",
binding.UIFormType.ToString(), binding.ControllerTypeName);
continue;
}
if (!seen.Add(binding.UIFormType))
{
Log.Warning("UIRouter duplicate binding for '{0}', later one overrides earlier one.",
Log.Error("UIRouter duplicate binding for '{0}', later one overrides earlier one.",
binding.UIFormType.ToString());
}
Type controllerType = Type.GetType(binding.ControllerTypeName);
if (controllerType == null)
{
Log.Warning("UIRouter binding type not found: {0}", binding.ControllerTypeName);
Log.Error("UIRouter binding type not found: {0}", binding.ControllerTypeName);
continue;
}
if (!typeof(IUIController).IsAssignableFrom(controllerType))
{
Log.Warning("UIRouter binding type '{0}' does not implement IUIFormController.",
Log.Error("UIRouter binding type '{0}' does not implement IUIController.",
binding.ControllerTypeName);
continue;
}