From 688fefe8485d57fddfff40fd49091bfef834b794 Mon Sep 17 00:00:00 2001 From: SepComet <202308010230@stu.csust.edu.cn> Date: Mon, 23 Feb 2026 11:21:35 +0800 Subject: [PATCH] fix 1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 修复投射物闪避口径(使用 Value,与全局伤害逻辑一致) - 将 SimulationWorld 内投射物伤害计算改为直接复用 AIUtility.CalcDamageHP(...)。 - 删除了 SimulationWorld 里那套重复且使用 dodgeStat.Percent 的私有计算函数,避免再次分叉。 2. 修复目标选择索引“重建过于激进” - 去掉了 Job Tick 末尾的“每帧强制 MarkDirty + Build”。 - 改为在 Job 输出回写时,只有敌人 XZ 坐标发生变化才标记 dirty。 - 空间索引构建条件改为“仅 dirty 时重建”,不再因跨帧自动重建。 --- .../Simulation/SimulationWorld.EnemyJobs.cs | 3 -- .../SimulationWorld.JobDataChannel.cs | 16 +++++++++- .../SimulationWorld.ProjectileJobs.cs | 32 +------------------ ...lationWorld.TargetSelectionSpatialIndex.cs | 8 +---- openspec/config.yaml | 20 ------------ 5 files changed, 17 insertions(+), 62 deletions(-) delete mode 100644 openspec/config.yaml diff --git a/Assets/GameMain/Scripts/Simulation/SimulationWorld.EnemyJobs.cs b/Assets/GameMain/Scripts/Simulation/SimulationWorld.EnemyJobs.cs index 3711363..8fbfee7 100644 --- a/Assets/GameMain/Scripts/Simulation/SimulationWorld.EnemyJobs.cs +++ b/Assets/GameMain/Scripts/Simulation/SimulationWorld.EnemyJobs.cs @@ -226,9 +226,6 @@ namespace Simulation RecycleInactiveProjectiles(); } } - - MarkEnemyTargetSpatialIndexDirty(); - BuildEnemyTargetSpatialIndexIfNeeded(); } private JobHandle ExecuteEnemyMovementJob(in SimulationTickContext context) diff --git a/Assets/GameMain/Scripts/Simulation/SimulationWorld.JobDataChannel.cs b/Assets/GameMain/Scripts/Simulation/SimulationWorld.JobDataChannel.cs index a4b9d32..53f2207 100644 --- a/Assets/GameMain/Scripts/Simulation/SimulationWorld.JobDataChannel.cs +++ b/Assets/GameMain/Scripts/Simulation/SimulationWorld.JobDataChannel.cs @@ -619,9 +619,23 @@ namespace Simulation private void ApplyJobOutputToSimulation() { int enemyCount = Mathf.Min(_enemies.Count, _enemyJobOutputs.Length); + bool hasEnemyPositionChanged = false; for (int i = 0; i < enemyCount; i++) { - _enemies[i] = ConvertToEnemySimData(_enemyJobOutputs[i]); + EnemyJobOutputData output = _enemyJobOutputs[i]; + if (!hasEnemyPositionChanged) + { + Vector3 currentPosition = _enemies[i].Position; + hasEnemyPositionChanged = currentPosition.x != output.Position.x || + currentPosition.z != output.Position.z; + } + + _enemies[i] = ConvertToEnemySimData(output); + } + + if (hasEnemyPositionChanged) + { + MarkEnemyTargetSpatialIndexDirty(); } int projectileCount = Mathf.Min(_projectiles.Count, _projectileJobOutputs.Length); diff --git a/Assets/GameMain/Scripts/Simulation/SimulationWorld.ProjectileJobs.cs b/Assets/GameMain/Scripts/Simulation/SimulationWorld.ProjectileJobs.cs index 8ec1748..d70d85b 100644 --- a/Assets/GameMain/Scripts/Simulation/SimulationWorld.ProjectileJobs.cs +++ b/Assets/GameMain/Scripts/Simulation/SimulationWorld.ProjectileJobs.cs @@ -453,7 +453,7 @@ namespace Simulation return false; } - damage = CalculateProjectileDamage(sourceImpact.AttackBase, sourceImpact.AttackStat, + damage = AIUtility.CalcDamageHP(sourceImpact.AttackBase, sourceImpact.AttackStat, targetImpact.DefenseStat, targetImpact.DodgeStat); shouldDispatchPresentation = true; @@ -537,36 +537,6 @@ namespace Simulation return false; } - private static int CalculateProjectileDamage(int attack, StatProperty attackStat, StatProperty defenseStat, - StatProperty dodgeStat) - { - if (dodgeStat != null) - { - if (UnityEngine.Random.value < Mathf.Clamp(dodgeStat.Percent, 0f, 0.9f)) - { - return 0; - } - } - - float damage = attack; - if (attackStat != null) - { - damage = (attack + attackStat.Value) * attackStat.Percent; - } - - if (defenseStat != null) - { - damage = (damage - defenseStat.Value) / defenseStat.Percent; - } - - if (damage < 1f) - { - return 1; - } - - return Mathf.CeilToInt(damage); - } - private static bool TryGetTargetableEntity(int entityId, out TargetableObject target) { target = null; diff --git a/Assets/GameMain/Scripts/Simulation/SimulationWorld.TargetSelectionSpatialIndex.cs b/Assets/GameMain/Scripts/Simulation/SimulationWorld.TargetSelectionSpatialIndex.cs index 23c39dd..37bf518 100644 --- a/Assets/GameMain/Scripts/Simulation/SimulationWorld.TargetSelectionSpatialIndex.cs +++ b/Assets/GameMain/Scripts/Simulation/SimulationWorld.TargetSelectionSpatialIndex.cs @@ -8,7 +8,6 @@ namespace Simulation { private NativeParallelMultiHashMap _enemyTargetBuckets; private bool _enemyTargetBucketsDirty = true; - private int _enemyTargetBucketsFrame = -1; [SerializeField] private float _targetSelectionCellSize = 2f; @@ -85,7 +84,6 @@ namespace Simulation _enemyTargetBuckets = new NativeParallelMultiHashMap(256, Allocator.Persistent); _enemyTargetBucketsDirty = true; - _enemyTargetBucketsFrame = -1; } private void DisposeEnemyTargetSpatialIndex() @@ -97,7 +95,6 @@ namespace Simulation _enemyTargetBuckets = default; _enemyTargetBucketsDirty = true; - _enemyTargetBucketsFrame = -1; } private void ClearEnemyTargetSpatialIndex() @@ -108,20 +105,18 @@ namespace Simulation } _enemyTargetBucketsDirty = true; - _enemyTargetBucketsFrame = -1; } private void MarkEnemyTargetSpatialIndexDirty() { _enemyTargetBucketsDirty = true; - _enemyTargetBucketsFrame = -1; } private void BuildEnemyTargetSpatialIndexIfNeeded() { InitializeEnemyTargetSpatialIndex(); - if (!_enemyTargetBucketsDirty && _enemyTargetBucketsFrame == Time.frameCount) + if (!_enemyTargetBucketsDirty) { return; } @@ -148,7 +143,6 @@ namespace Simulation } _enemyTargetBucketsDirty = false; - _enemyTargetBucketsFrame = Time.frameCount; } private float GetTargetSelectionCellSize() diff --git a/openspec/config.yaml b/openspec/config.yaml deleted file mode 100644 index 392946c..0000000 --- a/openspec/config.yaml +++ /dev/null @@ -1,20 +0,0 @@ -schema: spec-driven - -# Project context (optional) -# This is shown to AI when creating artifacts. -# Add your tech stack, conventions, style guides, domain knowledge, etc. -# Example: -# context: | -# Tech stack: TypeScript, React, Node.js -# We use conventional commits -# Domain: e-commerce platform - -# Per-artifact rules (optional) -# Add custom rules for specific artifacts. -# Example: -# rules: -# proposal: -# - Keep proposals under 500 words -# - Always include a "Non-goals" section -# tasks: -# - Break tasks into chunks of max 2 hours