230 lines
8.7 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
} |