优化 WeaponLance 的攻击逻辑
This commit is contained in:
+7
-3
@@ -65,13 +65,15 @@ namespace Simulation
|
||||
MaxTargets = math.max(1, maxTargets),
|
||||
ShapeType = CollisionShapeCircle,
|
||||
Direction = new float3(0f, 0f, 1f),
|
||||
HalfAngleDeg = 180f
|
||||
HalfAngleDeg = 180f,
|
||||
HalfWidth = 0f,
|
||||
HalfLength = 0f
|
||||
});
|
||||
}
|
||||
|
||||
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)
|
||||
in Vector3 direction, float halfAngleDeg, float halfWidth, float halfLength)
|
||||
{
|
||||
if (!_collisionQueryInputs.IsCreated || radius <= 0f)
|
||||
{
|
||||
@@ -101,7 +103,9 @@ namespace Simulation
|
||||
MaxTargets = math.max(1, maxTargets),
|
||||
ShapeType = shapeType,
|
||||
Direction = new float3(normalizedDirection.x, normalizedDirection.y, normalizedDirection.z),
|
||||
HalfAngleDeg = Mathf.Clamp(halfAngleDeg, 0f, 180f)
|
||||
HalfAngleDeg = Mathf.Clamp(halfAngleDeg, 0f, 180f),
|
||||
HalfWidth = Mathf.Max(0f, halfWidth),
|
||||
HalfLength = Mathf.Max(0f, halfLength)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Simulation
|
||||
private const int CollisionSourceTypeArea = 2;
|
||||
private const int CollisionShapeCircle = 0;
|
||||
private const int CollisionShapeSector = 1;
|
||||
private const int CollisionShapeRectangle = 2;
|
||||
|
||||
// Kept as top-level fields because current regression tests reflect them directly.
|
||||
private NativeList<CollisionQueryData> _collisionQueryInputs;
|
||||
|
||||
@@ -15,6 +15,8 @@ namespace Simulation
|
||||
public int ShapeType;
|
||||
public Vector3 Direction;
|
||||
public float HalfAngleDeg;
|
||||
public float HalfWidth;
|
||||
public float HalfLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ namespace Simulation
|
||||
public int ShapeType;
|
||||
public float3 Direction;
|
||||
public float HalfAngleDeg;
|
||||
public float HalfWidth;
|
||||
public float HalfLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ namespace Simulation
|
||||
public void Execute(int index)
|
||||
{
|
||||
CollisionQueryData query = Queries[index];
|
||||
float radiusSqr = query.Radius * query.Radius;
|
||||
int centerCellX = (int)math.floor(query.Position.x / CellSize);
|
||||
int centerCellZ = (int)math.floor(query.Position.z / CellSize);
|
||||
int queryRange = math.max(1, (int)math.ceil(query.Radius / CellSize));
|
||||
@@ -34,10 +33,14 @@ namespace Simulation
|
||||
query.SourceOwnerEntityId != PlayerTargetEntityId)
|
||||
{
|
||||
float3 playerPosition = PlayerPosition;
|
||||
playerPosition.y = query.Position.y;
|
||||
if (query.SourceType == CollisionSourceTypeArea)
|
||||
{
|
||||
playerPosition.y = query.Position.y;
|
||||
}
|
||||
float3 playerDelta = playerPosition - query.Position;
|
||||
float playerSqrDistance = math.lengthsq(playerDelta);
|
||||
if (playerSqrDistance <= radiusSqr)
|
||||
float playerRadiusSqr = query.Radius * query.Radius;
|
||||
if (playerSqrDistance <= playerRadiusSqr)
|
||||
{
|
||||
Candidates.AddNoResize(new CollisionCandidateData
|
||||
{
|
||||
@@ -86,12 +89,19 @@ namespace Simulation
|
||||
continue;
|
||||
}
|
||||
|
||||
float deltaY = query.SourceType == CollisionSourceTypeArea
|
||||
? 0f
|
||||
: enemy.Position.y - query.Position.y;
|
||||
float3 delta = new float3(
|
||||
enemy.Position.x - query.Position.x,
|
||||
enemy.Position.y - query.Position.y,
|
||||
deltaY,
|
||||
enemy.Position.z - query.Position.z);
|
||||
float sqrDistance = math.lengthsq(delta);
|
||||
if (sqrDistance > radiusSqr)
|
||||
float targetRadius = query.SourceType == CollisionSourceTypeArea
|
||||
? math.max(0f, enemy.EnemyBodyRadius)
|
||||
: 0f;
|
||||
float effectiveRadius = query.Radius + targetRadius;
|
||||
if (sqrDistance > effectiveRadius * effectiveRadius)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -119,4 +129,4 @@ namespace Simulation
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,8 @@ namespace Simulation
|
||||
AreaCollisionRequestData request = _areaCollisionRequests[i];
|
||||
AddAreaCollisionQuery(queryId, request.SourceEntityId, request.SourceOwnerEntityId,
|
||||
request.SourceWasActiveAtQueryTime, in request.Center, request.Radius, request.MaxTargets,
|
||||
request.ShapeType, in request.Direction, request.HalfAngleDeg);
|
||||
request.ShapeType, in request.Direction, request.HalfAngleDeg, request.HalfWidth,
|
||||
request.HalfLength);
|
||||
queryId++;
|
||||
builtAreaQueryCount++;
|
||||
if (request.Radius > maxQueryRadius)
|
||||
|
||||
@@ -12,18 +12,29 @@ namespace Simulation
|
||||
float radius, int maxTargets = 16)
|
||||
{
|
||||
return TryRequestAreaCollisionInternal(sourceEntityId, sourceOwnerEntityId, in center, radius,
|
||||
maxTargets, CollisionShapeCircle, Vector3.forward, 180f);
|
||||
maxTargets, CollisionShapeCircle, Vector3.forward, 180f, 0f, 0f);
|
||||
}
|
||||
|
||||
public bool TryRequestSectorCollision(int sourceEntityId, int sourceOwnerEntityId, in Vector3 center,
|
||||
float radius, in Vector3 direction, float halfAngleDeg, int maxTargets = 16)
|
||||
{
|
||||
return TryRequestAreaCollisionInternal(sourceEntityId, sourceOwnerEntityId, in center, radius,
|
||||
maxTargets, CollisionShapeSector, direction, halfAngleDeg);
|
||||
maxTargets, CollisionShapeSector, direction, halfAngleDeg, 0f, 0f);
|
||||
}
|
||||
|
||||
public bool TryRequestRectangleCollision(int sourceEntityId, int sourceOwnerEntityId, in Vector3 center,
|
||||
float halfWidth, float halfLength, in Vector3 direction, int maxTargets = 16)
|
||||
{
|
||||
float safeHalfWidth = Mathf.Max(0.01f, halfWidth);
|
||||
float safeHalfLength = Mathf.Max(0.01f, halfLength);
|
||||
float boundingRadius = Mathf.Sqrt(safeHalfWidth * safeHalfWidth + safeHalfLength * safeHalfLength);
|
||||
return TryRequestAreaCollisionInternal(sourceEntityId, sourceOwnerEntityId, in center, boundingRadius,
|
||||
maxTargets, CollisionShapeRectangle, direction, 0f, safeHalfWidth, safeHalfLength);
|
||||
}
|
||||
|
||||
private bool TryRequestAreaCollisionInternal(int sourceEntityId, int sourceOwnerEntityId,
|
||||
in Vector3 center, float radius, int maxTargets, int shapeType, in Vector3 direction, float halfAngleDeg)
|
||||
in Vector3 center, float radius, int maxTargets, int shapeType, in Vector3 direction, float halfAngleDeg,
|
||||
float halfWidth, float halfLength)
|
||||
{
|
||||
if (!_useSimulationMovement)
|
||||
{
|
||||
@@ -58,7 +69,9 @@ namespace Simulation
|
||||
MaxTargets = Mathf.Max(1, maxTargets),
|
||||
ShapeType = shapeType,
|
||||
Direction = normalizedDirection,
|
||||
HalfAngleDeg = Mathf.Clamp(halfAngleDeg, 0f, 180f)
|
||||
HalfAngleDeg = Mathf.Clamp(halfAngleDeg, 0f, 180f),
|
||||
HalfWidth = Mathf.Max(0f, halfWidth),
|
||||
HalfLength = Mathf.Max(0f, halfLength)
|
||||
});
|
||||
|
||||
return true;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Components;
|
||||
using CustomDebugger;
|
||||
using CustomUtility;
|
||||
using Definition.DataStruct;
|
||||
@@ -188,7 +189,8 @@ namespace Simulation
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!IsAreaTargetInsidePreciseShape(in query, target))
|
||||
float targetRadius = ResolveAreaTargetRadius(target);
|
||||
if (!IsAreaTargetInsidePreciseShape(in query, target, targetRadius))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -230,7 +232,24 @@ namespace Simulation
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool IsAreaTargetInsidePreciseShape(in CollisionQueryData query, TargetableObject target)
|
||||
private float ResolveAreaTargetRadius(TargetableObject target)
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
|
||||
if (target is EnemyBase && TryGetEnemyData(target.Id, out EnemySimData enemyData))
|
||||
{
|
||||
return Mathf.Max(0f, enemyData.EnemyBodyRadius);
|
||||
}
|
||||
|
||||
MovementComponent movementComponent = target.GetComponent<MovementComponent>();
|
||||
return movementComponent != null ? Mathf.Max(0f, movementComponent.EnemyBodyRadius) : 0f;
|
||||
}
|
||||
|
||||
private static bool IsAreaTargetInsidePreciseShape(in CollisionQueryData query, TargetableObject target,
|
||||
float targetRadius)
|
||||
{
|
||||
if (target == null || target.CachedTransform == null)
|
||||
{
|
||||
@@ -241,7 +260,7 @@ namespace Simulation
|
||||
Vector3 toTarget = target.CachedTransform.position - center;
|
||||
toTarget.y = 0f;
|
||||
|
||||
float radius = Mathf.Max(0.01f, query.Radius);
|
||||
float radius = Mathf.Max(0.01f, query.Radius + Mathf.Max(0f, targetRadius));
|
||||
float radiusSqr = radius * radius;
|
||||
float sqrDistance = toTarget.sqrMagnitude;
|
||||
if (sqrDistance > radiusSqr)
|
||||
@@ -249,6 +268,27 @@ namespace Simulation
|
||||
return false;
|
||||
}
|
||||
|
||||
if (query.ShapeType == CollisionShapeRectangle)
|
||||
{
|
||||
Vector3 forwardRect = new Vector3(query.Direction.x, query.Direction.y, query.Direction.z);
|
||||
forwardRect.y = 0f;
|
||||
if (forwardRect.sqrMagnitude <= Mathf.Epsilon)
|
||||
{
|
||||
forwardRect = Vector3.forward;
|
||||
}
|
||||
else
|
||||
{
|
||||
forwardRect.Normalize();
|
||||
}
|
||||
|
||||
Vector3 rightRect = Vector3.Cross(Vector3.up, forwardRect);
|
||||
float halfWidth = Mathf.Max(0.01f, query.HalfWidth + Mathf.Max(0f, targetRadius));
|
||||
float halfLength = Mathf.Max(0.01f, query.HalfLength + Mathf.Max(0f, targetRadius));
|
||||
float forwardDistance = Vector3.Dot(toTarget, forwardRect);
|
||||
float lateralDistance = Vector3.Dot(toTarget, rightRect);
|
||||
return Mathf.Abs(forwardDistance) <= halfLength && Mathf.Abs(lateralDistance) <= halfWidth;
|
||||
}
|
||||
|
||||
if (query.ShapeType != CollisionShapeSector)
|
||||
{
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user