From 76094b711b650a07ff9a7a33a11efc7276f14535 Mon Sep 17 00:00:00 2001 From: SepComet <202308010230@stu.csust.edu.cn> Date: Mon, 23 Feb 2026 11:48:05 +0800 Subject: [PATCH] fix 2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. MaxTargets 现在严格生效(包含玩家候选) - 玩家先被加入候选后,会计入 selectedCount,达到上限后不再继续查敌人桶。 2. UseSimulationMovement/UseJobSimulation 战斗中不生效 - 在 SimulationWorld 的 setter 中增加 Battle 状态保护:战斗中调用会被忽略并打 warning。 - 在 ProcedureGame 暴露当前状态类型,供 SimulationWorld 判断。 3. AOE 结算不再依赖结算时刻的 Weapon.IsAttacking - 在 AOE query 入队时快照 source 活跃状态(武器用 IsAttacking)。 - Query 数据结构增加 SourceWasActiveAtQueryTime。 - 结算时使用该快照判定,并通过 AIUtility.PerformCollision(..., ignoreRuntimeState: true) 避免被实时状态误伤。 --- .../Scripts/Procedure/Game/ProcedureGame.cs | 3 +- .../SimulationWorld.JobDataChannel.cs | 9 +++- .../SimulationWorld.ProjectileJobs.cs | 43 +++++++++++++++++-- .../Scripts/Simulation/SimulationWorld.cs | 25 +++++++++++ Assets/GameMain/Scripts/Utility/AIUtility.cs | 9 +++- 5 files changed, 80 insertions(+), 9 deletions(-) diff --git a/Assets/GameMain/Scripts/Procedure/Game/ProcedureGame.cs b/Assets/GameMain/Scripts/Procedure/Game/ProcedureGame.cs index bcb12aa..f7280d5 100644 --- a/Assets/GameMain/Scripts/Procedure/Game/ProcedureGame.cs +++ b/Assets/GameMain/Scripts/Procedure/Game/ProcedureGame.cs @@ -35,6 +35,7 @@ namespace Procedure public Player Player; public GameStateBase CurrentGameState => _gameStates[_currentGameState]; + public GameStateType CurrentGameStateType => _currentGameState; private void InitGameState() { @@ -169,4 +170,4 @@ namespace Procedure #endregion } -} \ No newline at end of file +} diff --git a/Assets/GameMain/Scripts/Simulation/SimulationWorld.JobDataChannel.cs b/Assets/GameMain/Scripts/Simulation/SimulationWorld.JobDataChannel.cs index 53f2207..04d36ba 100644 --- a/Assets/GameMain/Scripts/Simulation/SimulationWorld.JobDataChannel.cs +++ b/Assets/GameMain/Scripts/Simulation/SimulationWorld.JobDataChannel.cs @@ -75,6 +75,7 @@ namespace Simulation public int SourceType; public int SourceEntityId; public int SourceOwnerEntityId; + public bool SourceWasActiveAtQueryTime; public float3 Position; public float Radius; public int MaxTargets; @@ -98,6 +99,7 @@ namespace Simulation { public int SourceEntityId; public int SourceOwnerEntityId; + public bool SourceWasActiveAtQueryTime; public Vector3 Center; public float Radius; public int MaxTargets; @@ -474,6 +476,7 @@ namespace Simulation SourceType = CollisionSourceTypeProjectile, SourceEntityId = projectile.EntityId, SourceOwnerEntityId = projectile.OwnerEntityId, + SourceWasActiveAtQueryTime = true, Position = projectile.Position, Radius = radius, MaxTargets = math.max(1, maxTargets), @@ -483,8 +486,9 @@ namespace Simulation }); } - private void AddAreaCollisionQuery(int queryId, int sourceEntityId, int sourceOwnerEntityId, in Vector3 center, - float radius, int maxTargets, int shapeType, in Vector3 direction, float halfAngleDeg) + private void AddAreaCollisionQuery(int queryId, int sourceEntityId, int sourceOwnerEntityId, + bool sourceWasActiveAtQueryTime, in Vector3 center, float radius, int maxTargets, int shapeType, + in Vector3 direction, float halfAngleDeg) { if (!_collisionQueryInputs.IsCreated || radius <= 0f) { @@ -508,6 +512,7 @@ namespace Simulation SourceType = CollisionSourceTypeArea, SourceEntityId = sourceEntityId, SourceOwnerEntityId = sourceOwnerEntityId, + SourceWasActiveAtQueryTime = sourceWasActiveAtQueryTime, Position = new float3(center.x, center.y, center.z), Radius = radius, MaxTargets = math.max(1, maxTargets), diff --git a/Assets/GameMain/Scripts/Simulation/SimulationWorld.ProjectileJobs.cs b/Assets/GameMain/Scripts/Simulation/SimulationWorld.ProjectileJobs.cs index d70d85b..06cb4b4 100644 --- a/Assets/GameMain/Scripts/Simulation/SimulationWorld.ProjectileJobs.cs +++ b/Assets/GameMain/Scripts/Simulation/SimulationWorld.ProjectileJobs.cs @@ -106,6 +106,7 @@ namespace Simulation } int resolvedOwnerEntityId = sourceOwnerEntityId != 0 ? sourceOwnerEntityId : sourceEntityId; + bool sourceWasActiveAtQueryTime = IsCollisionSourceActiveAtQueryTime(sourceEntityId); Vector3 normalizedDirection = direction; normalizedDirection.y = 0f; if (normalizedDirection.sqrMagnitude <= Mathf.Epsilon) @@ -121,6 +122,7 @@ namespace Simulation { SourceEntityId = sourceEntityId, SourceOwnerEntityId = resolvedOwnerEntityId, + SourceWasActiveAtQueryTime = sourceWasActiveAtQueryTime, Center = center, Radius = Mathf.Max(0.01f, radius), MaxTargets = Mathf.Max(1, maxTargets), @@ -238,8 +240,9 @@ namespace Simulation for (int i = 0; i < areaQueryCount; i++) { AreaCollisionRequestData request = _areaCollisionRequests[i]; - AddAreaCollisionQuery(queryId, request.SourceEntityId, request.SourceOwnerEntityId, in request.Center, - request.Radius, request.MaxTargets, request.ShapeType, in request.Direction, request.HalfAngleDeg); + AddAreaCollisionQuery(queryId, request.SourceEntityId, request.SourceOwnerEntityId, + request.SourceWasActiveAtQueryTime, in request.Center, request.Radius, request.MaxTargets, + request.ShapeType, in request.Direction, request.HalfAngleDeg); queryId++; builtAreaQueryCount++; if (request.Radius > maxQueryRadius) @@ -628,6 +631,11 @@ namespace Simulation continue; } + if (!query.SourceWasActiveAtQueryTime) + { + continue; + } + EntityBase sourceEntity = TryGetEntityById(hitEvent.SourceEntityId); if (sourceEntity == null || !sourceEntity.Available) { @@ -644,7 +652,7 @@ namespace Simulation continue; } - AIUtility.PerformCollision(target, sourceEntity); + AIUtility.PerformCollision(target, sourceEntity, true); resolvedHitCount++; } @@ -787,10 +795,16 @@ namespace Simulation { areaCandidateCount++; } + + selectedCount++; + if (selectedCount >= query.MaxTargets) + { + reachedLimit = true; + } } } - if (!hasEnemyTargets) + if (!hasEnemyTargets || reachedLimit) { continue; } @@ -893,6 +907,27 @@ namespace Simulation return projectile.LifeTime > 0f && projectile.Age >= projectile.LifeTime; } + private static bool IsCollisionSourceActiveAtQueryTime(int sourceEntityId) + { + EntityBase sourceEntity = TryGetEntityById(sourceEntityId); + if (sourceEntity == null || !sourceEntity.Available) + { + return false; + } + + if (sourceEntity is WeaponBase weapon) + { + return weapon.IsAttacking; + } + + if (sourceEntity is EnemyProjectile projectile) + { + return projectile.IsActive; + } + + return true; + } + private static void ExecuteProjectileMovement(int index, NativeArray inputs, NativeArray outputs, float deltaTime, float3 playerPosition, float maxSqrDistanceFromPlayer, float maxVerticalOffsetFromPlayer) diff --git a/Assets/GameMain/Scripts/Simulation/SimulationWorld.cs b/Assets/GameMain/Scripts/Simulation/SimulationWorld.cs index 9c67d05..eae40a8 100644 --- a/Assets/GameMain/Scripts/Simulation/SimulationWorld.cs +++ b/Assets/GameMain/Scripts/Simulation/SimulationWorld.cs @@ -4,6 +4,7 @@ using CustomDebugger; using CustomUtility; using Entity; using Entity.EntityData; +using Procedure; using UnityEngine; using UnityGameFramework.Runtime; @@ -69,11 +70,23 @@ namespace Simulation public void SetUseSimulationMovement(bool enabled) { + if (IsBattleStateActive()) + { + Log.Warning("SetUseSimulationMovement is ignored during Battle. Change this switch outside Battle."); + return; + } + _useSimulationMovement = enabled; } public void SetUseJobSimulation(bool enabled) { + if (IsBattleStateActive()) + { + Log.Warning("SetUseJobSimulation is ignored during Battle. Change this switch outside Battle."); + return; + } + _useJobSimulation = enabled; } @@ -82,6 +95,18 @@ namespace Simulation _useBurstJobs = enabled; } + private static bool IsBattleStateActive() + { + var procedureComponent = GameEntry.Procedure; + if (procedureComponent == null || + procedureComponent.CurrentProcedure is not ProcedureGame procedureGame) + { + return false; + } + + return procedureGame.CurrentGameStateType == GameStateType.Battle; + } + protected override void Awake() { base.Awake(); diff --git a/Assets/GameMain/Scripts/Utility/AIUtility.cs b/Assets/GameMain/Scripts/Utility/AIUtility.cs index b9399ea..c118872 100644 --- a/Assets/GameMain/Scripts/Utility/AIUtility.cs +++ b/Assets/GameMain/Scripts/Utility/AIUtility.cs @@ -159,6 +159,11 @@ namespace CustomUtility } public static void PerformCollision(TargetableObject entity, EntityBase other) + { + PerformCollision(entity, other, false); + } + + public static void PerformCollision(TargetableObject entity, EntityBase other, bool ignoreRuntimeState) { if (entity == null || other == null) { @@ -204,7 +209,7 @@ namespace CustomUtility EnemyProjectile enemyProjectile = other as EnemyProjectile; if (enemyProjectile != null) { - if (!enemyProjectile.IsActive) return; + if (!ignoreRuntimeState && !enemyProjectile.IsActive) return; ImpactData entityImpactData = entity.GetImpactData(); ImpactData projectileImpactData = enemyProjectile.GetImpactData(); @@ -224,7 +229,7 @@ namespace CustomUtility WeaponBase weapon = other as WeaponBase; if (weapon != null) { - if (!weapon.IsAttacking) return; + if (!ignoreRuntimeState && !weapon.IsAttacking) return; ImpactData entityImpactData = entity.GetImpactData(); ImpactData weaponImpactData = weapon.GetImpactData(); if (GetRelation(entityImpactData.Camp, weaponImpactData.Camp) == RelationType.Friendly)