diff --git a/Assets/GameMain/DataTables/tbglobalconfig.bytes b/Assets/GameMain/DataTables/tbglobalconfig.bytes index 80bd62d..6135738 100644 Binary files a/Assets/GameMain/DataTables/tbglobalconfig.bytes and b/Assets/GameMain/DataTables/tbglobalconfig.bytes differ diff --git a/Assets/GameMain/DataTables/tbglobalconfig.json b/Assets/GameMain/DataTables/tbglobalconfig.json index a81057f..6dbd88b 100644 --- a/Assets/GameMain/DataTables/tbglobalconfig.json +++ b/Assets/GameMain/DataTables/tbglobalconfig.json @@ -1,12 +1,15 @@ [ { "weaponCapacity": 6, + "propMaxCount": -1, "weaponRecycleRate": 300, "shopGoodsCount": 4, "shopPriceRandomPercent": 50, "shopMinPrice": 0, - "propMaxCount": -1, "levelUpRefreshPriceBase": 2, - "levelUpRewardCount": 4 + "levelUpRewardCount": 4, + "enemyGroupName": "Enemy", + "spawnEnemyMaxCount": 5000, + "spawnDistanceFromPlayer": 20000 } ] \ No newline at end of file diff --git a/Assets/GameMain/DebugPanel/RuntimeDebugPanelComponent.cs b/Assets/GameMain/DebugPanel/RuntimeDebugPanelComponent.cs deleted file mode 100644 index 8f8765e..0000000 --- a/Assets/GameMain/DebugPanel/RuntimeDebugPanelComponent.cs +++ /dev/null @@ -1,580 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using SepCore.Event; -using SepCore.Definition; -using SepCore.Entity; -using SepCore.Components; -using SepCore.CustomUtility; -using SepCore.Simulation; -using SepCore.EnemyManager; -using SepCore.Procedure; -using UnityEngine; -using UnityGameFramework.Runtime; -#if ENABLE_INPUT_SYSTEM -using UnityEngine.InputSystem; -#endif - - -public class RuntimeDebugPanelComponent : MonoBehaviour - -{ - private const float MinSpawnRate = 0.1f; - private const float CornerTapWindow = 0.6f; - private const int RequiredCornerTapCount = 3; - private const int DebugHealAmount = 200; - - [Header("Window Content")] [SerializeField] - private bool _showBuffSection = true; - - [SerializeField] private bool _showBattleOverview = true; - [SerializeField] private bool _showCollisionStats = true; - [SerializeField] private bool _showSpawnControls = true; - [SerializeField] private bool _showBattleDurationControls = true; - [SerializeField] private bool _showPlayerWeaponControls = true; - [SerializeField] private bool _showPlayerHealthControls = true; - [SerializeField] private bool _showTips = true; - - private Rect _windowRect; - private Vector2 _panelScroll; - private GUISkin _panelSkin; - private bool _isPanelVisible; - private int _windowId; - - private string _searchText = string.Empty; - private int _selectedIndex; - private int _addCount = 1; - private Vector2 _buffScroll; - - private float _spawnRateScaleInput = 1f; - private float _extendDurationSeconds = 30f; - - private IReadOnlyList _allProps; - private IReadOnlyList _filteredProps; - private string[] _displayNames = Array.Empty(); - - private int _cornerTapCount; - private float _lastCornerTapTime = -10f; - private bool _lockPlayerHealthToMax; - - private void Awake() - { - _windowId = GetInstanceID(); - } - - private void Update() - { - if (IsTogglePressed()) - { - _isPanelVisible = !_isPanelVisible; - } - - HandleCornerTapGesture(); - if (_lockPlayerHealthToMax) - { - KeepPlayerHealthAtMax(); - } - } - - private void OnGUI() - { - GUISkin previousSkin = GUI.skin; - Matrix4x4 previousMatrix = GUI.matrix; - if (_panelSkin == null) - { - _panelSkin = Instantiate(previousSkin); - _panelSkin.label.fontSize = 18; - _panelSkin.label.wordWrap = true; - _panelSkin.button.fontSize = 18; - _panelSkin.button.padding = new RectOffset(12, 12, 10, 10); - _panelSkin.button.fixedHeight = 44f; - _panelSkin.textField.fontSize = 20; - _panelSkin.textField.fixedHeight = 44f; - _panelSkin.textField.padding = new RectOffset(10, 10, 10, 10); - _panelSkin.window.padding = new RectOffset(16, 16, 12, 16); - _panelSkin.verticalScrollbar.fixedWidth = 28f; - _panelSkin.verticalScrollbarThumb.fixedWidth = 28f; - } - - Rect safeArea = Screen.safeArea; - float scale = Mathf.Max(0.1f, Mathf.Min(safeArea.width, safeArea.height) / 480f); - Rect bounds = new Rect(0f, 0f, safeArea.width / scale, safeArea.height / scale); - try - { - GUI.skin = _panelSkin; - GUI.matrix = Matrix4x4.TRS( - new Vector3(safeArea.x, Screen.height - safeArea.yMax, 0f), - Quaternion.identity, new Vector3(scale, scale, 1f)); - DrawToggleButton(bounds); - if (!_isPanelVisible) return; - - float width = Mathf.Min(460f, bounds.width - 24f); - _windowRect = new Rect(bounds.width - width - 12f, 72f, width, - Mathf.Min(760f, bounds.height - 84f)); - GUI.Window(_windowId, _windowRect, DrawWindow, string.Empty); - } - finally - { - GUI.matrix = previousMatrix; - GUI.skin = previousSkin; - } - } - - private void OnDestroy() - { - if (_panelSkin != null) Destroy(_panelSkin); - } - - private void DrawToggleButton(Rect bounds) - { - const float width = 120f; - const float height = 48f; - Rect buttonRect = new Rect(bounds.width - width - 12f, 12f, width, height); - if (GUI.Button(buttonRect, "DEBUG")) - { - _isPanelVisible = !_isPanelVisible; - } - } - - private void DrawWindow(int windowId) - { - if (_showBuffSection) - { - EnsurePropList(); - } - - GUILayout.BeginVertical(); - GUILayout.BeginHorizontal(); - GUILayout.Label("Runtime Debug", GUILayout.ExpandWidth(true)); - if (GUILayout.Button("Close", GUILayout.Width(90f))) _isPanelVisible = false; - GUILayout.EndHorizontal(); - GUILayout.Space(8f); - _panelScroll = GUILayout.BeginScrollView(_panelScroll, false, true); - - bool hasPreviousSection = false; - if (_showBuffSection) - { - DrawBuffSection(); - hasPreviousSection = true; - } - - if (HasVisibleBattleSection()) - { - if (hasPreviousSection) - { - GUILayout.Space(8f); - GUILayout.Label(string.Empty, GUI.skin.horizontalSlider); - GUILayout.Space(8f); - } - - DrawBattleSection(); - hasPreviousSection = true; - } - - if (_showTips) - { - if (hasPreviousSection) - { - GUILayout.Space(8f); - } - - GUILayout.Label("Tips: press F8 or tap top-left corner 3 times to toggle."); - } - - GUILayout.EndScrollView(); - GUILayout.EndVertical(); - } - - private void DrawBuffSection() - { - GUILayout.Label("Buff Debug"); - GUILayout.BeginHorizontal(); - GUILayout.Label("Search", GUILayout.Width(78f)); - _searchText = GUILayout.TextField(_searchText); - if (GUILayout.Button("Refresh", GUILayout.Width(100f))) - { - EnsurePropList(true); - } - - GUILayout.EndHorizontal(); - - ApplyFilter(_searchText); - if (_displayNames.Length == 0) - { - GUILayout.Label("No Buff data. Enter battle and try again."); - return; - } - - _selectedIndex = Mathf.Clamp(_selectedIndex, 0, _displayNames.Length - 1); - _buffScroll = GUILayout.BeginScrollView(_buffScroll, GUILayout.Height(120f)); - _selectedIndex = GUILayout.SelectionGrid(_selectedIndex, _displayNames, 1); - GUILayout.EndScrollView(); - - PropConfig selectedProp = GetSelectedProp(); - if (selectedProp == null) return; - - GUILayout.Label($"Selected: {selectedProp.Name} ({selectedProp.Rarity})"); - GUILayout.Label(ItemDescUtility.CreatePropDescription(selectedProp.Modifiers), GUILayout.Height(40f)); - - GUILayout.BeginHorizontal(); - GUILayout.Label("Count", GUILayout.Width(78f)); - string addCountText = GUILayout.TextField(_addCount.ToString(), GUILayout.Width(88f)); - if (!int.TryParse(addCountText, out _addCount)) _addCount = 1; - _addCount = Mathf.Clamp(_addCount, 1, 99); - - if (GUILayout.Button("Add Buff To Player", GUILayout.Height(44f))) - { - AddSelectedBuffToPlayer(selectedProp, _addCount); - } - - GUILayout.EndHorizontal(); - } - - private void DrawBattleSection() - { - GUILayout.Label("Battle Debug"); - ProcedureGame procedure = GameEntry.Procedure.CurrentProcedure as ProcedureGame; - EnemyManagerComponent enemyManager = GameEntry.EnemyManager; - Player player = FindPlayer(); - HealthComponent playerHealth = player != null ? player.GetComponent() : null; - - if (enemyManager == null) - { - GUILayout.Label("EnemyManager unavailable."); - return; - } - - if (procedure == null) - { - GUILayout.Label("ProcedureGame unavailable."); - return; - } - - if (_showBattleOverview) - { - GUILayout.Label($"Spawn Rate: {enemyManager.SpawnRateScale:F2}"); - GUILayout.Label( - $"Battle Time: {enemyManager.ElapsedBattleTime:F1}s / {enemyManager.BattleDuration:F1}s"); - GUILayout.Label($"Enemy Count: {enemyManager.CurrentEnemyCount}"); - } - - SimulationWorld simulationWorld = GameEntry.SimulationWorld; - if (_showCollisionStats && simulationWorld != null) - { - GUILayout.Space(4f); - GUILayout.Label( - $"Collision Queries: total {simulationWorld.LastCollisionQueryCount} (Projectile {simulationWorld.LastProjectileCollisionQueryCount} / Area {simulationWorld.LastAreaCollisionQueryCount})"); - GUILayout.Label( - $"Collision Candidates: total {simulationWorld.LastCollisionCandidateCount} (Projectile {simulationWorld.LastProjectileCollisionCandidateCount} / Area {simulationWorld.LastAreaCollisionCandidateCount})"); - GUILayout.Label( - $"Area Resolve: hits {simulationWorld.LastResolvedAreaHitCount}"); - GUILayout.Label( - $"Broad Phase: cell {simulationWorld.LastCollisionCellSize:F2}, hasEnemyTargets {(simulationWorld.LastCollisionHasEnemyTargets ? "Yes" : "No")}"); - if (simulationWorld.LastCollisionCandidateCount != 0) - { - Log.Info($"LastCollisionCandidateCount:{simulationWorld.LastCollisionCandidateCount}"); - } - - if (simulationWorld.LastResolvedAreaHitCount != 0) - { - Log.Info($"LastResolvedAreaHitCount:{simulationWorld.LastResolvedAreaHitCount}"); - } - } - - if (_showSpawnControls) - { - GUILayout.Space(12f); - GUILayout.Label("Enemy Spawn Rate"); - GUILayout.BeginHorizontal(); - GUILayout.Label("Rate", GUILayout.Width(78f)); - string rateText = GUILayout.TextField(_spawnRateScaleInput.ToString("F2"), GUILayout.Width(88f)); - if (float.TryParse(rateText, out float parsedRate)) - { - _spawnRateScaleInput = Mathf.Clamp(parsedRate, MinSpawnRate, 50f); - } - - if (GUILayout.Button("Apply", GUILayout.Width(100f))) - { - enemyManager.SetSpawnRateScale(_spawnRateScaleInput); - } - - GUILayout.EndHorizontal(); - GUILayout.BeginHorizontal(); - - if (GUILayout.Button("x0.5")) - { - _spawnRateScaleInput = Mathf.Max(MinSpawnRate, enemyManager.SpawnRateScale * 0.5f); - enemyManager.SetSpawnRateScale(_spawnRateScaleInput); - } - - if (GUILayout.Button("x2")) - { - _spawnRateScaleInput = enemyManager.SpawnRateScale * 2f; - enemyManager.SetSpawnRateScale(_spawnRateScaleInput); - } - - GUILayout.EndHorizontal(); - } - - if (_showBattleDurationControls) - { - GUILayout.Space(12f); - GUILayout.Label("Battle Duration"); - GUILayout.BeginHorizontal(); - GUILayout.Label("Add Sec", GUILayout.Width(78f)); - string durationText = GUILayout.TextField(_extendDurationSeconds.ToString("F0"), GUILayout.Width(88f)); - if (float.TryParse(durationText, out float parsedDuration)) - { - _extendDurationSeconds = Mathf.Clamp(parsedDuration, 1f, 3600f); - } - - if (GUILayout.Button("Extend Battle", GUILayout.Height(44f))) - { - if (procedure.CurrentGameState is GameStateBattle gameState) - { - gameState.AddBattleDuration(_extendDurationSeconds); - } - } - - GUILayout.EndHorizontal(); - } - - if (_showPlayerWeaponControls) - { - GUILayout.Space(12f); - GUILayout.Label( - $"Player Weapon: {(player == null ? "Player not found" : (player.WeaponEnabled ? "Enabled" : "Disabled"))}"); - GUILayout.BeginHorizontal(); - GUI.enabled = player != null; - if (GUILayout.Button("Disable Weapons", GUILayout.Height(44f))) - { - player.SetWeaponEnabled(false); - } - - if (GUILayout.Button("Enable Weapons", GUILayout.Height(44f))) - { - player.SetWeaponEnabled(true); - } - - GUI.enabled = true; - GUILayout.EndHorizontal(); - } - - if (_showPlayerHealthControls) - { - GUILayout.Space(4f); - GUILayout.Label( - $"Player HP: {(playerHealth == null ? "Unavailable" : $"{playerHealth.CurrentHealth}/{playerHealth.MaxHealth}")}"); - GUILayout.BeginHorizontal(); - GUI.enabled = playerHealth != null; - if (GUILayout.Button($"+{DebugHealAmount} HP", GUILayout.Height(44f))) - { - AddPlayerHealth(playerHealth, DebugHealAmount); - } - - if (GUILayout.Button(_lockPlayerHealthToMax ? "GodMode: ON" : "GodMode: OFF", GUILayout.Height(44f))) - { - _lockPlayerHealthToMax = !_lockPlayerHealthToMax; - if (_lockPlayerHealthToMax) - { - RestorePlayerHealthToMax(playerHealth); - } - } - - GUI.enabled = true; - GUILayout.EndHorizontal(); - } - } - - private bool HasVisibleBattleSection() - { - return _showBattleOverview || - _showCollisionStats || - _showSpawnControls || - _showBattleDurationControls || - _showPlayerWeaponControls || - _showPlayerHealthControls; - } - - private void EnsurePropList(bool force = false) - { - if (!force && _allProps != null && _allProps.Count > 0) return; - - if (GameEntry.Luban == null) - { - _allProps = Array.Empty(); - _displayNames = Array.Empty(); - return; - } - - _allProps = GameEntry.Luban.GetTable(); - _selectedIndex = Mathf.Clamp(_selectedIndex, 0, Mathf.Max(0, _allProps.Count - 1)); - ApplyFilter(_searchText); - } - - private void ApplyFilter(string keyword) - { - if (_allProps == null || _allProps.Count == 0) - { - _displayNames = Array.Empty(); - return; - } - - if (string.IsNullOrWhiteSpace(keyword)) - { - _filteredProps = _allProps; - } - else - { - string search = keyword.Trim(); - _filteredProps = _allProps.Where(p => - p != null && - (p.Name?.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0 || - p.Id.ToString().Contains(search))).ToArray(); - } - - _displayNames = _filteredProps.Select(p => $"[{p.Id}] {p.Name} ({p.Rarity})").ToArray(); - if (_displayNames.Length == 0) _selectedIndex = 0; - else _selectedIndex = Mathf.Clamp(_selectedIndex, 0, _displayNames.Length - 1); - } - - private PropConfig GetSelectedProp() - { - if (_filteredProps == null || _filteredProps.Count == 0) return null; - _selectedIndex = Mathf.Clamp(_selectedIndex, 0, _filteredProps.Count - 1); - return _filteredProps[_selectedIndex]; - } - - private static Player FindPlayer() - { - return UnityEngine.Object.FindObjectOfType(); - } - - private void KeepPlayerHealthAtMax() - { - Player player = FindPlayer(); - if (player == null) return; - - HealthComponent playerHealth = player.GetComponent(); - if (playerHealth == null) return; - - RestorePlayerHealthToMax(playerHealth); - } - - private static void AddPlayerHealth(HealthComponent playerHealth, int amount) - { - if (playerHealth == null || amount <= 0) return; - if (playerHealth.CurrentHealth <= 0) return; - - int maxHealth = playerHealth.MaxHealth; - if (maxHealth <= 0) return; - - int nextHealth = Mathf.Clamp(playerHealth.CurrentHealth + amount, 0, maxHealth); - if (nextHealth == playerHealth.CurrentHealth) return; - - playerHealth.CurrentHealth = nextHealth; - PublishPlayerHealthChanged(playerHealth); - } - - private static void RestorePlayerHealthToMax(HealthComponent playerHealth) - { - if (playerHealth == null) return; - if (playerHealth.CurrentHealth <= 0) return; - - int maxHealth = playerHealth.MaxHealth; - if (maxHealth <= 0 || playerHealth.CurrentHealth >= maxHealth) return; - - playerHealth.CurrentHealth = maxHealth; - PublishPlayerHealthChanged(playerHealth); - } - - private static void PublishPlayerHealthChanged(HealthComponent playerHealth) - { - if (playerHealth == null || GameEntry.Event == null) return; - - GameEntry.Event.Fire(null, - PlayerHealthChangeEventArgs.Create(0, playerHealth.CurrentHealth, playerHealth.MaxHealth)); - } - - private static void AddSelectedBuffToPlayer(PropConfig prop, int count) - { - Player player = FindPlayer(); - if (player == null || prop == null || prop.Modifiers == null) return; - - int applyCount = Mathf.Clamp(count, 1, 99); - for (int i = 0; i < applyCount; i++) - { - player.AddProp(new PropItem(prop)); - } - } - - private void HandleCornerTapGesture() - { - if (!TryGetTouchReleased(out Vector2 touchPosition)) return; - if (touchPosition.x > 80f || touchPosition.y < Screen.height - 80f) return; - - float now = Time.unscaledTime; - if (now - _lastCornerTapTime > CornerTapWindow) - { - _cornerTapCount = 0; - } - - _lastCornerTapTime = now; - _cornerTapCount++; - - if (_cornerTapCount >= RequiredCornerTapCount) - { - _cornerTapCount = 0; - _isPanelVisible = !_isPanelVisible; - } - } - - private static bool IsTogglePressed() - { -#if ENABLE_INPUT_SYSTEM - Keyboard keyboard = Keyboard.current; - if (keyboard == null) return false; - return keyboard.backquoteKey.wasPressedThisFrame || keyboard.f8Key.wasPressedThisFrame; -#else - return Input.GetKeyDown(KeyCode.BackQuote) || Input.GetKeyDown(KeyCode.F8); -#endif - } - - private static bool TryGetTouchReleased(out Vector2 touchPosition) - { -#if ENABLE_INPUT_SYSTEM - Touchscreen touchscreen = Touchscreen.current; - if (touchscreen == null) - { - touchPosition = default; - return false; - } - - var touch = touchscreen.primaryTouch; - if (!touch.press.wasReleasedThisFrame) - { - touchPosition = default; - return false; - } - - touchPosition = touch.position.ReadValue(); - return true; -#else - if (Input.touchCount <= 0) - { - touchPosition = default; - return false; - } - - Touch touch = Input.GetTouch(0); - if (touch.phase != TouchPhase.Ended) - { - touchPosition = default; - return false; - } - - touchPosition = touch.position; - return true; -#endif - } -} diff --git a/Assets/GameMain/Scripts/Base/Gen/GlobalConfig.cs b/Assets/GameMain/Scripts/Base/Gen/GlobalConfig.cs index e17127c..47c990d 100644 --- a/Assets/GameMain/Scripts/Base/Gen/GlobalConfig.cs +++ b/Assets/GameMain/Scripts/Base/Gen/GlobalConfig.cs @@ -17,13 +17,16 @@ public sealed partial class GlobalConfig : Luban.BeanBase public GlobalConfig(ByteBuf _buf) { WeaponCapacity = _buf.ReadInt(); + PropMaxCount = _buf.ReadInt(); WeaponRecycleRate = _buf.ReadInt(); ShopGoodsCount = _buf.ReadInt(); ShopPriceRandomPercent = _buf.ReadInt(); ShopMinPrice = _buf.ReadInt(); - PropMaxCount = _buf.ReadInt(); LevelUpRefreshPriceBase = _buf.ReadInt(); LevelUpRewardCount = _buf.ReadInt(); + EnemyGroupName = _buf.ReadString(); + SpawnEnemyMaxCount = _buf.ReadInt(); + SpawnDistanceFromPlayer = _buf.ReadInt(); } public static GlobalConfig DeserializeGlobalConfig(ByteBuf _buf) @@ -36,6 +39,10 @@ public sealed partial class GlobalConfig : Luban.BeanBase /// public readonly int WeaponCapacity; /// + /// 最大持有道具数量 + /// + public readonly int PropMaxCount; + /// /// 武器回收价比例 /// public readonly int WeaponRecycleRate; @@ -52,10 +59,6 @@ public sealed partial class GlobalConfig : Luban.BeanBase /// public readonly int ShopMinPrice; /// - /// 最大持有道具数量 - /// - public readonly int PropMaxCount; - /// /// 升级奖励刷新基本价格 /// public readonly int LevelUpRefreshPriceBase; @@ -63,6 +66,18 @@ public sealed partial class GlobalConfig : Luban.BeanBase /// 升级奖励候选数 /// public readonly int LevelUpRewardCount; + /// + /// 敌人对象池名 + /// + public readonly string EnemyGroupName; + /// + /// 最大敌人数量 + /// + public readonly int SpawnEnemyMaxCount; + /// + /// 敌人生成距离 + /// + public readonly int SpawnDistanceFromPlayer; public const int __ID__ = -958250779; public override int GetTypeId() => __ID__; @@ -77,19 +92,25 @@ public sealed partial class GlobalConfig : Luban.BeanBase + + + } public override string ToString() { return "{ " + "weaponCapacity:" + WeaponCapacity + "," + + "propMaxCount:" + PropMaxCount + "," + "weaponRecycleRate:" + WeaponRecycleRate + "," + "shopGoodsCount:" + ShopGoodsCount + "," + "shopPriceRandomPercent:" + ShopPriceRandomPercent + "," + "shopMinPrice:" + ShopMinPrice + "," - + "propMaxCount:" + PropMaxCount + "," + "levelUpRefreshPriceBase:" + LevelUpRefreshPriceBase + "," + "levelUpRewardCount:" + LevelUpRewardCount + "," + + "enemyGroupName:" + EnemyGroupName + "," + + "spawnEnemyMaxCount:" + SpawnEnemyMaxCount + "," + + "spawnDistanceFromPlayer:" + SpawnDistanceFromPlayer + "," + "}"; } } diff --git a/Assets/GameMain/Scripts/Base/Gen/TbGlobalConfig.cs b/Assets/GameMain/Scripts/Base/Gen/TbGlobalConfig.cs index d2833c7..a992005 100644 --- a/Assets/GameMain/Scripts/Base/Gen/TbGlobalConfig.cs +++ b/Assets/GameMain/Scripts/Base/Gen/TbGlobalConfig.cs @@ -35,6 +35,10 @@ public partial class TbGlobalConfig /// public int WeaponCapacity => _data.WeaponCapacity; /// + /// 最大持有道具数量 + /// + public int PropMaxCount => _data.PropMaxCount; + /// /// 武器回收价比例 /// public int WeaponRecycleRate => _data.WeaponRecycleRate; @@ -51,10 +55,6 @@ public partial class TbGlobalConfig /// public int ShopMinPrice => _data.ShopMinPrice; /// - /// 最大持有道具数量 - /// - public int PropMaxCount => _data.PropMaxCount; - /// /// 升级奖励刷新基本价格 /// public int LevelUpRefreshPriceBase => _data.LevelUpRefreshPriceBase; @@ -62,6 +62,18 @@ public partial class TbGlobalConfig /// 升级奖励候选数 /// public int LevelUpRewardCount => _data.LevelUpRewardCount; + /// + /// 敌人对象池名 + /// + public string EnemyGroupName => _data.EnemyGroupName; + /// + /// 最大敌人数量 + /// + public int SpawnEnemyMaxCount => _data.SpawnEnemyMaxCount; + /// + /// 敌人生成距离 + /// + public int SpawnDistanceFromPlayer => _data.SpawnDistanceFromPlayer; public void ResolveRef(Tables tables) { diff --git a/Assets/GameMain/DebugPanel.meta b/Assets/GameMain/Scripts/Procedure/DebugPanel.meta similarity index 100% rename from Assets/GameMain/DebugPanel.meta rename to Assets/GameMain/Scripts/Procedure/DebugPanel.meta diff --git a/Assets/GameMain/Scripts/Procedure/DebugPanel/RuntimeDebugPanelComponent.cs b/Assets/GameMain/Scripts/Procedure/DebugPanel/RuntimeDebugPanelComponent.cs new file mode 100644 index 0000000..7adb0f0 --- /dev/null +++ b/Assets/GameMain/Scripts/Procedure/DebugPanel/RuntimeDebugPanelComponent.cs @@ -0,0 +1,561 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using SepCore.Event; +using SepCore.Definition; +using SepCore.Entity; +using SepCore.Components; +using SepCore.CustomUtility; +using SepCore.Simulation; +using SepCore.EnemyManager; +using SepCore.Procedure; +using UnityEngine; +using UnityGameFramework.Runtime; +#if ENABLE_INPUT_SYSTEM +using UnityEngine.InputSystem; +#endif + +namespace SepCore.DebugPanel +{ + public class RuntimeDebugPanelComponent : MonoBehaviour + { + private const float MinSpawnRate = 0.1f; + private const float CornerTapWindow = 0.6f; + private const int RequiredCornerTapCount = 3; + private const int DebugHealAmount = 200; + + [Header("Window Content")] + [SerializeField] private bool _showBuffSection = true; + + [SerializeField] private bool _showBattleOverview = true; + [SerializeField] private bool _showCollisionStats = true; + [SerializeField] private bool _showSpawnControls = true; + [SerializeField] private bool _showBattleDurationControls = true; + [SerializeField] private bool _showPlayerWeaponControls = true; + [SerializeField] private bool _showPlayerHealthControls = true; + [SerializeField] private bool _showTips = true; + + private Rect _windowRect; + private Vector2 _panelScroll; + private GUISkin _panelSkin; + private bool _isPanelVisible; + private int _windowId; + + private string _searchText = string.Empty; + private int _selectedIndex; + private int _addCount = 1; + private Vector2 _buffScroll; + + private float _spawnRateScaleInput = 1f; + private float _extendDurationSeconds = 30f; + + private IReadOnlyList _allProps; + private IReadOnlyList _filteredProps; + private string[] _displayNames = Array.Empty(); + + private int _cornerTapCount; + private float _lastCornerTapTime = -10f; + private bool _lockPlayerHealthToMax; + + private void Awake() + { + _windowId = GetInstanceID(); + } + + private void Update() + { + if (IsTogglePressed()) + { + _isPanelVisible = !_isPanelVisible; + } + + HandleCornerTapGesture(); + if (_lockPlayerHealthToMax) + { + KeepPlayerHealthAtMax(); + } + } + + private void OnGUI() + { + GUISkin previousSkin = GUI.skin; + Matrix4x4 previousMatrix = GUI.matrix; + if (_panelSkin == null) + { + _panelSkin = Instantiate(previousSkin); + _panelSkin.label.fontSize = 18; + _panelSkin.label.wordWrap = true; + _panelSkin.button.fontSize = 18; + _panelSkin.button.padding = new RectOffset(12, 12, 10, 10); + _panelSkin.button.fixedHeight = 44f; + _panelSkin.textField.fontSize = 20; + _panelSkin.textField.fixedHeight = 44f; + _panelSkin.textField.padding = new RectOffset(10, 10, 10, 10); + _panelSkin.window.padding = new RectOffset(16, 16, 12, 16); + _panelSkin.verticalScrollbar.fixedWidth = 28f; + _panelSkin.verticalScrollbarThumb.fixedWidth = 28f; + } + + Rect safeArea = Screen.safeArea; + float scale = Mathf.Max(0.1f, Mathf.Min(safeArea.width, safeArea.height) / 480f); + Rect bounds = new Rect(0f, 0f, safeArea.width / scale, safeArea.height / scale); + try + { + GUI.skin = _panelSkin; + GUI.matrix = Matrix4x4.TRS( + new Vector3(safeArea.x, Screen.height - safeArea.yMax, 0f), + Quaternion.identity, new Vector3(scale, scale, 1f)); + DrawToggleButton(bounds); + if (!_isPanelVisible) return; + + float width = Mathf.Min(460f, bounds.width - 24f); + _windowRect = new Rect(bounds.width - width - 12f, 72f, width, + Mathf.Min(760f, bounds.height - 84f)); + GUI.Window(_windowId, _windowRect, DrawWindow, string.Empty); + } + finally + { + GUI.matrix = previousMatrix; + GUI.skin = previousSkin; + } + } + + private void OnDestroy() + { + if (_panelSkin != null) Destroy(_panelSkin); + } + + private void DrawToggleButton(Rect bounds) + { + const float width = 120f; + const float height = 48f; + Rect buttonRect = new Rect(bounds.width - width - 12f, 12f, width, height); + if (GUI.Button(buttonRect, "DEBUG")) + { + _isPanelVisible = !_isPanelVisible; + } + } + + private void DrawWindow(int windowId) + { + if (_showBuffSection) + { + EnsurePropList(); + } + + GUILayout.BeginVertical(); + GUILayout.BeginHorizontal(); + GUILayout.Label("Runtime Debug", GUILayout.ExpandWidth(true)); + if (GUILayout.Button("Close", GUILayout.Width(90f))) _isPanelVisible = false; + GUILayout.EndHorizontal(); + GUILayout.Space(8f); + _panelScroll = GUILayout.BeginScrollView(_panelScroll, false, true); + + bool hasPreviousSection = false; + if (_showBuffSection) + { + DrawBuffSection(); + hasPreviousSection = true; + } + + if (HasVisibleBattleSection()) + { + if (hasPreviousSection) + { + GUILayout.Space(8f); + GUILayout.Label(string.Empty, GUI.skin.horizontalSlider); + GUILayout.Space(8f); + } + + DrawBattleSection(); + hasPreviousSection = true; + } + + if (_showTips) + { + if (hasPreviousSection) + { + GUILayout.Space(8f); + } + + GUILayout.Label("Tips: press F8 or tap top-left corner 3 times to toggle."); + } + + GUILayout.EndScrollView(); + GUILayout.EndVertical(); + } + + private void DrawBuffSection() + { + GUILayout.Label("Buff Debug"); + GUILayout.BeginHorizontal(); + GUILayout.Label("Search", GUILayout.Width(78f)); + _searchText = GUILayout.TextField(_searchText); + if (GUILayout.Button("Refresh", GUILayout.Width(100f))) + { + EnsurePropList(true); + } + + GUILayout.EndHorizontal(); + + ApplyFilter(_searchText); + if (_displayNames.Length == 0) + { + GUILayout.Label("No Buff data. Enter battle and try again."); + return; + } + + _selectedIndex = Mathf.Clamp(_selectedIndex, 0, _displayNames.Length - 1); + _buffScroll = GUILayout.BeginScrollView(_buffScroll, GUILayout.Height(120f)); + _selectedIndex = GUILayout.SelectionGrid(_selectedIndex, _displayNames, 1); + GUILayout.EndScrollView(); + + PropConfig selectedProp = GetSelectedProp(); + if (selectedProp == null) return; + + GUILayout.Label($"Selected: {selectedProp.Name} ({selectedProp.Rarity})"); + GUILayout.Label(ItemDescUtility.CreatePropDescription(selectedProp.Modifiers), GUILayout.Height(40f)); + + GUILayout.BeginHorizontal(); + GUILayout.Label("Count", GUILayout.Width(78f)); + string addCountText = GUILayout.TextField(_addCount.ToString(), GUILayout.Width(88f)); + if (!int.TryParse(addCountText, out _addCount)) _addCount = 1; + _addCount = Mathf.Clamp(_addCount, 1, 99); + + if (GUILayout.Button("Add Buff To Player", GUILayout.Height(44f))) + { + AddSelectedBuffToPlayer(selectedProp, _addCount); + } + + GUILayout.EndHorizontal(); + } + + private void DrawBattleSection() + { + GUILayout.Label("Battle Debug"); + ProcedureGame procedure = GameEntry.Procedure.CurrentProcedure as ProcedureGame; + Player player = FindPlayer(); + HealthComponent playerHealth = player != null ? player.GetComponent() : null; + + if (procedure == null) + { + GUILayout.Label("ProcedureGame unavailable."); + return; + } + + EnemyManagerComponent enemyManager = GameEntry.EnemyManager; + + if (_showBattleOverview) + { + GUILayout.Label($"Spawn Rate: {enemyManager.SpawnRateScale:F2}"); + GUILayout.Label( + $"Battle Time: {enemyManager.ElapsedBattleTime:F1}s / {enemyManager.BattleDuration:F1}s"); + GUILayout.Label($"Enemy Count: {enemyManager.CurrentEnemyCount}"); + } + + if (_showCollisionStats) + { + SimulationWorld simulationWorld = GameEntry.SimulationWorld; + GUILayout.Space(4f); + GUILayout.Label( + $"Collision Queries: total {simulationWorld.LastCollisionQueryCount} (Projectile {simulationWorld.LastProjectileCollisionQueryCount} / Area {simulationWorld.LastAreaCollisionQueryCount})"); + GUILayout.Label( + $"Collision Candidates: total {simulationWorld.LastCollisionCandidateCount} (Projectile {simulationWorld.LastProjectileCollisionCandidateCount} / Area {simulationWorld.LastAreaCollisionCandidateCount})"); + GUILayout.Label( + $"Area Resolve: hits {simulationWorld.LastResolvedAreaHitCount}"); + GUILayout.Label( + $"Broad Phase: cell {simulationWorld.LastCollisionCellSize:F2}, hasEnemyTargets {(simulationWorld.LastCollisionHasEnemyTargets ? "Yes" : "No")}"); + } + + if (_showSpawnControls) + { + GUILayout.Space(12f); + GUILayout.Label("Enemy Spawn Rate"); + GUILayout.BeginHorizontal(); + GUILayout.Label("Rate", GUILayout.Width(78f)); + string rateText = GUILayout.TextField(_spawnRateScaleInput.ToString("F2"), GUILayout.Width(88f)); + if (float.TryParse(rateText, out float parsedRate)) + { + _spawnRateScaleInput = Mathf.Clamp(parsedRate, MinSpawnRate, 50f); + } + + if (GUILayout.Button("Apply", GUILayout.Width(100f))) + { + enemyManager.SetSpawnRateScale(_spawnRateScaleInput); + } + + GUILayout.EndHorizontal(); + GUILayout.BeginHorizontal(); + + if (GUILayout.Button("x0.5")) + { + _spawnRateScaleInput = Mathf.Max(MinSpawnRate, enemyManager.SpawnRateScale * 0.5f); + enemyManager.SetSpawnRateScale(_spawnRateScaleInput); + } + + if (GUILayout.Button("x2")) + { + _spawnRateScaleInput = enemyManager.SpawnRateScale * 2f; + enemyManager.SetSpawnRateScale(_spawnRateScaleInput); + } + + GUILayout.EndHorizontal(); + } + + if (_showBattleDurationControls) + { + GUILayout.Space(12f); + GUILayout.Label("Battle Duration"); + GUILayout.BeginHorizontal(); + GUILayout.Label("Add Sec", GUILayout.Width(78f)); + string durationText = GUILayout.TextField(_extendDurationSeconds.ToString("F0"), GUILayout.Width(88f)); + if (float.TryParse(durationText, out float parsedDuration)) + { + _extendDurationSeconds = Mathf.Clamp(parsedDuration, 1f, 3600f); + } + + if (GUILayout.Button("Extend Battle", GUILayout.Height(44f))) + { + if (procedure.CurrentGameState is GameStateBattle gameState) + { + gameState.AddBattleDuration(_extendDurationSeconds); + } + } + + GUILayout.EndHorizontal(); + } + + if (_showPlayerWeaponControls) + { + GUILayout.Space(12f); + GUILayout.Label( + $"Player Weapon: {(player == null ? "Player not found" : (player.WeaponEnabled ? "Enabled" : "Disabled"))}"); + GUILayout.BeginHorizontal(); + GUI.enabled = player != null; + if (GUILayout.Button("Disable Weapons", GUILayout.Height(44f))) + { + player.SetWeaponEnabled(false); + } + + if (GUILayout.Button("Enable Weapons", GUILayout.Height(44f))) + { + player.SetWeaponEnabled(true); + } + + GUI.enabled = true; + GUILayout.EndHorizontal(); + } + + if (_showPlayerHealthControls) + { + GUILayout.Space(4f); + GUILayout.Label( + $"Player HP: {(playerHealth == null ? "Unavailable" : $"{playerHealth.CurrentHealth}/{playerHealth.MaxHealth}")}"); + GUILayout.BeginHorizontal(); + GUI.enabled = playerHealth != null; + if (GUILayout.Button($"+{DebugHealAmount} HP", GUILayout.Height(44f))) + { + AddPlayerHealth(playerHealth, DebugHealAmount); + } + + if (GUILayout.Button(_lockPlayerHealthToMax ? "GodMode: ON" : "GodMode: OFF", GUILayout.Height(44f))) + { + _lockPlayerHealthToMax = !_lockPlayerHealthToMax; + if (_lockPlayerHealthToMax) + { + RestorePlayerHealthToMax(playerHealth); + } + } + + GUI.enabled = true; + GUILayout.EndHorizontal(); + } + } + + private bool HasVisibleBattleSection() + { + return _showBattleOverview || + _showCollisionStats || + _showSpawnControls || + _showBattleDurationControls || + _showPlayerWeaponControls || + _showPlayerHealthControls; + } + + private void EnsurePropList(bool force = false) + { + if (!force && _allProps != null && _allProps.Count > 0) return; + + if (!GameEntry.Luban.IsReady) + { + _allProps = Array.Empty(); + _displayNames = Array.Empty(); + return; + } + + _allProps = GameEntry.Luban.GetTable(); + _selectedIndex = Mathf.Clamp(_selectedIndex, 0, Mathf.Max(0, _allProps.Count - 1)); + ApplyFilter(_searchText); + } + + private void ApplyFilter(string keyword) + { + if (_allProps == null || _allProps.Count == 0) + { + _displayNames = Array.Empty(); + return; + } + + if (string.IsNullOrWhiteSpace(keyword)) + { + _filteredProps = _allProps; + } + else + { + string search = keyword.Trim(); + _filteredProps = _allProps.Where(p => + p.Name.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0 || + p.Id.ToString().Contains(search)).ToArray(); + } + + _displayNames = _filteredProps.Select(p => $"[{p.Id}] {p.Name} ({p.Rarity})").ToArray(); + if (_displayNames.Length == 0) _selectedIndex = 0; + else _selectedIndex = Mathf.Clamp(_selectedIndex, 0, _displayNames.Length - 1); + } + + private PropConfig GetSelectedProp() + { + if (_filteredProps == null || _filteredProps.Count == 0) return null; + _selectedIndex = Mathf.Clamp(_selectedIndex, 0, _filteredProps.Count - 1); + return _filteredProps[_selectedIndex]; + } + + private static Player FindPlayer() + { + return UnityEngine.Object.FindObjectOfType(); + } + + private void KeepPlayerHealthAtMax() + { + Player player = FindPlayer(); + if (player == null) return; + + HealthComponent playerHealth = player.GetComponent(); + RestorePlayerHealthToMax(playerHealth); + } + + private static void AddPlayerHealth(HealthComponent playerHealth, int amount) + { + if (amount <= 0) return; + if (playerHealth.CurrentHealth <= 0) return; + + int maxHealth = playerHealth.MaxHealth; + if (maxHealth <= 0) return; + + int nextHealth = Mathf.Clamp(playerHealth.CurrentHealth + amount, 0, maxHealth); + if (nextHealth == playerHealth.CurrentHealth) return; + + playerHealth.CurrentHealth = nextHealth; + PublishPlayerHealthChanged(playerHealth); + } + + private static void RestorePlayerHealthToMax(HealthComponent playerHealth) + { + if (playerHealth.CurrentHealth <= 0) return; + + int maxHealth = playerHealth.MaxHealth; + if (maxHealth <= 0 || playerHealth.CurrentHealth >= maxHealth) return; + + playerHealth.CurrentHealth = maxHealth; + PublishPlayerHealthChanged(playerHealth); + } + + private static void PublishPlayerHealthChanged(HealthComponent playerHealth) + { + GameEntry.Event.Fire(null, + PlayerHealthChangeEventArgs.Create(0, playerHealth.CurrentHealth, playerHealth.MaxHealth)); + } + + private static void AddSelectedBuffToPlayer(PropConfig prop, int count) + { + Player player = FindPlayer(); + if (player == null) return; + + int applyCount = Mathf.Clamp(count, 1, 99); + for (int i = 0; i < applyCount; i++) + { + player.AddProp(new PropItem(prop)); + } + } + + private void HandleCornerTapGesture() + { + if (!TryGetTouchReleased(out Vector2 touchPosition)) return; + if (touchPosition.x > 80f || touchPosition.y < Screen.height - 80f) return; + + float now = Time.unscaledTime; + if (now - _lastCornerTapTime > CornerTapWindow) + { + _cornerTapCount = 0; + } + + _lastCornerTapTime = now; + _cornerTapCount++; + + if (_cornerTapCount >= RequiredCornerTapCount) + { + _cornerTapCount = 0; + _isPanelVisible = !_isPanelVisible; + } + } + + private static bool IsTogglePressed() + { +#if ENABLE_INPUT_SYSTEM + Keyboard keyboard = Keyboard.current; + if (keyboard == null) return false; + return keyboard.backquoteKey.wasPressedThisFrame || keyboard.f8Key.wasPressedThisFrame; +#else + return Input.GetKeyDown(KeyCode.BackQuote) || Input.GetKeyDown(KeyCode.F8); +#endif + } + + private static bool TryGetTouchReleased(out Vector2 touchPosition) + { +#if ENABLE_INPUT_SYSTEM + Touchscreen touchscreen = Touchscreen.current; + if (touchscreen == null) + { + touchPosition = default; + return false; + } + + var touch = touchscreen.primaryTouch; + if (!touch.press.wasReleasedThisFrame) + { + touchPosition = default; + return false; + } + + touchPosition = touch.position.ReadValue(); + return true; +#else + if (Input.touchCount <= 0) + { + touchPosition = default; + return false; + } + + Touch touch = Input.GetTouch(0); + if (touch.phase != TouchPhase.Ended) + { + touchPosition = default; + return false; + } + + touchPosition = touch.position; + return true; +#endif + } + } +} diff --git a/Assets/GameMain/DebugPanel/RuntimeDebugPanelComponent.cs.meta b/Assets/GameMain/Scripts/Procedure/DebugPanel/RuntimeDebugPanelComponent.cs.meta similarity index 100% rename from Assets/GameMain/DebugPanel/RuntimeDebugPanelComponent.cs.meta rename to Assets/GameMain/Scripts/Procedure/DebugPanel/RuntimeDebugPanelComponent.cs.meta diff --git a/Assets/GameMain/Scripts/Procedure/Game/GameStateBattle.cs b/Assets/GameMain/Scripts/Procedure/Game/GameStateBattle.cs index 82e020c..832ecd5 100644 --- a/Assets/GameMain/Scripts/Procedure/Game/GameStateBattle.cs +++ b/Assets/GameMain/Scripts/Procedure/Game/GameStateBattle.cs @@ -49,7 +49,7 @@ namespace SepCore.Procedure _levelTimerHandle = GameEntry.Timer.ScheduleOnce(levelConfig.Duration, OnLevelTimeUp, this); _enemyManager.OnInit(levelConfig, Player); - if (Player != null) Player.Enable = true; + Player.Enable = true; if (Application.isMobilePlatform) { @@ -61,12 +61,8 @@ namespace SepCore.Procedure { _enemyManager.OnUpdate(elapseSeconds, realElapseSeconds); - SimulationWorld simulationWorld = GameEntry.SimulationWorld; - if (simulationWorld != null) - { - Vector3 playerPosition = Player != null ? Player.CachedTransform.position : Vector3.zero; - simulationWorld.Tick(new SimulationTickContext(elapseSeconds, realElapseSeconds, playerPosition)); - } + Vector3 playerPosition = Player.CachedTransform.position; + GameEntry.SimulationWorld.Tick(new SimulationTickContext(elapseSeconds, realElapseSeconds, playerPosition)); int timeLeft = Mathf.Max(0, (int)GameEntry.Timer.GetRemainingTime(_levelTimerHandle)); GameEntry.Event.Fire(this, LevelProcessEventArgs.Create(timeLeft)); diff --git a/Assets/GameMain/Scripts/Procedure/SepCore.Procedure.asmdef b/Assets/GameMain/Scripts/Procedure/SepCore.Procedure.asmdef index 41bdb46..e723ecb 100644 --- a/Assets/GameMain/Scripts/Procedure/SepCore.Procedure.asmdef +++ b/Assets/GameMain/Scripts/Procedure/SepCore.Procedure.asmdef @@ -8,7 +8,8 @@ "GUID:47a82ffa13c291447ab895cd0bc251cd", "GUID:436e23dbdc31e7d4fb5c3f804548b2df", "GUID:0e1d182005e0ae647ab3fa40f5492dbb", - "GUID:3bb549212964b4192b427888ac9382e7" + "GUID:3bb549212964b4192b427888ac9382e7", + "GUID:75469ad4d38634e559750d17036d5f7c" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/Assets/GameMain/Scripts/Runtime/BuiltinComponent/AsyncTask/EntityAsyncExtension.cs b/Assets/GameMain/Scripts/Runtime/BuiltinComponent/AsyncTask/EntityAsyncExtension.cs index ee3398a..473497f 100644 --- a/Assets/GameMain/Scripts/Runtime/BuiltinComponent/AsyncTask/EntityAsyncExtension.cs +++ b/Assets/GameMain/Scripts/Runtime/BuiltinComponent/AsyncTask/EntityAsyncExtension.cs @@ -167,7 +167,7 @@ namespace SepCore.AsyncTask return entityComponent.ShowEntityAsync( data.Id, enemyType, AssetUtility.GetEntityAsset(entityConfig.PrefabPath), "Enemy", Constant.AssetPriority.EnemyAsset, data, timeout, cancellationToken) - .ContinueWith(entity => entity?.Logic as EnemyBase); + .ContinueWith(entity => entity.Logic as EnemyBase); } /// @@ -184,7 +184,7 @@ namespace SepCore.AsyncTask return entityComponent.ShowEntityAsync( data.Id, weaponType, AssetUtility.GetEntityAsset(entityConfig.PrefabPath), "Weapon", Constant.AssetPriority.WeaponAsset, data, timeout, cancellationToken) - .ContinueWith(entity => entity?.Logic as WeaponBase); + .ContinueWith(entity => entity.Logic as WeaponBase); } /// diff --git a/Assets/GameMain/Scripts/Runtime/CustomComponent/CameraModule/CameraModuleComponent.cs b/Assets/GameMain/Scripts/Runtime/CustomComponent/CameraModule/CameraModuleComponent.cs index 1460d55..aceb615 100644 --- a/Assets/GameMain/Scripts/Runtime/CustomComponent/CameraModule/CameraModuleComponent.cs +++ b/Assets/GameMain/Scripts/Runtime/CustomComponent/CameraModule/CameraModuleComponent.cs @@ -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(true); - if (_cinemachineController == null) - { -#if UNITY_2023_1_OR_NEWER - _cinemachineController = FindFirstObjectByType(FindObjectsInactive.Include); -#else - _cinemachineController = FindObjectOfType(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; } } } diff --git a/Assets/GameMain/Scripts/Runtime/CustomComponent/DamageText/DamageTextComponent.cs b/Assets/GameMain/Scripts/Runtime/CustomComponent/DamageText/DamageTextComponent.cs index e7cbdaf..91bef96 100644 --- a/Assets/GameMain/Scripts/Runtime/CustomComponent/DamageText/DamageTextComponent.cs +++ b/Assets/GameMain/Scripts/Runtime/CustomComponent/DamageText/DamageTextComponent.cs @@ -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 _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; } } } diff --git a/Assets/GameMain/Scripts/Runtime/CustomComponent/DamageText/DamageTextItem.cs b/Assets/GameMain/Scripts/Runtime/CustomComponent/DamageText/DamageTextItem.cs index 2f1d08a..fad4e53 100644 --- a/Assets/GameMain/Scripts/Runtime/CustomComponent/DamageText/DamageTextItem.cs +++ b/Assets/GameMain/Scripts/Runtime/CustomComponent/DamageText/DamageTextItem.cs @@ -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 _onComplete; - private void Awake() - { - if (_cachedTransform == null) _cachedTransform = GetComponent(); - if (_canvasGroup == null) _canvasGroup = GetComponent(); - if (_text == null) _text = GetComponent(); - } - public void Show(Vector3 worldPosition, int damage, Canvas canvas, Action 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; } diff --git a/Assets/GameMain/Scripts/Runtime/CustomComponent/EnemyManager/EnemyManagerComponent.cs b/Assets/GameMain/Scripts/Runtime/CustomComponent/EnemyManager/EnemyManagerComponent.cs index a3c2062..0ab45c6 100644 --- a/Assets/GameMain/Scripts/Runtime/CustomComponent/EnemyManager/EnemyManagerComponent.cs +++ b/Assets/GameMain/Scripts/Runtime/CustomComponent/EnemyManager/EnemyManagerComponent.cs @@ -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 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); } diff --git a/Assets/GameMain/Scripts/Runtime/CustomComponent/HPBar/HPBarComponent.cs b/Assets/GameMain/Scripts/Runtime/CustomComponent/HPBar/HPBarComponent.cs index 0e7fc47..2de0a20 100644 --- a/Assets/GameMain/Scripts/Runtime/CustomComponent/HPBar/HPBarComponent.cs +++ b/Assets/GameMain/Scripts/Runtime/CustomComponent/HPBar/HPBarComponent.cs @@ -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(); _hpBarItemObjectPool = GameEntry.ObjectPool.CreateSingleSpawnObjectPool("HPBarItem", _instancePoolCapacity); _activeHPBarItems = new List(); } - 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 = hpBarItem.transform; transform.SetParent(_hpBarInstanceRoot); transform.localScale = Vector3.one; _hpBarItemObjectPool.Register(HPBarItemObject.Create(hpBarItem), true); diff --git a/Assets/GameMain/Scripts/Runtime/CustomComponent/HPBar/HPBarItem.cs b/Assets/GameMain/Scripts/Runtime/CustomComponent/HPBar/HPBarItem.cs index 855c408..d261803 100644 --- a/Assets/GameMain/Scripts/Runtime/CustomComponent/HPBar/HPBarItem.cs +++ b/Assets/GameMain/Scripts/Runtime/CustomComponent/HPBar/HPBarItem.cs @@ -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(); - if (_cachedTransform == null) - { - Log.Error("RectTransform is invalid."); - return; - } - _cachedCanvasGroup = GetComponent(); - 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); } diff --git a/Assets/GameMain/Scripts/Runtime/CustomComponent/UIRouterComponent.cs b/Assets/GameMain/Scripts/Runtime/CustomComponent/UIRouterComponent.cs index 68822d1..8922788 100644 --- a/Assets/GameMain/Scripts/Runtime/CustomComponent/UIRouterComponent.cs +++ b/Assets/GameMain/Scripts/Runtime/CustomComponent/UIRouterComponent.cs @@ -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 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; } diff --git a/Assets/GameMain/Scripts/Runtime/EntityLogic/Enemy/EnemyBase.cs b/Assets/GameMain/Scripts/Runtime/EntityLogic/Enemy/EnemyBase.cs index 6e4d833..3a5f5ea 100644 --- a/Assets/GameMain/Scripts/Runtime/EntityLogic/Enemy/EnemyBase.cs +++ b/Assets/GameMain/Scripts/Runtime/EntityLogic/Enemy/EnemyBase.cs @@ -77,12 +77,9 @@ public abstract class EnemyBase : TargetableObject CachedTransform.localScale = Vector3.one * Mathf.Max(0.1f, data.Scale); var renderer = GetComponentInChildren(); - if (renderer != null) - { - var block = new MaterialPropertyBlock(); - block.SetColor("_BaseColor", data.Color); - renderer.SetPropertyBlock(block); - } + var block = new MaterialPropertyBlock(); + block.SetColor("_BaseColor", data.Color); + renderer.SetPropertyBlock(block); } } diff --git a/Assets/GameMain/Scripts/Runtime/Utility/EntityDataFactory.cs b/Assets/GameMain/Scripts/Runtime/Utility/EntityDataFactory.cs index 0482c28..42fecae 100644 --- a/Assets/GameMain/Scripts/Runtime/Utility/EntityDataFactory.cs +++ b/Assets/GameMain/Scripts/Runtime/Utility/EntityDataFactory.cs @@ -27,7 +27,7 @@ namespace SepCore.CustomUtility WeaponType.Axe => new WeaponSlashData(entityId, config, ownerId, ownerCamp), WeaponType.Lightning => new WeaponLightningData(entityId, config, ownerId, ownerCamp), WeaponType.Lance => new WeaponLanceData(entityId, config, ownerId, ownerCamp), - _ => throw new NotImplementedException() + _ => throw new NotImplementedException($"Unsupported weapon type '{weaponType}'.") }; } diff --git a/Assets/Launcher.unity b/Assets/Launcher.unity index 72bde22..a4d3075 100644 --- a/Assets/Launcher.unity +++ b/Assets/Launcher.unity @@ -338,30 +338,6 @@ MonoBehaviour: m_PointerBehavior: 0 m_CursorLockBehavior: 0 m_ScrollDeltaPerTick: 6 ---- !u!114 &142428270 stripped -MonoBehaviour: - m_CorrespondingSourceObject: {fileID: 6269556444878685483, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - m_PrefabInstance: {fileID: 1280276266} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 2efdcd06cdaa830448f76b22ea7c98fb, type: 3} - m_Name: - m_EditorClassIdentifier: ---- !u!114 &142428271 stripped -MonoBehaviour: - m_CorrespondingSourceObject: {fileID: 400612800417406683, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - m_PrefabInstance: {fileID: 1280276266} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fbaa237e23f7d4d3f85f73e0acd7eaec, type: 3} - m_Name: - m_EditorClassIdentifier: --- !u!1001 &343730742 PrefabInstance: m_ObjectHideFlags: 0 @@ -841,30 +817,6 @@ MonoBehaviour: _showPlayerWeaponControls: 1 _showPlayerHealthControls: 1 _showTips: 0 ---- !u!114 &491542084 stripped -MonoBehaviour: - m_CorrespondingSourceObject: {fileID: 6053195524865570449, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - m_PrefabInstance: {fileID: 1280276266} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: a5079836f95c2a44b96fa331487ebb70, type: 3} - m_Name: - m_EditorClassIdentifier: ---- !u!114 &491542086 stripped -MonoBehaviour: - m_CorrespondingSourceObject: {fileID: 227536339921118688, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - m_PrefabInstance: {fileID: 1280276266} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fbaa237e23f7d4d3f85f73e0acd7eaec, type: 3} - m_Name: - m_EditorClassIdentifier: --- !u!1 &513208572 GameObject: m_ObjectHideFlags: 0 @@ -960,9 +912,10 @@ MonoBehaviour: m_EditorClassIdentifier: _instancePoolCapacity: 256 _poolName: DamageTextItem - _instanceRoot: {fileID: 0} - _canvas: {fileID: 0} - _damageTextItemPrefab: {fileID: 0} + _instanceRoot: {fileID: 31248797} + _canvas: {fileID: 31248799} + _damageTextItemPrefab: {fileID: 8729657611800212236, guid: 308577c72eb4cd14ca676aeee62b0ea5, + type: 3} --- !u!1 &553656361 GameObject: m_ObjectHideFlags: 0 @@ -993,8 +946,7 @@ RectTransform: m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 0, y: 0, z: 0} m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 1280276267} + m_Children: [] m_Father: {fileID: 432952642} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} @@ -1065,54 +1017,6 @@ Canvas: m_SortingLayerID: 0 m_SortingOrder: 0 m_TargetDisplay: 0 ---- !u!114 &640014055 stripped -MonoBehaviour: - m_CorrespondingSourceObject: {fileID: 103163210424128144, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - m_PrefabInstance: {fileID: 1280276266} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} - m_Name: - m_EditorClassIdentifier: ---- !u!114 &640014059 stripped -MonoBehaviour: - m_CorrespondingSourceObject: {fileID: 8559108892240801629, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - m_PrefabInstance: {fileID: 1280276266} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fbaa237e23f7d4d3f85f73e0acd7eaec, type: 3} - m_Name: - m_EditorClassIdentifier: ---- !u!114 &652305783 stripped -MonoBehaviour: - m_CorrespondingSourceObject: {fileID: 6102478747521363808, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - m_PrefabInstance: {fileID: 1280276266} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} - m_Name: - m_EditorClassIdentifier: ---- !u!114 &652305787 stripped -MonoBehaviour: - m_CorrespondingSourceObject: {fileID: 3868237545351061730, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - m_PrefabInstance: {fileID: 1280276266} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fbaa237e23f7d4d3f85f73e0acd7eaec, type: 3} - m_Name: - m_EditorClassIdentifier: --- !u!850595691 &819759088 LightingSettings: m_ObjectHideFlags: 0 @@ -1223,8 +1127,6 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: _cinemachineController: {fileID: 2103467908} - _autoSearchController: 0 - _logMissingControllerWarnings: 1 --- !u!1 &1245211030 GameObject: m_ObjectHideFlags: 0 @@ -1275,337 +1177,6 @@ MonoBehaviour: _loadBindingOverridesOnInit: 1 _saveBindingOverridesOnDestroy: 0 _bindingOverrideSettingKey: SepCore.InputModule.BindingOverrides ---- !u!114 &1258981242 stripped -MonoBehaviour: - m_CorrespondingSourceObject: {fileID: 7330401870143477410, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - m_PrefabInstance: {fileID: 1280276266} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} - m_Name: - m_EditorClassIdentifier: ---- !u!114 &1258981246 stripped -MonoBehaviour: - m_CorrespondingSourceObject: {fileID: 249520213934040151, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - m_PrefabInstance: {fileID: 1280276266} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fbaa237e23f7d4d3f85f73e0acd7eaec, type: 3} - m_Name: - m_EditorClassIdentifier: ---- !u!1001 &1280276266 -PrefabInstance: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_Modification: - serializedVersion: 3 - m_TransformParent: {fileID: 553656362} - m_Modifications: - - target: {fileID: 395929355422612576, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: m_Name - value: ItemTooltipForm - objectReference: {fileID: 0} - - target: {fileID: 2236042990348165862, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: serializationItems.Array.size - value: 8 - objectReference: {fileID: 0} - - target: {fileID: 2236042990348165862, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: serializationItems.Array.data[0] - value: - objectReference: {fileID: 1280276276} - - target: {fileID: 2236042990348165862, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: serializationItems.Array.data[1] - value: - objectReference: {fileID: 1280276273} - - target: {fileID: 2236042990348165862, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: serializationItems.Array.data[2] - value: - objectReference: {fileID: 640014059} - - target: {fileID: 2236042990348165862, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: serializationItems.Array.data[3] - value: - objectReference: {fileID: 1258981246} - - target: {fileID: 2236042990348165862, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: serializationItems.Array.data[4] - value: - objectReference: {fileID: 652305787} - - target: {fileID: 2236042990348165862, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: serializationItems.Array.data[5] - value: - objectReference: {fileID: 1352570666} - - target: {fileID: 2236042990348165862, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: serializationItems.Array.data[6] - value: - objectReference: {fileID: 142428271} - - target: {fileID: 2236042990348165862, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: serializationItems.Array.data[7] - value: - objectReference: {fileID: 491542086} - - target: {fileID: 4303509830935515119, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: _view - value: - objectReference: {fileID: 1280276275} - - target: {fileID: 6368625289863409235, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: m_Pivot.x - value: 0.5 - objectReference: {fileID: 0} - - target: {fileID: 6368625289863409235, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: m_Pivot.y - value: 0.5 - objectReference: {fileID: 0} - - target: {fileID: 6368625289863409235, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: m_AnchorMax.x - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 6368625289863409235, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: m_AnchorMax.y - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 6368625289863409235, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: m_AnchorMin.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 6368625289863409235, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: m_AnchorMin.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 6368625289863409235, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: m_SizeDelta.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 6368625289863409235, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: m_SizeDelta.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 6368625289863409235, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: m_LocalPosition.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 6368625289863409235, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: m_LocalPosition.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 6368625289863409235, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: m_LocalPosition.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 6368625289863409235, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: m_LocalRotation.w - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 6368625289863409235, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: m_LocalRotation.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 6368625289863409235, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: m_LocalRotation.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 6368625289863409235, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: m_LocalRotation.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 6368625289863409235, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: m_AnchoredPosition.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 6368625289863409235, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: m_AnchoredPosition.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 6368625289863409235, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: m_LocalEulerAnglesHint.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 6368625289863409235, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: m_LocalEulerAnglesHint.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 6368625289863409235, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - propertyPath: m_LocalEulerAnglesHint.z - value: 0 - objectReference: {fileID: 0} - m_RemovedComponents: [] - m_RemovedGameObjects: [] - m_AddedGameObjects: [] - m_AddedComponents: - - targetCorrespondingSourceObject: {fileID: 395929355422612576, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - insertIndex: -1 - addedObject: {fileID: 1280276275} - - targetCorrespondingSourceObject: {fileID: 625540161254782982, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - insertIndex: -1 - addedObject: {fileID: 1280276276} - m_SourcePrefab: {fileID: 100100000, guid: 20e5dc75d1c3fe74bb841127a036d69d, type: 3} ---- !u!224 &1280276267 stripped -RectTransform: - m_CorrespondingSourceObject: {fileID: 6368625289863409235, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - m_PrefabInstance: {fileID: 1280276266} - m_PrefabAsset: {fileID: 0} ---- !u!114 &1280276268 stripped -MonoBehaviour: - m_CorrespondingSourceObject: {fileID: 7488000213460330546, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - m_PrefabInstance: {fileID: 1280276266} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 578fa91d15f54e74a95ccce338d0a772, type: 3} - m_Name: - m_EditorClassIdentifier: ---- !u!224 &1280276269 stripped -RectTransform: - m_CorrespondingSourceObject: {fileID: 7543853000780573685, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - m_PrefabInstance: {fileID: 1280276266} - m_PrefabAsset: {fileID: 0} ---- !u!1 &1280276270 stripped -GameObject: - m_CorrespondingSourceObject: {fileID: 625540161254782982, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - m_PrefabInstance: {fileID: 1280276266} - m_PrefabAsset: {fileID: 0} ---- !u!114 &1280276271 stripped -MonoBehaviour: - m_CorrespondingSourceObject: {fileID: 1280310065211852598, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - m_PrefabInstance: {fileID: 1280276266} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1280276270} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: ---- !u!1 &1280276272 stripped -GameObject: - m_CorrespondingSourceObject: {fileID: 395929355422612576, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - m_PrefabInstance: {fileID: 1280276266} - m_PrefabAsset: {fileID: 0} ---- !u!114 &1280276273 stripped -MonoBehaviour: - m_CorrespondingSourceObject: {fileID: 8926258706962002499, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - m_PrefabInstance: {fileID: 1280276266} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fbaa237e23f7d4d3f85f73e0acd7eaec, type: 3} - m_Name: - m_EditorClassIdentifier: ---- !u!222 &1280276274 stripped -CanvasRenderer: - m_CorrespondingSourceObject: {fileID: 3996340794476105959, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - m_PrefabInstance: {fileID: 1280276266} - m_PrefabAsset: {fileID: 0} ---- !u!114 &1280276275 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1280276272} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4d9524b70efb9c840a84baed8b0c12d0, type: 3} - m_Name: - m_EditorClassIdentifier: - iconArea: {fileID: 1280276268} - titleText: {fileID: 640014055} - typeText: {fileID: 1258981242} - infoText: {fileID: 652305783} - recycleButton: {fileID: 1352570662} - textFormatText: {fileID: 142428270} - cancelButton: {fileID: 491542084} ---- !u!114 &1280276276 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1280276270} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fbaa237e23f7d4d3f85f73e0acd7eaec, type: 3} - m_Name: - m_EditorClassIdentifier: - componentReferences: - - component: {fileID: 1280276269} - generateReference: 1 - variableName: contentRectTransform - - component: {fileID: 1280276274} - generateReference: 0 - variableName: contentCanvasRenderer - - component: {fileID: 1280276271} - generateReference: 0 - variableName: contentImage ---- !u!114 &1352570662 stripped -MonoBehaviour: - m_CorrespondingSourceObject: {fileID: 7966632555814587605, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - m_PrefabInstance: {fileID: 1280276266} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: a5079836f95c2a44b96fa331487ebb70, type: 3} - m_Name: - m_EditorClassIdentifier: ---- !u!114 &1352570666 stripped -MonoBehaviour: - m_CorrespondingSourceObject: {fileID: 5617935853479120081, guid: 20e5dc75d1c3fe74bb841127a036d69d, - type: 3} - m_PrefabInstance: {fileID: 1280276266} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fbaa237e23f7d4d3f85f73e0acd7eaec, type: 3} - m_Name: - m_EditorClassIdentifier: --- !u!1 &1454214586 GameObject: m_ObjectHideFlags: 0 @@ -1984,8 +1555,6 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8d840df1b53db744cb522b82426f2cd5, type: 3} m_Name: m_EditorClassIdentifier: - _spawnEnemyMaxCount: 5000 - _spawnDistanceFromPlayer: 20 --- !u!1 &2050832066 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Plugins/InputModule/Runtime/InputModuleComponent.cs b/Assets/Plugins/InputModule/Runtime/InputModuleComponent.cs index 126648c..11a7b16 100644 --- a/Assets/Plugins/InputModule/Runtime/InputModuleComponent.cs +++ b/Assets/Plugins/InputModule/Runtime/InputModuleComponent.cs @@ -30,7 +30,6 @@ namespace SepCore.InputModule.Runtime private SettingComponent _settingComponent = null; private bool _isInitialized = false; private bool _onInitCalled = false; - private bool _ownsRuntimeActions = false; private InputActionRebindingExtensions.RebindingOperation _activeRebindOperation; private bool _rebindCanceledByUser; private IInputPromptMap _promptMap; @@ -75,11 +74,6 @@ namespace SepCore.InputModule.Runtime } } - protected override void Awake() - { - base.Awake(); - } - private void OnEnable() { if (_isInitialized) @@ -112,29 +106,21 @@ namespace SepCore.InputModule.Runtime UnsubscribeFromGlobalDeviceTracking(); UnsubscribeFromActions(); - if (_ownsRuntimeActions && _runtimeActions != null) + if (Application.isPlaying) { - if (Application.isPlaying) - { - Destroy(_runtimeActions); - } - else - { - DestroyImmediate(_runtimeActions); - } + Destroy(_runtimeActions); + } + else + { + DestroyImmediate(_runtimeActions); } - - _runtimeActions = null; - _actionMaps.Clear(); - _listeners.Clear(); - _isInitialized = false; - _onInitCalled = false; } public void RegisterListener(InputActionId actionId, Action listener) { if (listener == null) { + Log.Error("InputModuleComponent.RegisterListener() listener is invalid."); return; } @@ -160,7 +146,7 @@ namespace SepCore.InputModule.Runtime if (_listeners.TryGetValue(command.ActionId, out Action listener)) { - listener?.Invoke(command); + listener.Invoke(command); } } @@ -343,11 +329,14 @@ namespace SepCore.InputModule.Runtime EnsureInitialized(); if (!TryGetAction(contextId, actionId, out InputAction action)) { + Log.Error("InputModuleComponent.ResetBindingToDefault() action '{0}' is not found in context '{1}'.", + actionId, contextId); return; } if (bindingIndex < 0 || bindingIndex >= action.bindings.Count) { + Log.Error("InputModuleComponent.ResetBindingToDefault() binding index '{0}' is invalid.", bindingIndex); return; } @@ -364,6 +353,8 @@ namespace SepCore.InputModule.Runtime EnsureInitialized(); if (!TryGetAction(contextId, actionId, out InputAction action)) { + Log.Error("InputModuleComponent.ResetActionToDefaults() action '{0}' is not found in context '{1}'.", + actionId, contextId); return; } @@ -392,11 +383,7 @@ namespace SepCore.InputModule.Runtime string overridesJson = _runtimeActions.SaveBindingOverridesAsJson(); string storedData = BindingOverridePersistence.Serialize(overridesJson); - SettingComponent settingComponent = GetSettingComponent(); - if (settingComponent != null) - { - settingComponent.SetString(_bindingOverrideSettingKey, storedData); - } + GetSettingComponent().SetString(_bindingOverrideSettingKey, storedData); return new InputBindingSnapshot(overridesJson); } @@ -409,13 +396,8 @@ namespace SepCore.InputModule.Runtime private void LoadBindingOverridesCore() { - if (_runtimeActions == null) - { - return; - } - SettingComponent settingComponent = GetSettingComponent(); - if (settingComponent == null || !settingComponent.HasSetting(_bindingOverrideSettingKey)) + if (!settingComponent.HasSetting(_bindingOverrideSettingKey)) { return; } @@ -423,6 +405,7 @@ namespace SepCore.InputModule.Runtime string storedData = settingComponent.GetString(_bindingOverrideSettingKey); if (!BindingOverridePersistence.TryDeserialize(storedData, out string overridesJson)) { + Log.Error("InputModuleComponent failed to deserialize stored binding overrides."); return; } @@ -455,7 +438,6 @@ namespace SepCore.InputModule.Runtime _runtimeActions = _inputActionsAsset != null ? Instantiate(_inputActionsAsset) : InputModuleDefaultActions.Create(); - _ownsRuntimeActions = true; CacheActionMaps(); SubscribeToActions(); @@ -470,7 +452,7 @@ namespace SepCore.InputModule.Runtime int mapCount = _actionMaps.Count; if (mapCount == 0) { - Log.Warning("[InputModule] Initialized but no action maps were cached. Check that action map names match InputContextId enum values."); + Log.Error("[InputModule] Initialized but no action maps were cached. Check that action map names match InputContextId enum values."); } else { @@ -504,7 +486,7 @@ namespace SepCore.InputModule.Runtime } else { - Log.Warning("[InputModule] ActionMap '{0}' does not match any InputContextId and will be ignored.", map.name); + Log.Error("[InputModule] ActionMap '{0}' does not match any InputContextId and will be ignored.", map.name); } } } @@ -521,11 +503,6 @@ namespace SepCore.InputModule.Runtime private void UnsubscribeFromActions() { - if (_runtimeActions == null) - { - return; - } - foreach (InputAction action in _runtimeActions) { action.started -= OnActionTriggered; @@ -559,11 +536,6 @@ namespace SepCore.InputModule.Runtime // context is active at any time, preventing overlapping bindings from stacked maps. private void ApplyContextState() { - if (_runtimeActions == null) - { - return; - } - _runtimeActions.Disable(); if (_actionMaps.TryGetValue(InputContextId.Global, out InputActionMap globalMap)) @@ -600,7 +572,7 @@ namespace SepCore.InputModule.Runtime if (_listeners.TryGetValue(actionId, out Action listener)) { - listener?.Invoke(command); + listener.Invoke(command); } } @@ -725,7 +697,7 @@ namespace SepCore.InputModule.Runtime continue; } - if (string.Equals(binding.effectivePath, newPath, System.StringComparison.OrdinalIgnoreCase)) + if (string.Equals(binding.effectivePath, newPath, StringComparison.OrdinalIgnoreCase)) { return true; } diff --git a/Assets/Plugins/InputModule/Tests/PlayMode/InputModule/InputModuleComponentContextTests.cs b/Assets/Plugins/InputModule/Tests/PlayMode/InputModule/InputModuleComponentContextTests.cs index bbba851..e40a508 100644 --- a/Assets/Plugins/InputModule/Tests/PlayMode/InputModule/InputModuleComponentContextTests.cs +++ b/Assets/Plugins/InputModule/Tests/PlayMode/InputModule/InputModuleComponentContextTests.cs @@ -16,7 +16,7 @@ namespace SepCore.InputModule.Tests public void SetUp() { _gameObject = new GameObject("InputModuleTest"); - _component = _gameObject.AddComponent(); + _component = InputModuleTestFactory.CreateComponent(_gameObject); } [TearDown] diff --git a/Assets/Plugins/InputModule/Tests/PlayMode/InputModule/InputModuleComponentEventTests.cs b/Assets/Plugins/InputModule/Tests/PlayMode/InputModule/InputModuleComponentEventTests.cs index 8cd7859..f4d2f7e 100644 --- a/Assets/Plugins/InputModule/Tests/PlayMode/InputModule/InputModuleComponentEventTests.cs +++ b/Assets/Plugins/InputModule/Tests/PlayMode/InputModule/InputModuleComponentEventTests.cs @@ -17,7 +17,7 @@ namespace SepCore.InputModule.Tests public void SetUp() { _gameObject = new GameObject("InputModuleEventTest"); - _component = _gameObject.AddComponent(); + _component = InputModuleTestFactory.CreateComponent(_gameObject); _component.OnInit(); } @@ -185,6 +185,9 @@ namespace SepCore.InputModule.Tests public void RegisterListener_NullCallback_DoesNotThrow() { Assert.DoesNotThrow(() => _component.RegisterListener(InputActionId.Pause, null)); + + Dictionary> listeners = GetPrivateListenersDictionary(); + Assert.That(listeners.ContainsKey(InputActionId.Pause), Is.False); } [Test] diff --git a/Assets/Plugins/InputModule/Tests/PlayMode/InputModule/InputModuleComponentRebindTests.cs b/Assets/Plugins/InputModule/Tests/PlayMode/InputModule/InputModuleComponentRebindTests.cs index cca51af..e0b66b2 100644 --- a/Assets/Plugins/InputModule/Tests/PlayMode/InputModule/InputModuleComponentRebindTests.cs +++ b/Assets/Plugins/InputModule/Tests/PlayMode/InputModule/InputModuleComponentRebindTests.cs @@ -17,7 +17,7 @@ namespace SepCore.InputModule.Tests { base.Setup(); _gameObject = new GameObject("InputModuleRebindTest"); - _component = _gameObject.AddComponent(); + _component = InputModuleTestFactory.CreateComponent(_gameObject); _component.OnInit(); } @@ -202,7 +202,8 @@ namespace SepCore.InputModule.Tests InputAction confirmAction = _component.RuntimeActions.FindAction($"{nameof(InputContextId.UI)}/{nameof(InputActionId.Confirm)}"); confirmAction.ApplyBindingOverride(0, "/space"); - InputBindingSnapshot snapshot = _component.SaveBindingOverrides(); + string overridesJson = _component.RuntimeActions.SaveBindingOverridesAsJson(); + InputBindingSnapshot snapshot = new InputBindingSnapshot(overridesJson); _component.ResetAllBindingsToDefaults(); Assert.That(confirmAction.bindings[0].overridePath, Is.Null); diff --git a/Assets/Plugins/InputModule/Tests/PlayMode/InputModule/InputModuleDebuggerReflectionTests.cs b/Assets/Plugins/InputModule/Tests/PlayMode/InputModule/InputModuleDebuggerReflectionTests.cs index eab44fe..96b2214 100644 --- a/Assets/Plugins/InputModule/Tests/PlayMode/InputModule/InputModuleDebuggerReflectionTests.cs +++ b/Assets/Plugins/InputModule/Tests/PlayMode/InputModule/InputModuleDebuggerReflectionTests.cs @@ -17,7 +17,7 @@ namespace SepCore.InputModule.Tests public void SetUp() { _gameObject = new GameObject("InputModuleDebuggerReflectionTest"); - _component = _gameObject.AddComponent(); + _component = InputModuleTestFactory.CreateComponent(_gameObject); } [TearDown] diff --git a/Assets/Plugins/InputModule/Tests/PlayMode/InputModule/InputModuleTestFactory.cs b/Assets/Plugins/InputModule/Tests/PlayMode/InputModule/InputModuleTestFactory.cs new file mode 100644 index 0000000..b305eb1 --- /dev/null +++ b/Assets/Plugins/InputModule/Tests/PlayMode/InputModule/InputModuleTestFactory.cs @@ -0,0 +1,18 @@ +using System.Reflection; +using SepCore.InputModule.Runtime; +using UnityEngine; + +namespace SepCore.InputModule.Tests +{ + internal static class InputModuleTestFactory + { + public static InputModuleComponent CreateComponent(GameObject gameObject) + { + InputModuleComponent component = gameObject.AddComponent(); + typeof(InputModuleComponent) + .GetField("_loadBindingOverridesOnInit", BindingFlags.Instance | BindingFlags.NonPublic) + .SetValue(component, false); + return component; + } + } +} diff --git a/Assets/Plugins/InputModule/Tests/PlayMode/InputModule/InputModuleTestFactory.cs.meta b/Assets/Plugins/InputModule/Tests/PlayMode/InputModule/InputModuleTestFactory.cs.meta new file mode 100644 index 0000000..acc8560 --- /dev/null +++ b/Assets/Plugins/InputModule/Tests/PlayMode/InputModule/InputModuleTestFactory.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1e4066e709bd03646a983938f9b9b525 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/TimerModule/Runtime/TimerComponent.cs b/Assets/Plugins/TimerModule/Runtime/TimerComponent.cs index 2cf1318..c8922ab 100644 --- a/Assets/Plugins/TimerModule/Runtime/TimerComponent.cs +++ b/Assets/Plugins/TimerModule/Runtime/TimerComponent.cs @@ -57,6 +57,7 @@ namespace SepCore.Timer if (timerTask.RepeatCount == 0) { + Log.Error("Timer task repeat count is zero."); return TimerHandle.Invalid; } @@ -139,6 +140,7 @@ namespace SepCore.Timer { if (owner == null) { + Log.Error("Timer task owner is invalid."); return 0; } @@ -248,6 +250,12 @@ namespace SepCore.Timer } float safeInterval = Mathf.Max(0f, newInterval); + if (taskInfo.IsRepeating && safeInterval <= 0f) + { + Log.Error("Timer task interval must be greater than zero for repeated tasks."); + return false; + } + if (adjustRemainingTime && taskInfo.Interval > 0f && safeInterval > 0f) { float ratio = safeInterval / taskInfo.Interval; @@ -443,11 +451,6 @@ namespace SepCore.Timer _isUpdating = true; for (int i = taskCount - 1; i >= 0; i--) { - if (i >= _timerTasks.Count) - { - continue; - } - TimerTaskInfo taskInfo = _timerTasks[i]; if (taskInfo.IsCancelled || taskInfo.IsPaused) { @@ -539,6 +542,7 @@ namespace SepCore.Timer RemainingTime = delay; Interval = interval; RemainingRepeatCount = repeatCount; + IsRepeating = repeatCount != 1; TimeMode = timeMode; Owner = owner; Callback = callback; @@ -569,6 +573,11 @@ namespace SepCore.Timer set; } + public bool IsRepeating + { + get; + } + public TimerTimeMode TimeMode { get; diff --git a/数据表/Datas/GlobalConfig_全局配置.xlsx b/数据表/Datas/GlobalConfig_全局配置.xlsx index b53e15a..9fff49a 100644 Binary files a/数据表/Datas/GlobalConfig_全局配置.xlsx and b/数据表/Datas/GlobalConfig_全局配置.xlsx differ