2023-08-23 01:59:40 +08:00
|
|
|
using System;
|
2023-08-27 02:58:19 +08:00
|
|
|
using BITFALL.Entities.Player.Movement.States;
|
2023-09-01 14:33:54 +08:00
|
|
|
using BITFALL.Player.Movement;
|
2023-08-23 01:59:40 +08:00
|
|
|
using BITKit;
|
|
|
|
using BITKit.Entities;
|
2023-08-27 02:58:19 +08:00
|
|
|
using BITKit.Entities.Physics;
|
|
|
|
using BITKit.Entities.Player;
|
2023-08-23 01:59:40 +08:00
|
|
|
using Lightbug.CharacterControllerPro.Core;
|
2023-09-01 14:33:54 +08:00
|
|
|
using Unity.Mathematics;
|
2023-08-23 01:59:40 +08:00
|
|
|
using UnityEngine;
|
|
|
|
using UnityEngine.InputSystem;
|
|
|
|
using UnityEngine.InputSystem.Interactions;
|
2023-08-27 02:58:19 +08:00
|
|
|
using UnityEngine.UIElements;
|
2023-08-23 01:59:40 +08:00
|
|
|
|
2023-08-27 02:58:19 +08:00
|
|
|
namespace BITFALL.Entities.Player.Movement
|
2023-08-23 01:59:40 +08:00
|
|
|
{
|
2023-09-01 14:33:54 +08:00
|
|
|
[CustomType(typeof(IEntityMovement))]
|
|
|
|
[CustomType(typeof(IPlayerMovement))]
|
|
|
|
public class PlayerCharacterController : StateBasedPlayerComponent<IEntityMovementState>,IEntityMovement,IServiceRegister,IPlayerMovement
|
2023-08-23 01:59:40 +08:00
|
|
|
{
|
|
|
|
public override Type BaseType => typeof(IEntityMovement);
|
|
|
|
[SerializeField] private CharacterActor actor;
|
2023-09-01 14:33:54 +08:00
|
|
|
[SerializeField] private Vector3 initialCameraPosition = new(0,0.11f,0.27f);
|
2023-08-27 02:58:19 +08:00
|
|
|
[SerializeField] private float initialSpeed;
|
|
|
|
|
|
|
|
[SerializeReference,SubclassSelector] private IClosePoint climbClosePoint;
|
2023-08-23 01:59:40 +08:00
|
|
|
|
|
|
|
[SerializeReference, SubclassSelector]
|
|
|
|
private IProvider adsProvider;
|
|
|
|
|
|
|
|
[SerializeField] private Transform cameraTransform;
|
2023-09-01 14:33:54 +08:00
|
|
|
public Vector3 ViewCenter { get; set; }
|
|
|
|
public Quaternion ViewRotation { get; set; }
|
2023-08-27 02:58:19 +08:00
|
|
|
public Vector3 LocomotionBasedVelocity { get;private set; }
|
2023-08-23 01:59:40 +08:00
|
|
|
public Vector3 Velocity => actor.Velocity;
|
|
|
|
public Vector3 GroundVelocity=>actor.GroundVelocity;
|
2023-09-01 14:33:54 +08:00
|
|
|
public Vector3 AngularVelocity { get;private set; }
|
2023-08-23 01:59:40 +08:00
|
|
|
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;
|
2023-08-27 02:58:19 +08:00
|
|
|
public ExpectState<Vector3> expectClimb;
|
2023-08-23 01:59:40 +08:00
|
|
|
public Vector3 CurrentCameraPosition;
|
2023-08-27 02:58:19 +08:00
|
|
|
private readonly ValidHandle allowMovement = new();
|
2023-09-01 14:33:54 +08:00
|
|
|
private readonly ValidHandle allowRun = new();
|
2023-08-27 02:58:19 +08:00
|
|
|
private IEntityPhysics physics;
|
|
|
|
private IHealth _health;
|
|
|
|
private bool isDead;
|
|
|
|
private Vector3 keepVelocity;
|
2023-08-23 01:59:40 +08:00
|
|
|
public override void OnAwake()
|
|
|
|
{
|
|
|
|
CurrentCameraPosition = initialCameraPosition;
|
2023-08-27 02:58:19 +08:00
|
|
|
_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);
|
2023-09-01 14:33:54 +08:00
|
|
|
allowRun.SetElements(this,obj);
|
2023-08-27 02:58:19 +08:00
|
|
|
if (obj)
|
|
|
|
{
|
|
|
|
if (!isDead) return;
|
|
|
|
actor.Position = physics.Center;
|
|
|
|
isDead = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
isDead = true;
|
|
|
|
}
|
2023-08-23 01:59:40 +08:00
|
|
|
}
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2023-09-01 14:33:54 +08:00
|
|
|
public void ExecuteCommand<T>(T command=default)
|
2023-08-23 01:59:40 +08:00
|
|
|
{
|
|
|
|
foreach (var x in StateDictionary.Values)
|
|
|
|
{
|
|
|
|
x.ExecuteCommand<T>(command);
|
|
|
|
}
|
2023-09-01 14:33:54 +08:00
|
|
|
switch (command)
|
|
|
|
{
|
|
|
|
case PlayerEnableRunCommand enableRunCommand:
|
|
|
|
allowRun.RemoveDisableElements(enableRunCommand.Lock);
|
|
|
|
ExpectRun.Reset();
|
|
|
|
ExpectSprint.Reset();
|
|
|
|
break;
|
|
|
|
case PlayerDisableRunCommand disableRunCommand:
|
|
|
|
allowRun.AddDisableElements(disableRunCommand.Lock);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
OnCommand?.Invoke(command);
|
2023-08-23 01:59:40 +08:00
|
|
|
}
|
2023-09-01 14:33:54 +08:00
|
|
|
public event Action<object> OnCommand;
|
2023-08-23 01:59:40 +08:00
|
|
|
|
|
|
|
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;
|
2023-09-01 14:33:54 +08:00
|
|
|
|
|
|
|
AngularVelocity = new Vector3
|
|
|
|
(
|
|
|
|
raw.y,
|
|
|
|
-raw.x
|
|
|
|
);
|
2023-08-23 01:59:40 +08:00
|
|
|
}
|
|
|
|
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();
|
2023-08-27 02:58:19 +08:00
|
|
|
if (climbClosePoint.TryGetClosePoint(out var closePoint))
|
|
|
|
{
|
|
|
|
expectClimb.shouldBe = closePoint;
|
|
|
|
TransitionState<Climb>();
|
|
|
|
}
|
2023-08-23 01:59:40 +08:00
|
|
|
}
|
|
|
|
public void Run(InputAction.CallbackContext context)
|
|
|
|
{
|
2023-09-01 14:33:54 +08:00
|
|
|
if (allowRun.Allow is false) return;
|
2023-08-23 01:59:40 +08:00
|
|
|
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;
|
2023-08-27 02:58:19 +08:00
|
|
|
if (CurrentState is Climb)
|
|
|
|
{
|
|
|
|
TransitionState<Walk>();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ExpectCrouch.shouldBe = !ExpectCrouch.shouldBe;
|
|
|
|
ExpectRun.Reset();
|
|
|
|
}
|
2023-08-23 01:59:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
public override void OnUpdate(float deltaTime)
|
|
|
|
{
|
|
|
|
CurrentState?.BeforeUpdateMovement(deltaTime);
|
|
|
|
}
|
2023-08-27 02:58:19 +08:00
|
|
|
|
2023-08-23 01:59:40 +08:00
|
|
|
public override void OnFixedUpdate(float deltaTime)
|
|
|
|
{
|
|
|
|
var currentVelocity = actor.Velocity;
|
|
|
|
var currentRotation = actor.Rotation;
|
2023-08-27 02:58:19 +08:00
|
|
|
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;
|
2023-08-23 01:59:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
public override void OnLateUpdate(float deltaTime)
|
|
|
|
{
|
2023-08-27 02:58:19 +08:00
|
|
|
if (allowMovement.Allow is false) return;
|
2023-08-23 01:59:40 +08:00
|
|
|
var rotation = Quaternion.Euler(LookInput);
|
|
|
|
cameraTransform.rotation = rotation;
|
|
|
|
CurrentState?.AfterUpdateMovement(deltaTime);
|
|
|
|
cameraTransform.localPosition = Vector3.Lerp(cameraTransform.localPosition,CurrentCameraPosition,5 * deltaTime);
|
2023-09-01 14:33:54 +08:00
|
|
|
|
|
|
|
ViewCenter = cameraTransform.position;
|
|
|
|
ViewRotation = rotation;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void AddViewEuler(float2 euler)
|
|
|
|
{
|
|
|
|
LookInput = new Vector3
|
|
|
|
{
|
|
|
|
x = LookInput.x + euler.x,
|
|
|
|
y = LookInput.y + euler.y
|
|
|
|
};
|
2023-08-23 01:59:40 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|