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

199 lines
6.0 KiB
C#

using System;
using System.Collections.Generic;
using System.Data;
using BITKit;
using BITKit.Entities;
using Microsoft.Extensions.DependencyInjection;
using Net.Project.B.Health;
using NodeCanvas.Framework;
using Project.B.CharacterController;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.AI;
namespace Net.Project.B.AI
{
public class NpcCharacterController : ICharacterController,IDisposable
{
private readonly IEntity _entity;
private static readonly HashSet<int> Created = new();
internal readonly IHealthComponent HealthComponent;
internal readonly UnityNavMeshAgentController NavMeshAgentController;
internal readonly Animator Animator;
internal readonly NavMeshAgent Agent;
internal readonly Transform Transform;
public ICharacterState CurrentState { get; private set; }
public event Action<ICharacterState, ICharacterState> OnStateChanged;
private readonly IServiceProvider _serviceProvider;
private readonly IFixedTicker _fixedTicker;
private readonly IBlackboard _blackboard;
private bool _isDisposed;
public NpcCharacterController(IServiceProvider serviceProvider, IFixedTicker fixedTicker, NavMeshAgent agent, Transform transform, Animator animator, IBlackboard blackboard, IHealthComponent healthComponent, IEntity entity)
{
if (Created.Add(entity.Id) is false)
{
throw new DuplicateNameException();
}
_serviceProvider = serviceProvider;
_fixedTicker = fixedTicker;
Agent = agent;
Transform = transform;
Animator = animator;
_blackboard = blackboard;
HealthComponent = healthComponent;
_entity = entity;
_fixedTicker.Add(UpdateState);
Agent.updateRotation = false;
Agent.updatePosition = false;
NavMeshAgentController = Transform.GetComponent<UnityNavMeshAgentController>();
AllowMovement.AddElement(8964189);
HealthComponent.OnHealthChanged += (x, y) =>
{
AllowMovement.SetDisableElements(HealthComponent,y<0);
};
AllowMovement.AddListener(x =>
{
if(x)
{
TransitionState<ICharacterStateIdle>();
}
else
{
DisposeState();
}
agent.isStopped = !x;
});
}
public ICharacterState TransitionState<TState>() where TState : ICharacterState
{
if (_isDisposed) return null;
var state = _serviceProvider.GetRequiredService<TState>();
var newState= TransitionState(state);
return newState;
}
public ICharacterState TransitionState(ICharacterState state)
{
AllowMovement.SetElements(this,state is not null);
var current = CurrentState;
CurrentState = state;
OnStateChanged?.Invoke(current, state);
return state;
}
public bool Enabled { get; set; }
public event Action<ICharacterState> OnStateRegistered;
public event Action<ICharacterState> OnStateUnRegistered;
public IDictionary<Type, ICharacterState> StateDictionary { get; }
public void Initialize()
{
}
public void UpdateState(float deltaTime)
{
if (AllowMovement.Allow is false)
{
if (HealthComponent.HealthPoint < 0)
{
}
else
{
}
return;
}
if(!Agent.isActiveAndEnabled)return;
CurrentState?.OnStateUpdate(deltaTime);
if (CurrentState is not null)
{
float3 velocity = Agent.desiredVelocity;
quaternion rotation = Transform.rotation;
quaternion viewRotation = rotation;
float3 position = Transform.position;
CurrentState.BeforeUpdateVelocity(deltaTime);
CurrentState.UpdateVelocity(ref velocity, deltaTime);
CurrentState.AfterUpdateVelocity(deltaTime);
CurrentState.UpdateRotation(ref position, ref rotation, ref viewRotation, deltaTime);
Agent.velocity = velocity;
if (Agent.enabled)
{
Transform.position = Agent.nextPosition;
}
Transform.rotation = rotation;
}
}
public void DisposeState()
{
TransitionState(null);
Agent.velocity = Velocity= default;
}
public ValidHandle AllowMovement { get; } = new();
public float Height => Agent.height;
public float3 Center { get; }
public float3 Position
{
get => Transform.position;
set
{
Agent.Warp(value);
Transform.position = value;
}
}
public float3 Velocity
{
get => Agent.velocity;
set => Agent.velocity = value;
}
public float3 ViewPosition => Position + (float3)Vector3.up;
public float3 AngularVelocity { get; }
public quaternion Rotation
{
get => Transform.rotation;
set => Transform.rotation = value;
}
public quaternion ViewRotation { get; set; }
public float3 SelfVelocity { get; set; }
public bool IsGrounded { get; }
public event Action<float3, float> OnLand;
public void Dispose()
{
_isDisposed = true;
_fixedTicker.Remove(UpdateState);
Created.Remove(_entity.Id);
}
}
}