- 补充游戏核心逻辑

- 完成 TodOList P0
    - 添加游戏内控制台便于调试
    - 增加敌人互斥机制提高运算负载
    - 优化互斥算法将游戏性能基准线拉到 1k 敌人
This commit is contained in:
SepComet
2026-02-20 18:08:27 +08:00
parent b4bc8b0445
commit 3742110e9a
196 changed files with 4868 additions and 31326 deletions
@@ -4,7 +4,8 @@ using System.Linq;
using DataTable;
using Definition.DataStruct;
using Entity;
using Game.Utility;
using CustomUtility;
using Procedure;
using UnityEngine;
using UnityGameFramework.Runtime;
#if ENABLE_INPUT_SYSTEM
@@ -41,7 +42,7 @@ namespace CustomComponent
protected override void Awake()
{
base.Awake();
_windowId = GetInstanceID();
}
@@ -105,6 +106,7 @@ namespace CustomComponent
{
EnsurePropList(true);
}
GUILayout.EndHorizontal();
ApplyFilter(_searchText);
@@ -135,12 +137,14 @@ namespace CustomComponent
{
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();
@@ -150,8 +154,15 @@ namespace CustomComponent
return;
}
if (procedure == null)
{
GUILayout.Label("ProcedureGame unavailable.");
return;
}
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}");
GUILayout.BeginHorizontal();
GUILayout.Label("Rate", GUILayout.Width(52f));
@@ -165,16 +176,19 @@ namespace CustomComponent
{
enemyManager.SetSpawnRateScale(_spawnRateScaleInput);
}
if (GUILayout.Button("x0.5", GUILayout.Width(60f)))
{
_spawnRateScaleInput = Mathf.Max(MinSpawnRate, enemyManager.SpawnRateScale * 0.5f);
enemyManager.SetSpawnRateScale(_spawnRateScaleInput);
}
if (GUILayout.Button("x2", GUILayout.Width(60f)))
{
_spawnRateScaleInput = enemyManager.SpawnRateScale * 2f;
enemyManager.SetSpawnRateScale(_spawnRateScaleInput);
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
@@ -187,21 +201,43 @@ namespace CustomComponent
if (GUILayout.Button("Extend Battle", GUILayout.Height(24f)))
{
enemyManager.AddBattleDuration(_extendDurationSeconds);
if (procedure.CurrentGameState is GameStateBattle gameState)
{
gameState.AddBattleDuration(_extendDurationSeconds);
}
}
GUILayout.EndHorizontal();
GUILayout.Label($"Player Weapon: {(player == null ? "Player not found" : (player.WeaponEnabled ? "Enabled" : "Disabled"))}");
GUILayout.Space(4f);
GUILayout.Label($"Enemy Separation Solver: {EnemySeparationSolverProvider.CurrentSolverName}");
GUILayout.BeginHorizontal();
if (GUILayout.Button("Use Naive O(N^2)", GUILayout.Height(24f)))
{
EnemySeparationSolverProvider.UseNaiveSolver();
}
if (GUILayout.Button("Use Grid Bucket", GUILayout.Height(24f)))
{
EnemySeparationSolverProvider.UseGridBucketSolver();
}
GUILayout.EndHorizontal();
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(24f)))
{
player.SetWeaponEnabled(false);
}
if (GUILayout.Button("Enable Weapons", GUILayout.Height(24f)))
{
player.SetWeaponEnabled(true);
}
GUI.enabled = true;
GUILayout.EndHorizontal();
}
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using DataTable;
using Definition.Enum;
using Entity;
using Entity.EntityData;
using GameFramework.Event;
@@ -22,20 +23,20 @@ namespace CustomComponent
public List<EntityBase> Enemies => _enemies;
private float _spawnEnemyTimer;
private int _spawnEnemyMaxCount = 5000;
[SerializeField] private int _spawnEnemyMaxCount = 5000;
private int _currentEnemyCount;
private int _spawnDistanceFromPlayer = 20;
[SerializeField] private int _spawnDistanceFromPlayer = 20;
private int _currentSpawnEnemyId;
private int _currentLevel;
private float[] _baseSpawnEnemyIntervals;
private float[] _spawnEnemyIntervals;
private int[] _spawnEnemyIds;
private EnemyType[] _spawnEnemyTypes;
private int[] _spawnEnemyCounts;
private float _duration;
private float _baseDuration;
@@ -45,11 +46,10 @@ namespace CustomComponent
private Transform _player;
private GameStateBattle _battle;
public float SpawnRateScale => _spawnRateScale;
public float BattleDuration => _duration;
public float ElapsedBattleTime => _spawnEnemyTimer;
public int CurrentEnemyCount => _currentEnemyCount;
#region FSM
@@ -71,22 +71,18 @@ namespace CustomComponent
_entity = null;
}
public void OnInit(int level, GameStateBattle battle)
public void OnInit(DRLevel level)
{
_battle = battle;
_currentLevel = level;
DRLevel levelData = GameEntry.DataTable.GetDataTableRow<DRLevel>(_currentLevel);
_baseSpawnEnemyIntervals = (float[])levelData.Intervals.Clone();
_baseSpawnEnemyIntervals = (float[])level.Intervals.Clone();
_spawnEnemyIntervals = (float[])_baseSpawnEnemyIntervals.Clone();
_spawnEnemyIds = levelData.EntityIds;
_spawnEnemyCounts = levelData.EntityCounts;
_baseDuration = levelData.Duration;
_spawnEnemyTypes = level.EntityTypes;
_spawnEnemyCounts = level.EntityCounts;
_baseDuration = level.Duration;
_duration = _baseDuration;
SetSpawnRateScale(_spawnRateScale);
_currentEnemyCount = 0;
_currentSpawnEnemyId = 0;
}
@@ -94,19 +90,13 @@ namespace CustomComponent
{
_spawnEnemyTimer += elapseSeconds;
if (_spawnEnemyTimer > _duration)
{
_battle.LevelOver();
return;
}
for (int i = 0; i < _nextSpawnTimes.Length; i++)
{
float nextSpawnTime = _nextSpawnTimes[i];
if (_spawnEnemyTimer < nextSpawnTime) continue;
for (int j = 0; j < _spawnEnemyCounts[i]; j++)
{
SpawnEnemy(_spawnEnemyIds[i]);
SpawnEnemy(_spawnEnemyTypes[i]);
}
_nextSpawnTimes[i] += _spawnEnemyIntervals[i];
@@ -115,24 +105,57 @@ namespace CustomComponent
public void OnReset()
{
_currentEnemyCount = 0;
_spawnEnemyTimer = 0;
_currentSpawnEnemyId = 0;
_currentLevel = 0;
_baseSpawnEnemyIntervals = null;
_spawnEnemyIntervals = null;
_spawnEnemyIds = null;
_spawnEnemyTypes = null;
_spawnEnemyCounts = null;
_baseDuration = 0;
_duration = 0;
_nextSpawnTimes = null;
_battle = null;
ClearEnemies();
_currentEnemyCount = 0;
}
#endregion
private void SpawnEnemy(EnemyType enemyType)
{
if (_player == null) return;
if (_currentEnemyCount >= _spawnEnemyMaxCount) return;
int entityPoolId = _currentSpawnEnemyId % _spawnEnemyMaxCount;
var enemyData = new EnemyData(entityPoolId, enemyType, _currentLevel)
{
Position = GetRandomPosition()
};
_entity.ShowEnemy(enemyData);
_currentSpawnEnemyId++;
}
private Vector3 GetRandomPosition()
{
float x = Random.Range(-1f, 1f);
float z = Random.Range(-1f, 1f);
Vector3 dir = new Vector3(x, 0, z).normalized;
return _player.position + dir * _spawnDistanceFromPlayer;
}
public void ClearEnemies()
{
foreach (var enemy in _enemies)
{
if (enemy == null || !enemy.Available) continue;
_entity.HideEntity(enemy);
}
_enemies.Clear();
}
public void SetSpawnRateScale(float scale)
@@ -174,53 +197,12 @@ namespace CustomComponent
}
}
public void AddBattleDuration(float seconds)
{
if (seconds <= 0f) return;
_duration += seconds;
}
private static float GetScaledInterval(float baseInterval, float scale)
{
float safeScale = Mathf.Max(MinSpawnRateScale, scale);
return baseInterval / safeScale;
}
#endregion
private void SpawnEnemy(int entityId)
{
if (_player == null) return;
if (_currentEnemyCount >= _spawnEnemyMaxCount) return;
int entityPoolId = _currentSpawnEnemyId % _spawnEnemyMaxCount;
var enemyData = new EnemyData(entityPoolId, entityId, _currentLevel)
{
Position = GetRandomPosition()
};
_entity.ShowEnemy(enemyData);
_currentSpawnEnemyId++;
}
private Vector3 GetRandomPosition()
{
float x = Random.Range(-1f, 1f);
float z = Random.Range(-1f, 1f);
Vector3 dir = new Vector3(x, 0, z).normalized;
return _player.position + dir * _spawnDistanceFromPlayer;
}
public void ClearEnemies()
{
foreach (var enemy in _enemies)
{
if (enemy == null || !enemy.Available) continue;
_entity.HideEntity(enemy);
}
_enemies.Clear();
}
#region Event Handler
private void OnShowEntitySuccess(object sender, GameEventArgs e)
@@ -253,4 +235,4 @@ namespace CustomComponent
#endregion
}
}
}