153 lines
4.7 KiB
C#
153 lines
4.7 KiB
C#
![]() |
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; }
|
||
|
}
|
||
|
}
|