BITFALL/Assets/Artists/Scripts/Entities/Movement/MotionBasedMovement.cs

205 lines
5.1 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Animancer;
using BITFALL.Movement.MotionBased.States;
using BITKit;
using BITKit.Entities;
using BITKit.StateMachine;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.InputSystem;
namespace BITFALL.Movement.MotionBased
{
public interface IMotionBasedState : IEntityMovementState
{
void OnAnimatorMove();
}
public interface IMotionBasedAnimationState:ICloneable
{
}
public interface IMotionBasedAnimationClip{}
public abstract class MotionBasedAnimationState
{
}
[CustomType(typeof(MotionBasedMovement))]
public sealed class MotionBasedMovement : StateBasedBehavior<IMotionBasedState>,IEntityMovement
{
[SerializeField] private NavMeshAgent agent;
[SerializeField] private AnimancerComponent animancerComponent;
[Inject] private IEntityOverride _override;
[Inject] private IHealth _health;
private bool _isAnimatorRoot;
public override void Initialize(IEntity entity)
{
if (entity is IUnityEntity _unityEntity)
{
_unityEntity.AddService(animancerComponent);
_unityEntity.AddService(agent);
}
base.Initialize(entity);
}
public override void OnStart()
{
base.OnStart();
agent.updatePosition = false;
agent.updateRotation = false;
_health.OnSetAlive += OnSetAlive;
_override.OnOverride += OnOverride;
_isAnimatorRoot = animancerComponent.Animator.transform == transform;
}
private void OnSetAlive(bool obj)
{
if (obj)
{
TransitionState<Walk>();
}
else
{
TransitionState<Empty>();
}
}
private void OnOverride(bool obj)
{
agent.isStopped = obj;
}
public override void OnFixedUpdate(float deltaTime)
{
if (_override.IsOvering) return;
if (_health.IsAlive is false) return;
base.OnFixedUpdate(deltaTime);
CurrentState?.BeforeUpdateMovement(deltaTime);
UpdateState(deltaTime);
var currentVelocity = agent.velocity;
var currentRotation = agent.transform.rotation;
if (CurrentState is not null)
{
CurrentState.UpdateVelocity(ref currentVelocity, deltaTime);
CurrentState.UpdateRotation(ref currentRotation, deltaTime);
agent.velocity = currentVelocity;
agent.transform.rotation = currentRotation;
}
CurrentState?.AfterUpdateMovement(deltaTime);
}
private void OnAnimatorMove()
{
if (_override.IsOvering)
{
var animatorTransform = animancerComponent.Animator.transform;
animancerComponent.Animator.ApplyBuiltinRootMotion();
if (_isAnimatorRoot is false)
{
Position = animatorTransform.position;
Rotation = animatorTransform.rotation;
animatorTransform.localPosition = default;
animatorTransform.localRotation = default;
}
agent.velocity = animancerComponent.Animator.velocity;
}
else
{
CurrentState?.OnAnimatorMove();
}
}
IEntityMovementState IStateMachine<IEntityMovementState>.CurrentState
{
get => CurrentState;
set => CurrentState = value as IMotionBasedState;
}
event Action<IEntityMovementState, IEntityMovementState> IStateMachine<IEntityMovementState>.OnStateChanged
{
add => OnStateChanged += value;
remove => OnStateChanged -= value;
}
IDictionary<Type, IEntityMovementState> IStateMachine<IEntityMovementState>.StateDictionary => throw new NotImplementedException();
void IStateMachine<IEntityMovementState>.Initialize()=> throw new NotImplementedException();
void IStateMachine<IEntityMovementState>.TransitionState<State>()
{
var state = StateDictionary[typeof(State)];
TransitionState(state);
}
void IStateMachine<IEntityMovementState>.TransitionState(IEntityMovementState state)
{
TransitionState(state as IMotionBasedState);
}
public Vector3 Position
{
get => Transform.position;
set => Transform.position = value;
}
public Quaternion Rotation
{
get => Transform.rotation;
set => Transform.rotation = value;
}
public Vector3 Forward => Rotation * Vector3.forward;
Vector3 IEntityMovement.ViewForward => Transform.forward;
Vector3 IEntityMovement.ViewCenter { get; } = Vector3.up;
Vector3 IEntityMovement.FocusPoint { get; } = Vector3.up;
Quaternion IEntityMovement.ViewRotation => Rotation;
Vector3 IEntityMovement.LocomotionBasedVelocity => Transform.InverseTransformPoint(agent.velocity);
Vector3 IEntityMovement.Velocity => agent.velocity;
Vector3 IEntityMovement.GroundVelocity => agent.velocity;
Vector3 IEntityMovement.AngularVelocity => throw new NotImplementedException();
bool IEntityMovement.IsGrounded => agent.isOnOffMeshLink;
void IEntityMovement.SyncMovement(Vector3 velocity, Vector3 position, Quaternion rotation, bool isGrounded)
{
throw new NotImplementedException();
}
void IEntityMovement.OnMovement(Vector3 relativeVector)
{
throw new NotImplementedException();
}
void IEntityMovement.OnMovement(InputAction.CallbackContext context)
{
throw new NotImplementedException();
}
void IEntityMovement.ExecuteCommand<T>(T command = default)
{
OnCommand?.Invoke(command);
}
public event Action<object> OnCommand;
}
}