214 lines
10 KiB
C#
214 lines
10 KiB
C#
using Unity.CharacterController;
|
|
using Unity.Entities;
|
|
using Unity.Mathematics;
|
|
using Unity.Physics;
|
|
|
|
namespace ProjectM.Simulation
|
|
{
|
|
/// <summary>
|
|
/// Per-update "global" data the character processor needs (lookups, singletons). Empty for the minimal
|
|
/// top-down character — kept so the CC update signature is satisfied and future lookups have a home.
|
|
/// </summary>
|
|
public struct CharacterUpdateContext
|
|
{
|
|
public void OnSystemCreate(ref SystemState state) { }
|
|
public void OnSystemUpdate(ref SystemState state) { }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Top-down kinematic character processor (CC 1.4.2 pattern: <see cref="IKinematicCharacterProcessor{T}"/>
|
|
/// + a <see cref="KinematicCharacterDataAccess"/> built in the job, driving the static
|
|
/// <see cref="KinematicCharacterUtilities"/> Update_* sequence). Stripped of all FPS features: no jump,
|
|
/// no air movement, no gravity, no view. <see cref="PhysicsUpdate"/> runs the canonical CC update
|
|
/// sequence; <see cref="HandleVelocityControl"/> lerps RelativeVelocity toward the desired planar
|
|
/// velocity <see cref="PlayerControlSystem"/> wrote. Rotation/facing is owned by <see cref="PlayerAimSystem"/>.
|
|
/// </summary>
|
|
public struct CharacterProcessor : IKinematicCharacterProcessor<CharacterUpdateContext>
|
|
{
|
|
public KinematicCharacterDataAccess CharacterDataAccess;
|
|
public RefRW<CharacterComponent> CharacterComponent;
|
|
public RefRW<CharacterControl> CharacterControl;
|
|
|
|
public void PhysicsUpdate(ref CharacterUpdateContext context, ref KinematicCharacterUpdateContext baseContext)
|
|
{
|
|
ref CharacterComponent characterComponent = ref CharacterComponent.ValueRW;
|
|
ref KinematicCharacterBody characterBody = ref CharacterDataAccess.CharacterBody.ValueRW;
|
|
ref float3 characterPosition = ref CharacterDataAccess.LocalTransform.ValueRW.Position;
|
|
|
|
KinematicCharacterUtilities.Update_Initialize(
|
|
in this, ref context, ref baseContext,
|
|
ref characterBody,
|
|
CharacterDataAccess.CharacterHitsBuffer,
|
|
CharacterDataAccess.DeferredImpulsesBuffer,
|
|
CharacterDataAccess.VelocityProjectionHits,
|
|
baseContext.Time.DeltaTime);
|
|
|
|
KinematicCharacterUtilities.Update_ParentMovement(
|
|
in this, ref context, ref baseContext,
|
|
CharacterDataAccess.CharacterEntity,
|
|
ref characterBody,
|
|
CharacterDataAccess.CharacterProperties.ValueRO,
|
|
CharacterDataAccess.PhysicsCollider.ValueRO,
|
|
CharacterDataAccess.LocalTransform.ValueRO,
|
|
ref characterPosition,
|
|
characterBody.WasGroundedBeforeCharacterUpdate);
|
|
|
|
KinematicCharacterUtilities.Update_Grounding(
|
|
in this, ref context, ref baseContext,
|
|
ref characterBody,
|
|
CharacterDataAccess.CharacterEntity,
|
|
CharacterDataAccess.CharacterProperties.ValueRO,
|
|
CharacterDataAccess.PhysicsCollider.ValueRO,
|
|
CharacterDataAccess.LocalTransform.ValueRO,
|
|
CharacterDataAccess.VelocityProjectionHits,
|
|
CharacterDataAccess.CharacterHitsBuffer,
|
|
ref characterPosition);
|
|
|
|
HandleVelocityControl(ref context, ref baseContext);
|
|
|
|
KinematicCharacterUtilities.Update_PreventGroundingFromFutureSlopeChange(
|
|
in this, ref context, ref baseContext,
|
|
CharacterDataAccess.CharacterEntity,
|
|
ref characterBody,
|
|
CharacterDataAccess.CharacterProperties.ValueRO,
|
|
CharacterDataAccess.PhysicsCollider.ValueRO,
|
|
in characterComponent.StepAndSlopeHandling);
|
|
|
|
KinematicCharacterUtilities.Update_GroundPushing(
|
|
in this, ref context, ref baseContext,
|
|
ref characterBody,
|
|
CharacterDataAccess.CharacterProperties.ValueRO,
|
|
CharacterDataAccess.LocalTransform.ValueRO,
|
|
CharacterDataAccess.DeferredImpulsesBuffer,
|
|
float3.zero);
|
|
|
|
KinematicCharacterUtilities.Update_MovementAndDecollisions(
|
|
in this, ref context, ref baseContext,
|
|
CharacterDataAccess.CharacterEntity,
|
|
ref characterBody,
|
|
CharacterDataAccess.CharacterProperties.ValueRO,
|
|
CharacterDataAccess.PhysicsCollider.ValueRO,
|
|
CharacterDataAccess.LocalTransform.ValueRO,
|
|
CharacterDataAccess.VelocityProjectionHits,
|
|
CharacterDataAccess.CharacterHitsBuffer,
|
|
CharacterDataAccess.DeferredImpulsesBuffer,
|
|
ref characterPosition);
|
|
|
|
KinematicCharacterUtilities.Update_MovingPlatformDetection(ref baseContext, ref characterBody);
|
|
KinematicCharacterUtilities.Update_ParentMomentum(ref baseContext, ref characterBody,
|
|
CharacterDataAccess.LocalTransform.ValueRO.Position);
|
|
KinematicCharacterUtilities.Update_ProcessStatefulCharacterHits(
|
|
CharacterDataAccess.CharacterHitsBuffer,
|
|
CharacterDataAccess.StatefulHitsBuffer);
|
|
}
|
|
|
|
void HandleVelocityControl(ref CharacterUpdateContext context, ref KinematicCharacterUpdateContext baseContext)
|
|
{
|
|
float deltaTime = baseContext.Time.DeltaTime;
|
|
ref KinematicCharacterBody characterBody = ref CharacterDataAccess.CharacterBody.ValueRW;
|
|
ref CharacterComponent characterComponent = ref CharacterComponent.ValueRW;
|
|
CharacterControl characterControl = CharacterControl.ValueRO;
|
|
|
|
// Planar twin-stick: smoothly approach the desired world velocity (already speed-scaled, Y==0).
|
|
float3 targetVelocity = characterControl.MoveVelocity;
|
|
CharacterControlUtilities.StandardGroundMove_Interpolated(
|
|
ref characterBody.RelativeVelocity,
|
|
targetVelocity,
|
|
characterComponent.GroundedMovementSharpness,
|
|
deltaTime,
|
|
math.up(),
|
|
math.up());
|
|
}
|
|
|
|
public void VariableUpdate(ref CharacterUpdateContext context, ref KinematicCharacterUpdateContext baseContext) { }
|
|
|
|
public void UpdateGroundingUp(ref CharacterUpdateContext context, ref KinematicCharacterUpdateContext baseContext)
|
|
{
|
|
ref KinematicCharacterBody characterBody = ref CharacterDataAccess.CharacterBody.ValueRW;
|
|
KinematicCharacterUtilities.Default_UpdateGroundingUp(
|
|
ref characterBody,
|
|
CharacterDataAccess.LocalTransform.ValueRO.Rotation);
|
|
}
|
|
|
|
public bool CanCollideWithHit(ref CharacterUpdateContext context, ref KinematicCharacterUpdateContext baseContext, in BasicHit hit)
|
|
{
|
|
return PhysicsUtilities.IsCollidable(hit.Material);
|
|
}
|
|
|
|
public bool IsGroundedOnHit(ref CharacterUpdateContext context, ref KinematicCharacterUpdateContext baseContext, in BasicHit hit, int groundingEvaluationType)
|
|
{
|
|
CharacterComponent characterComponent = CharacterComponent.ValueRO;
|
|
return KinematicCharacterUtilities.Default_IsGroundedOnHit(
|
|
in this, ref context, ref baseContext,
|
|
CharacterDataAccess.CharacterEntity,
|
|
CharacterDataAccess.PhysicsCollider.ValueRO,
|
|
CharacterDataAccess.CharacterBody.ValueRO,
|
|
CharacterDataAccess.CharacterProperties.ValueRO,
|
|
in hit,
|
|
in characterComponent.StepAndSlopeHandling,
|
|
groundingEvaluationType);
|
|
}
|
|
|
|
public void OnMovementHit(
|
|
ref CharacterUpdateContext context,
|
|
ref KinematicCharacterUpdateContext baseContext,
|
|
ref KinematicCharacterHit hit,
|
|
ref float3 remainingMovementDirection,
|
|
ref float remainingMovementLength,
|
|
float3 originalVelocityDirection,
|
|
float hitDistance)
|
|
{
|
|
ref KinematicCharacterBody characterBody = ref CharacterDataAccess.CharacterBody.ValueRW;
|
|
ref float3 characterPosition = ref CharacterDataAccess.LocalTransform.ValueRW.Position;
|
|
CharacterComponent characterComponent = CharacterComponent.ValueRO;
|
|
|
|
KinematicCharacterUtilities.Default_OnMovementHit(
|
|
in this, ref context, ref baseContext,
|
|
ref characterBody,
|
|
CharacterDataAccess.CharacterEntity,
|
|
CharacterDataAccess.CharacterProperties.ValueRO,
|
|
CharacterDataAccess.PhysicsCollider.ValueRO,
|
|
CharacterDataAccess.LocalTransform.ValueRO,
|
|
ref characterPosition,
|
|
CharacterDataAccess.VelocityProjectionHits,
|
|
ref hit,
|
|
ref remainingMovementDirection,
|
|
ref remainingMovementLength,
|
|
originalVelocityDirection,
|
|
hitDistance,
|
|
characterComponent.StepAndSlopeHandling.StepHandling,
|
|
characterComponent.StepAndSlopeHandling.MaxStepHeight,
|
|
characterComponent.StepAndSlopeHandling.CharacterWidthForStepGroundingCheck);
|
|
}
|
|
|
|
public void OverrideDynamicHitMasses(
|
|
ref CharacterUpdateContext context,
|
|
ref KinematicCharacterUpdateContext baseContext,
|
|
ref PhysicsMass characterMass,
|
|
ref PhysicsMass otherMass,
|
|
BasicHit hit)
|
|
{
|
|
}
|
|
|
|
public void ProjectVelocityOnHits(
|
|
ref CharacterUpdateContext context,
|
|
ref KinematicCharacterUpdateContext baseContext,
|
|
ref float3 velocity,
|
|
ref bool characterIsGrounded,
|
|
ref BasicHit characterGroundHit,
|
|
in DynamicBuffer<KinematicVelocityProjectionHit> velocityProjectionHits,
|
|
float3 originalVelocityDirection)
|
|
{
|
|
CharacterComponent characterComponent = CharacterComponent.ValueRO;
|
|
KinematicCharacterUtilities.Default_ProjectVelocityOnHits(
|
|
ref velocity,
|
|
ref characterIsGrounded,
|
|
ref characterGroundHit,
|
|
in velocityProjectionHits,
|
|
originalVelocityDirection,
|
|
characterComponent.StepAndSlopeHandling.ConstrainVelocityToGroundPlane,
|
|
in CharacterDataAccess.CharacterBody.ValueRO);
|
|
}
|
|
}
|
|
}
|