Files
Net.Like.Xue.Tokyo/Packages-Local/Com.Project.B.Unity/Npc/NpcCharacterStates.cs

153 lines
4.7 KiB
C#
Raw Normal View History

2025-06-24 23:49:13 +08:00
using BITKit.StateMachine;
using Project.B.CharacterController;
using Unity.Mathematics;
using UnityEngine;
namespace Net.Project.B.AI
{
public abstract class NpcCharacterStates :ICharacterState
{
public virtual bool Enabled { get; set; }
public virtual void Initialize()
{
}
public virtual void OnStateEntry(IState old)
{
}
public virtual void OnStateUpdate(float deltaTime)
{
}
public virtual void OnStateExit(IState old, IState newState)
{
}
public virtual void UpdateVelocity(ref float3 currentVelocity, float deltaTime)
{
}
public virtual void UpdateRotation(ref float3 localPosition, ref quaternion currentRotation, ref quaternion viewRotation,
float deltaTime)
{
}
public virtual void BeforeUpdateVelocity(float deltaTime)
{
}
public virtual void AfterUpdateVelocity(float deltaTime)
{
}
}
public abstract class NpcCharacterMotionState:NpcCharacterStates
{
protected readonly NpcCharacterController Self;
protected NpcCharacterMotionState(NpcCharacterController self)
{
Self = self;
}
public override void UpdateVelocity(ref float3 currentVelocity, float deltaTime)
{
currentVelocity =Vector3.ProjectOnPlane( Self.NavMeshAgentController.Velocity, Vector3.up);
}
public override void UpdateRotation(ref float3 localPosition, ref quaternion currentRotation, ref quaternion viewRotation,
float deltaTime)
{
base.UpdateRotation(ref localPosition, ref currentRotation, ref viewRotation, deltaTime);
while (Self.NavMeshAgentController.QueuedDeltaRotation.TryDequeue(out var deltaRotation))
{
currentRotation *= deltaRotation;
}
}
}
public class NpcCharacterStateIdle : NpcCharacterMotionState, ICharacterStateIdle
{
public NpcCharacterStateIdle(NpcCharacterController self) : base(self)
{
}
public override void OnStateUpdate(float deltaTime)
{
if (!Self.Agent.pathPending && Self.Agent.remainingDistance > Self.Agent.stoppingDistance)
{
Self.TransitionState<ICharacterStateWalk>();
}
}
}
public class NpcCharacterStateWalk : NpcCharacterMotionState, ICharacterStateWalk
{
public NpcCharacterStateWalk(NpcCharacterController self) : base(self)
{
}
public override void OnStateUpdate(float deltaTime)
{
base.OnStateUpdate(deltaTime);
if (!Self.Agent.pathPending && Self.Agent.remainingDistance <= Self.Agent.stoppingDistance)
{
Self.TransitionState<ICharacterStateIdle>();
}
}
public override void UpdateRotation(ref float3 localPosition, ref quaternion currentRotation,
ref quaternion viewRotation,
float deltaTime)
{
var vectors = Self.Agent.path.corners;
base.UpdateRotation(ref localPosition, ref currentRotation, ref viewRotation, deltaTime);
if (Self.AllowMovement.Allow && Self.Agent.remainingDistance>Self.Agent.stoppingDistance && Self.AllowMovement.Allow && vectors.Length > 1)
{
var target = vectors[1];
var distance= Vector3.Distance(Self.Transform.position, target);
if (distance < 1 &&vectors.Length > 2)
{
target = vectors[2];
}
var dir = Vector3.ProjectOnPlane(target - Self.Transform.position, Vector3.up);
var angle = Quaternion.Angle(Quaternion.LookRotation(dir), currentRotation);
if (angle < 1) return;
var rot = Quaternion.LookRotation(dir);
rot = Quaternion.Lerp(currentRotation, rot, 8 * deltaTime);
currentRotation = rot;
}
else
{
var dir =Vector3.ProjectOnPlane( Self.Agent.destination - (Vector3)Self.Position,Vector3.up);
if(dir.sqrMagnitude<0.1f)return;
currentRotation=Quaternion.Lerp(currentRotation, Quaternion.LookRotation(dir), 8 * deltaTime);
}
}
}
public class NpcCharacterStateAnimation : NpcCharacterMotionState,ICharacterStateAnimation
{
public NpcCharacterStateAnimation(NpcCharacterController self) : base(self)
{
}
public bool AllowCollision { get; set; }
}
}