- 补充游戏核心逻辑
- 完成 TodOList P0
- 添加游戏内控制台便于调试
- 增加敌人互斥机制提高运算负载
- 优化互斥算法将游戏性能基准线拉到 1k 敌人
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user