BITFALL/Assets/Artists/Scripts/Player/CharacterControllerPro/PlayerCharacterController.cs

198 lines
5.6 KiB
C#

using System;
using BITFALL.Entities.Player.Movement.States;
using BITKit;
using BITKit.Entities;
using BITKit.Entities.Physics;
using BITKit.Entities.Player;
using Lightbug.CharacterControllerPro.Core;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Interactions;
using UnityEngine.UIElements;
namespace BITFALL.Entities.Player.Movement
{
public class PlayerCharacterController : StateBasedPlayerComponent<IEntityMovementState>,IEntityMovement,IServiceRegister
{
public override Type BaseType => typeof(IEntityMovement);
[SerializeField] private CharacterActor actor;
[SerializeField] private Vector3 initialCameraPosition = new Vector3(0,0.11f,0.27f);
[SerializeField] private float initialSpeed;
[SerializeReference,SubclassSelector] private IClosePoint climbClosePoint;
[SerializeReference, SubclassSelector]
private IProvider adsProvider;
[SerializeField] private Transform cameraTransform;
public Vector3 LocomotionBasedVelocity { get;private set; }
public Vector3 Velocity => actor.Velocity;
public Vector3 GroundVelocity=>actor.GroundVelocity;
public bool IsGrounded => actor.IsGrounded;
public Vector3 MovementInput { get; private set; }
public Vector2 LookInput{ get; private set; }
public ExpectState<bool> ExpectRun;
public ExpectState<bool> ExpectJump;
public ExpectState<bool> ExpectCrouch;
public ExpectState<bool> ExpectSprint;
public ExpectState<Vector3> expectClimb;
public Vector3 CurrentCameraPosition;
private readonly ValidHandle allowMovement = new();
private IEntityPhysics physics;
private IHealth _health;
private bool isDead;
private Vector3 keepVelocity;
public override void OnAwake()
{
CurrentCameraPosition = initialCameraPosition;
_health = entity.Get<IHealth>();
_health.OnSetAlive += OnSetAlive;
physics = entity.Get<IEntityPhysics>();
physics.OnSetPhysics += OnSetPhysics;
}
private void OnSetPhysics(bool obj)
{
if (obj is false) return;
physics.Velocity = keepVelocity;
actor.Velocity = Vector3.zero;
}
private void OnSetAlive(bool obj)
{
allowMovement.SetElements(this,obj);
if (obj)
{
if (!isDead) return;
actor.Position = physics.Center;
isDead = false;
}
else
{
isDead = true;
}
}
public void SyncMovement(Vector3 velocity, Vector3 position, Quaternion rotation, bool isGrounded)
{
throw new NotImplementedException();
}
public void Movement(Vector3 relativeVector)
{
MovementInput = relativeVector;
}
public void Movement(InputAction.CallbackContext context)
{
MovementInput = context.ReadValue<Vector2>();
MovementInput = new Vector3(MovementInput.x,0,MovementInput.y);
if (!(MovementInput.z <= 0.16f)) return;
ExpectRun.Reset();
ExpectSprint.Reset();
}
public void ExecuteCommand<T>(T command)
{
foreach (var x in StateDictionary.Values)
{
x.ExecuteCommand<T>(command);
}
}
public void View(InputAction.CallbackContext context)
{
if (BITAppForUnity.AllowCursor) return;
var playerConfig = Data.Get<PlayerConfig>() ?? new PlayerConfig();
var ads = adsProvider.Get<float>();
if (ads is 0) ads = 1;
var raw = context.ReadValue<Vector2>() * playerConfig.sensitivity * playerConfig.m_yaw * ads;
var lookInput = LookInput;
lookInput.x -= raw.y;
lookInput.y += raw.x;
lookInput.x = Mathf.Clamp(lookInput.x, -80, 80);
LookInput = lookInput;
}
public void Jump(InputAction.CallbackContext context)
{
if (ExpectJump.shouldBe) return;
if (context.interaction is not null && context.started is false) return;
if (actor.IsGrounded)
ExpectJump.shouldBe = true;
ExpectCrouch.Reset();
if (climbClosePoint.TryGetClosePoint(out var closePoint))
{
expectClimb.shouldBe = closePoint;
TransitionState<Climb>();
}
}
public void Run(InputAction.CallbackContext context)
{
switch (context)
{
case { interaction: PressInteraction, started: true }:
if (ExpectRun.shouldBe)
ExpectSprint.shouldBe = true;
ExpectRun.shouldBe = true;
ExpectCrouch.Reset();
break;
case {interaction:MultiTapInteraction,performed:true}:
ExpectSprint.shouldBe = true;
ExpectCrouch.Reset();
break;
}
}
public void Crouch(InputAction.CallbackContext context)
{
if (context.interaction is not null && context.started is false) return;
if (CurrentState is Climb)
{
TransitionState<Walk>();
}
else
{
ExpectCrouch.shouldBe = !ExpectCrouch.shouldBe;
ExpectRun.Reset();
}
}
public override void OnUpdate(float deltaTime)
{
CurrentState?.BeforeUpdateMovement(deltaTime);
}
public override void OnFixedUpdate(float deltaTime)
{
var currentVelocity = actor.Velocity;
var currentRotation = actor.Rotation;
CurrentState.OnStateUpdate(deltaTime);
CurrentState?.UpdateVelocity(ref currentVelocity, deltaTime);
CurrentState?.UpdateRotation(ref currentRotation, deltaTime);
if (allowMovement && _health.IsAlive)
{
actor.Velocity = currentVelocity;
actor.Rotation = currentRotation;
if (currentVelocity.sqrMagnitude > 0.01f)
keepVelocity = currentVelocity;
}
var localVelocity = transform.InverseTransformDirection(Velocity);
localVelocity.y = 0;
LocomotionBasedVelocity = localVelocity;
}
public override void OnLateUpdate(float deltaTime)
{
if (allowMovement.Allow is false) return;
var rotation = Quaternion.Euler(LookInput);
cameraTransform.rotation = rotation;
CurrentState?.AfterUpdateMovement(deltaTime);
cameraTransform.localPosition = Vector3.Lerp(cameraTransform.localPosition,CurrentCameraPosition,5 * deltaTime);
}
}
}