Polishes
This commit is contained in:
@@ -40,14 +40,18 @@ namespace ProjectM.Simulation
|
||||
/// Projects a planar movement <paramref name="vel"/> onto a wall plane defined by <paramref name="surfaceNormal"/>
|
||||
/// (collide-and-slide): removes the component of <paramref name="vel"/> that pushes into the surface so the
|
||||
/// mover glances along the wall instead of stopping dead. Both inputs are flattened to the XZ plane (top-down).
|
||||
/// Returns <paramref name="vel"/> unchanged when the normal is degenerate.
|
||||
/// When the flattened normal is DEGENERATE (a near-vertical / rounded-rock face collapses to ~0 in XZ),
|
||||
/// sliding is undefined and returning <paramref name="vel"/> unchanged would drive the mover straight back
|
||||
/// into the wall (the enemy-stuck-on-cover-rock bug) — so it deflects to a horizontal tangent of the motion
|
||||
/// (a 90 deg turn about Y) to glance AROUND the obstacle instead of freezing against it.
|
||||
/// </summary>
|
||||
public static float3 SlideVelocity(float3 vel, float3 surfaceNormal)
|
||||
{
|
||||
vel.y = 0f;
|
||||
surfaceNormal.y = 0f;
|
||||
float len = math.length(surfaceNormal);
|
||||
if (len < 1e-6f)
|
||||
return vel;
|
||||
return new float3(-vel.z, 0f, vel.x); // degenerate normal -> tangent deflection, not motion-into-wall
|
||||
float3 n = surfaceNormal / len;
|
||||
float3 slid = vel - math.dot(vel, n) * n;
|
||||
slid.y = 0f;
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
using Unity.Entities;
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace ProjectM.Simulation
|
||||
{
|
||||
/// <summary>
|
||||
/// Server-only per-Husk navigation / anti-stuck state (NOT replicated — clients never simulate enemies, so this
|
||||
/// carries no <c>[GhostField]</c> and does not change the ghost hash). Tracks the enemy's XZ position at the end
|
||||
/// of last tick plus how long it has failed to make progress toward its target, so <c>EnemyAISystem</c> can
|
||||
/// phase-nudge a genuinely stuck enemy (wedged on a cover rock or a rock-vs-boundary pocket) toward the nearest
|
||||
/// player — the guaranteed backstop that keeps an expedition room from ever soft-locking on one unreachable Husk.
|
||||
/// Baked onto every enemy by <c>EnemyAuthoring</c>. Complements the collide-and-slide fixes in
|
||||
/// <see cref="EnemyAIMath.SlideVelocity"/> / <c>EnemyMoveUtil</c> (which make sticking rare in the first place).
|
||||
/// </summary>
|
||||
public struct EnemyNavState : IComponentData
|
||||
{
|
||||
/// <summary>Enemy XZ position at the end of last tick (progress baseline; Y unused).</summary>
|
||||
public float3 LastPos;
|
||||
|
||||
/// <summary>Consecutive ticks the enemy wanted to move toward its target but made ~no progress.</summary>
|
||||
public uint StuckTicks;
|
||||
|
||||
/// <summary>While a <c>NetworkTick</c> newer than the current tick is stored here the enemy is phase-nudging
|
||||
/// toward its target (collide-and-slide bypassed) to escape geometry; <c>0</c> = not nudging. Routed through
|
||||
/// <c>TickUtil.NonZero</c> so a computed tick never collides with the 0 "inactive" sentinel.</summary>
|
||||
public uint NudgeUntilTick;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5f3964cc62bbb0042b85e8a6a944dabe
|
||||
Reference in New Issue
Block a user