From 17ee268416d93b53e65bff57e3456770634b7768 Mon Sep 17 00:00:00 2001 From: basil <2428390463@qq.com> Date: Mon, 14 Sep 2026 18:35:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B8=85=E7=90=86=E5=90=84=E4=B8=AA=20Componen?= =?UTF-8?q?t=20=E9=87=8C=E7=9A=84=E5=88=A4=E6=96=AD=E4=BB=A5=E5=8F=8A?= =?UTF-8?q?=E8=B0=83=E7=94=A8=E8=A7=84=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GameMain/DataTables/tbglobalconfig.bytes | Bin 14 -> 25 bytes .../GameMain/DataTables/tbglobalconfig.json | 7 +- .../DebugPanel/RuntimeDebugPanelComponent.cs | 580 ------------------ .../GameMain/Scripts/Base/Gen/GlobalConfig.cs | 33 +- .../Scripts/Base/Gen/TbGlobalConfig.cs | 20 +- .../{ => Scripts/Procedure}/DebugPanel.meta | 0 .../DebugPanel/RuntimeDebugPanelComponent.cs | 561 +++++++++++++++++ .../RuntimeDebugPanelComponent.cs.meta | 0 .../Scripts/Procedure/Game/GameStateBattle.cs | 10 +- .../Procedure/SepCore.Procedure.asmdef | 3 +- .../AsyncTask/EntityAsyncExtension.cs | 4 +- .../CameraModule/CameraModuleComponent.cs | 157 +---- .../DamageText/DamageTextComponent.cs | 12 +- .../DamageText/DamageTextItem.cs | 18 +- .../EnemyManager/EnemyManagerComponent.cs | 38 +- .../CustomComponent/HPBar/HPBarComponent.cs | 23 +- .../CustomComponent/HPBar/HPBarItem.cs | 27 +- .../CustomComponent/UIRouterComponent.cs | 20 +- .../Runtime/EntityLogic/Enemy/EnemyBase.cs | 9 +- .../Runtime/Utility/EntityDataFactory.cs | 2 +- Assets/Launcher.unity | 441 +------------ .../Runtime/InputModuleComponent.cs | 68 +- .../InputModuleComponentContextTests.cs | 2 +- .../InputModuleComponentEventTests.cs | 5 +- .../InputModuleComponentRebindTests.cs | 5 +- .../InputModuleDebuggerReflectionTests.cs | 2 +- .../InputModule/InputModuleTestFactory.cs | 18 + .../InputModuleTestFactory.cs.meta | 11 + .../TimerModule/Runtime/TimerComponent.cs | 19 +- 数据表/Datas/GlobalConfig_全局配置.xlsx | Bin 10047 -> 10455 bytes 30 files changed, 769 insertions(+), 1326 deletions(-) delete mode 100644 Assets/GameMain/DebugPanel/RuntimeDebugPanelComponent.cs rename Assets/GameMain/{ => Scripts/Procedure}/DebugPanel.meta (100%) create mode 100644 Assets/GameMain/Scripts/Procedure/DebugPanel/RuntimeDebugPanelComponent.cs rename Assets/GameMain/{ => Scripts/Procedure}/DebugPanel/RuntimeDebugPanelComponent.cs.meta (100%) create mode 100644 Assets/Plugins/InputModule/Tests/PlayMode/InputModule/InputModuleTestFactory.cs create mode 100644 Assets/Plugins/InputModule/Tests/PlayMode/InputModule/InputModuleTestFactory.cs.meta diff --git a/Assets/GameMain/DataTables/tbglobalconfig.bytes b/Assets/GameMain/DataTables/tbglobalconfig.bytes index 80bd62d12e4eb94d03f24b9c5c6063540b76e7b0..6135738f42b9b364aefa053eeb33bad056b790de 100644 GIT binary patch literal 25 fcmZQ%`|uwK8g*EV7?@aCUGq|ND<^jx@KXQ)k1+}< literal 14 TcmZQ%Yt&&eV)*bM2$)y^BFY8b 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 b53e15ae32121cfd0efacf0d8056b9df2b8a81d5..9fff49a9db86cdaa19855783a7bd339e25a63979 100644 GIT binary patch delta 5993 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 U$8-C49p!L5CRVgI@IT0Z0Z?f{IRF3v delta 5548 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 A;s5{u