199 lines
6.0 KiB
C#
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);
|
|
}
|
|
}
|
|
|
|
}
|