NPC steering blending (#25666)
* NPC steering blending Significantly more stable than using LastSteerDirection and also AntiStuck never got tripped locally when I was running around. I also left future notes for me to cleanup the pathfinder in future. * Remove index
This commit is contained in:
@@ -9,6 +9,7 @@ using Content.Shared.Movement.Components;
|
||||
using Content.Shared.NPC;
|
||||
using Content.Shared.Physics;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using ClimbingComponent = Content.Shared.Climbing.Components.ClimbingComponent;
|
||||
|
||||
@@ -16,7 +17,7 @@ namespace Content.Server.NPC.Systems;
|
||||
|
||||
public sealed partial class NPCSteeringSystem
|
||||
{
|
||||
private void ApplySeek(float[] interest, Vector2 direction, float weight)
|
||||
private void ApplySeek(Span<float> interest, Vector2 direction, float weight)
|
||||
{
|
||||
if (weight == 0f || direction == Vector2.Zero)
|
||||
return;
|
||||
@@ -25,13 +26,10 @@ public sealed partial class NPCSteeringSystem
|
||||
|
||||
for (var i = 0; i < InterestDirections; i++)
|
||||
{
|
||||
if (interest[i].Equals(-1f))
|
||||
continue;
|
||||
|
||||
var angle = i * InterestRadians;
|
||||
var dot = MathF.Cos(directionAngle - angle);
|
||||
dot = (dot + 1) * 0.5f;
|
||||
interest[i] += dot * weight;
|
||||
dot = (dot + 1f) * 0.5f;
|
||||
interest[i] = Math.Clamp(interest[i] + dot * weight, 0f, 1f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +70,7 @@ public sealed partial class NPCSteeringSystem
|
||||
TransformComponent xform,
|
||||
Angle offsetRot,
|
||||
float moveSpeed,
|
||||
float[] interest,
|
||||
Span<float> interest,
|
||||
float frameTime,
|
||||
ref bool forceSteer)
|
||||
{
|
||||
@@ -274,7 +272,8 @@ public sealed partial class NPCSteeringSystem
|
||||
}
|
||||
|
||||
// If not in LOS and no path then get a new one fam.
|
||||
if (!inLos && steering.CurrentPath.Count == 0)
|
||||
if ((!inLos && steering.ArriveOnLineOfSight && steering.CurrentPath.Count == 0) ||
|
||||
(!steering.ArriveOnLineOfSight && steering.CurrentPath.Count == 0))
|
||||
{
|
||||
needsPath = true;
|
||||
}
|
||||
@@ -465,12 +464,12 @@ public sealed partial class NPCSteeringSystem
|
||||
int layer,
|
||||
int mask,
|
||||
TransformComponent xform,
|
||||
float[] danger)
|
||||
Span<float> danger)
|
||||
{
|
||||
var objectRadius = 0.15f;
|
||||
var objectRadius = 0.25f;
|
||||
var detectionRadius = MathF.Max(0.35f, agentRadius + objectRadius);
|
||||
var ents = _entSetPool.Get();
|
||||
_lookup.GetEntitiesInRange(uid, detectionRadius, ents, LookupFlags.Static);
|
||||
_lookup.GetEntitiesInRange(uid, detectionRadius, ents, LookupFlags.Dynamic | LookupFlags.Static);
|
||||
|
||||
foreach (var ent in ents)
|
||||
{
|
||||
@@ -478,6 +477,7 @@ public sealed partial class NPCSteeringSystem
|
||||
if (!_physicsQuery.TryGetComponent(ent, out var otherBody) ||
|
||||
!otherBody.Hard ||
|
||||
!otherBody.CanCollide ||
|
||||
otherBody.BodyType == BodyType.KinematicController ||
|
||||
(mask & otherBody.CollisionLayer) == 0x0 &&
|
||||
(layer & otherBody.CollisionMask) == 0x0)
|
||||
{
|
||||
@@ -506,7 +506,7 @@ public sealed partial class NPCSteeringSystem
|
||||
}
|
||||
else
|
||||
{
|
||||
weight = distance / detectionRadius;
|
||||
weight = (detectionRadius - distance) / detectionRadius;
|
||||
}
|
||||
|
||||
if (obstacleDirection == Vector2.Zero)
|
||||
@@ -541,7 +541,7 @@ public sealed partial class NPCSteeringSystem
|
||||
int mask,
|
||||
PhysicsComponent body,
|
||||
TransformComponent xform,
|
||||
float[] danger)
|
||||
Span<float> danger)
|
||||
{
|
||||
var objectRadius = 0.25f;
|
||||
var detectionRadius = MathF.Max(0.35f, agentRadius + objectRadius);
|
||||
@@ -614,4 +614,35 @@ public sealed partial class NPCSteeringSystem
|
||||
// TODO: Alignment
|
||||
|
||||
// TODO: Cohesion
|
||||
private void Blend(NPCSteeringComponent steering, float frameTime, Span<float> interest, Span<float> danger)
|
||||
{
|
||||
/*
|
||||
* Future sloth notes:
|
||||
* Pathfinder cleanup:
|
||||
- Cleanup whatever the fuck is happening in pathfinder
|
||||
- Use Flee for melee behavior / actions and get the seek direction from that rather than bulldozing
|
||||
- Must always have a path
|
||||
- Path should return the full version + the snipped version
|
||||
- Pathfinder needs to do diagonals
|
||||
- Next node is either <current node + 1> or <nearest node + 1> (on the full path)
|
||||
- If greater than <1.5m distance> repath
|
||||
*/
|
||||
|
||||
// IDK why I didn't do this sooner but blending is a lot better than lastdir for fixing stuttering.
|
||||
const float BlendWeight = 10f;
|
||||
var blendValue = Math.Min(1f, frameTime * BlendWeight);
|
||||
|
||||
for (var i = 0; i < InterestDirections; i++)
|
||||
{
|
||||
var currentInterest = interest[i];
|
||||
var lastInterest = steering.Interest[i];
|
||||
var interestDiff = (currentInterest - lastInterest) * blendValue;
|
||||
steering.Interest[i] = lastInterest + interestDiff;
|
||||
|
||||
var currentDanger = danger[i];
|
||||
var lastDanger = steering.Danger[i];
|
||||
var dangerDiff = (currentDanger - lastDanger) * blendValue;
|
||||
steering.Danger[i] = lastDanger + dangerDiff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user