BITFALL/Assets/Artists/Scripts/Entity/KinematicMovement/KinematicMovementStates/Idle.cs

230 lines
8.7 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BITKit;
using BITFALL.Entites;
using KinematicCharacterController;
using BITKit.StateMachine;
using UnityEngine.InputSystem;
using BITKit.Animations;
using BITKit.Sensors;
using BITKit.Entities;
namespace BITFALL.Entites.KinematicMovementStates
{
[System.Serializable]
public class Movement : KinematicMovementState
{
public UnityAnimator animator;
[SerializeReference, SubclassSelector] public IClosePoint closePoint;
public override void OnStateEnter(IState old)
{
base.OnStateEnter(old);
}
public override void OnStateExit(IState old, IState newState)
{
base.OnStateExit(old, newState);
}
public override void BeforeCharacterUpdate(float deltaTime)
{
if (controller.runState.shouldBe && controller.runState.being is false)
{
controller.runState.Release();
controller
.entity
.Invoke<IMovementCallback>(new OnRunCallback()
{
started = true
});
}
if (controller.moveInput.z is 0 || controller.runState.shouldBe is false)
{
var input = controller.entity.Get<InputAction.CallbackContext>(nameof(controller.OnRun));
if (input.performed)
{
}
else
{
controller.runState.Reset();
controller
.entity
.Invoke<IMovementCallback>(new OnRunCallback()
{
canceled = true
});
}
}
if (controller.jumpState.shouldBe)
{
if (closePoint.TryGetClosePoint(out var pos))
{
controller.matchTargetPosition = pos;
TransitionState<ClimbBox>();
controller.jumpState.Reset();
}
else if (controller.groundState.being is false)
{
controller.jumpState.Reset();
}
}
else
{
controller.jumpState.Reset();
}
controller.crouchState.Release();
}
public override void AfterCharacterUpdate(float deltaTime)
{
var veloctiy = motor.BaseVelocity; veloctiy.y = 0;
var sqrMagnitude = veloctiy.sqrMagnitude;
var nextState = (controller.runState.being, controller.crouchState.being, controller.groundState.being) switch
{
(_, _, false) => "Air",
(_, true, _) => "Crouch",
(true, _, _) => "Run",
_ => "Movement",
};
if (animator[0].stateName != nextState)
{
switch (animator[0].fullStateName)
{
case "Run.Move":
if (nextState is "Movement")
{
//if (sqrMagnitude < 0.5f)
{
animator.Play("Movement.Stop");
break;
}
}
goto default;
default:
animator.CrossFade(nextState, 0.1f);
break;
}
}
if (controller.runState)
{
controller
.entity
.Invoke<IMovementCallback>(new OnRunCallback()
{
updated = true
});
}
}
public override void UpdateRotation(ref Quaternion currentRotation, float deltaTime)
{
var projectRotation = Quaternion.LookRotation(Vector3.ProjectOnPlane(controller.cameraRoot.forward, Vector3.up));
var rotSpeed = 720;
currentRotation =
Quaternion.RotateTowards(
currentRotation,
projectRotation,
rotSpeed * deltaTime
);
}
public override void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime)
{
var _moveVelocity = Quaternion.Euler(controller.lookInput) * controller.moveInput;
float currentVelocityMagnitude = currentVelocity.magnitude;
Vector3 effectiveGroundNormal = motor.GroundingStatus.GroundNormal;
if (currentVelocityMagnitude > 0f && motor.GroundingStatus.SnappingPrevented)
{
// Take the normal from where we're coming from
Vector3 groundPointToCharacter = motor.TransientPosition - motor.GroundingStatus.GroundPoint;
if (Vector3.Dot(currentVelocity, groundPointToCharacter) >= 0f)
{
effectiveGroundNormal = motor.GroundingStatus.OuterGroundNormal;
}
else
{
effectiveGroundNormal = motor.GroundingStatus.InnerGroundNormal;
}
}
if (motor.GroundingStatus.FoundAnyGround)
{
if (controller.jumpState.shouldBe)
{
controller.jumpState.Reset();
motor.ForceUnground();
currentVelocity += Vector3.up * 8;
controller.entity.Invoke<string>(Constant.Animation.Play, controller._jump);
}
Vector3 inputRight = Vector3.Cross(_moveVelocity, motor.CharacterUp);
Vector3 reorientedInput = Vector3.Cross(effectiveGroundNormal, inputRight).normalized * _moveVelocity.magnitude;
Vector3 targetMovementVelocity = reorientedInput * controller._moveSpeed;
// Smooth movement Velocity
currentVelocity = Vector3.Lerp(currentVelocity, targetMovementVelocity, 1f - Mathf.Exp(-16 * deltaTime));
}
// Air movement
else
{
// Add move input
if (_moveVelocity.sqrMagnitude > 0f)
{
Vector3 addedVelocity = _moveVelocity * 3 * deltaTime;
Vector3 currentVelocityOnInputsPlane = Vector3.ProjectOnPlane(currentVelocity, motor.CharacterUp);
// Limit air velocity from inputs
if (currentVelocityOnInputsPlane.magnitude < 5)
{
// clamp addedVel to make total vel not exceed max vel on inputs plane
Vector3 newTotal = Vector3.ClampMagnitude(currentVelocityOnInputsPlane + addedVelocity, 5);
addedVelocity = newTotal - currentVelocityOnInputsPlane;
}
else
{
// Make sure added vel doesn't go in the direction of the already-exceeding velocity
if (Vector3.Dot(currentVelocityOnInputsPlane, addedVelocity) > 0f)
{
addedVelocity = Vector3.ProjectOnPlane(addedVelocity, currentVelocityOnInputsPlane.normalized);
}
}
// Prevent air-climbing sloped walls
if (motor.GroundingStatus.FoundAnyGround)
{
if (Vector3.Dot(currentVelocity + addedVelocity, addedVelocity) > 0f)
{
Vector3 perpenticularObstructionNormal = Vector3.Cross(Vector3.Cross(motor.CharacterUp, motor.GroundingStatus.GroundNormal), motor.CharacterUp).normalized;
addedVelocity = Vector3.ProjectOnPlane(addedVelocity, perpenticularObstructionNormal);
}
}
// Apply added velocity
currentVelocity += addedVelocity;
controller.currentGravity = Mathf.Min(controller.currentGravity, motor.Velocity.y);
}
// Gravity
currentVelocity += -Vector3.up * 30 * deltaTime;
// Drag
currentVelocity *= (1f / (1f + (0.1f * deltaTime)));
}
}
public override void OnCancelMovement(IMovementCancelAction action)
{
switch (action)
{
case CancelMovement:
break;
case CancelRunOrSprint:
controller.runState.shouldBe = false;
break;
}
}
}
}