change: fixing of many issues in handler, deprecation/deletion of variables, cleanup of UnitMovementHandler, cleaning up of inspector

This commit is contained in:
Chris
2025-09-23 14:14:47 -04:00
parent b21adf93e2
commit bd2903a0b2
10 changed files with 445 additions and 838 deletions

View File

@@ -1,19 +1,20 @@
using System.Collections.Generic;
using UnityEngine;
using Reset.Core.Tools;
using Sirenix.OdinInspector;
namespace Reset.Units{
public class UnitMovementHandler : MonoBehaviour{
[ShowInInspector]
[ShowInInspector, InlineProperty, HideLabel, FoldoutGroup("Resolved Movement", expanded: true)]
public ResolvedMovement resolvedMovement;
[FoldoutGroup("Final Values"), ShowInInspector, ReadOnly] private float outputSpeed;
[FoldoutGroup("Final Values"), ShowInInspector, ReadOnly] private float additionalSpeed;
[FoldoutGroup("Final Values"), ShowInInspector, ReadOnly] public Vector3 outputMoveDirection;
[FoldoutGroup("Final Values"), ShowInInspector, ReadOnly] public Vector3 additionalMoveDirection;
[FoldoutGroup("Final Values"), ShowInInspector, ReadOnly] private Quaternion outputRotation;
[FoldoutGroup("Final Values"), ShowInInspector, ReadOnly] private Quaternion specifiedRotation;
[FoldoutGroup("Final Values"), ShowInInspector, ReadOnly] private float outputRotationSpeed;
[HideInInspector] public Vector3 outputMoveDirection;
[HideInInspector] public Vector3 additionalMoveDirection;
// SmoothDamp Velocities
private Quaternion refVelocityRotationSpeed;
private float refVelocityAcceleration;
private float refVelocityDeacceleration;
// Smoothing Values
private float directionChangeDotLerp;
@@ -26,112 +27,69 @@ namespace Reset.Units{
private LockOnManager lockOnManager;
// Movement Data
[ShowInInspector, PropertyOrder(2)] public UnitMovementData data = new();
[ShowInInspector, PropertyOrder(2), FoldoutGroup("Movement Data", expanded: true), InlineProperty, HideLabel] public UnitMovementData data = new();
void Awake(){
controller = GetComponent<CharacterController>();
controls = GetComponent<PlayerControls>();
lockOnManager = GetComponent<LockOnManager>();
InitAllSettings();
}
void Start(){
resolvedMovement = new ResolvedMovement();
resolvedMovement.moveDirection = new ResolvedMovement.MoveDirection(transform);
resolvedMovement = new ResolvedMovement{
moveDirection = new ResolvedMovement.MoveDirection(transform)
};
}
void Update(){
SmoothAllSettings();
UpdateCurrentDirection();
UpdateCurrentGravity();
UpdateCurrentSpeed();
// UpdateCurrentRotation();
UpdateCurrentRotation();
DoMovement();
}
// Add directly to the direction
public void AddToCurrentDirection(Vector3 inputDirection, float power){ // Old
additionalMoveDirection += inputDirection.normalized;
additionalSpeed = power;
}
public void SmoothToSpeed(float desiredSpeed, float smoothing){ // Old
additionalSpeed = Mathf.Lerp(additionalSpeed, desiredSpeed, smoothing * Time.deltaTime);
}
public void SetNewDirection(Vector3 inputDirection){ // NOTE: If smoothing desired add a default bool for smoothing maybe? // Old
additionalMoveDirection = inputDirection.Flatten(null, 0f, null);
}
public void SetNewGravity(float value){
additionalMoveDirection.y = value;
}
// Hold a new rotation to be moved to during PlayerFacingDirection.SpecifiedRotation
public void SetSpecifiedRotation(Quaternion inputRotation){ // Old
specifiedRotation = inputRotation;
}
// Blend between the current direction and an input direction, based on the current controller input
public void OverwriteDirectionFromInput(Vector2 value, float priority, float speed = Mathf.Infinity){ // Old
// Create a new direction that is the current controller input * the amount of power they should have
Vector3 dirToAdd = new Vector3(controls.rawMoveInput.x * value.x, 0f, controls.rawMoveInput.y * value.y);
// Multiply it by the current magnitude (why? i forgor)
dirToAdd *= controls.rawMoveInput.magnitude;
// Blend the existing direction into it
dirToAdd = Vector3.Lerp(outputMoveDirection, dirToAdd, priority * controls.rawMoveInput.magnitude);
// Set the new direction
outputMoveDirection = new Vector3(dirToAdd.x, outputMoveDirection.y, dirToAdd.z);
// Everthing under here is for the speed now. If it's not set do...nothing. Otherwise set it to the max value between move speed and the new speed
if (float.IsPositiveInfinity(speed)) {
return;
}
outputSpeed = Mathf.Lerp(outputSpeed, Mathf.Max(data.moveSpeed.Value, speed), priority);
}
// Setting absolute to true will cause the current gravity to snap to the new gravity value.
// Keeping it false will make it apply additively to the current gravity. Both options use relativty for linear interpolation.
public void SetNewGravity(float value, float relativity, bool absolute){ // new
if (absolute){
resolvedMovement.gravity = Mathf.Lerp(resolvedMovement.gravity, value, relativity);
} else {
resolvedMovement.gravity = Mathf.Lerp(resolvedMovement.gravity, resolvedMovement.gravity + value, relativity);
}
DebugOverlayDrawer.ChangeValue("Movement", "Move Direction (Local)", resolvedMovement.moveDirection.Local);
DebugOverlayDrawer.ChangeValue("Movement", "Move Direction (World)", resolvedMovement.moveDirection.World);
}
// Update the direction, called every frame
private void UpdateCurrentDirection(){
// Get input value
Vector2 targetDirection = new Vector2(controls.rawMoveInput.x, controls.rawMoveInput.y);
targetDirection = (Camera.main.transform.rotation * targetDirection.ToVector3()).ToVector2();
// Deadzone
if (targetDirection.magnitude < .05f) {
if (targetDirection.magnitude < .08f) {
targetDirection = Vector2.zero;
}
// Set Raw Direciton
resolvedMovement.moveDirection.RawWorld = targetDirection;
// Get current direction
Vector2 currentDirection = resolvedMovement.moveDirection.Local;
Vector2 currentDirection = resolvedMovement.moveDirection.World;
// Also need to find the dot value of the current input versus the current move direction
Vector3 slerpedValue;
Vector2 lerpedValue;
Vector2 newDirection;
float switchedDirection = Vector3.Dot(targetDirection, currentDirection);
float switchedDirectionRemapped = Mathf.Lerp(0, 1, switchedDirection);
directionChangeDotLerp = Mathf.Lerp(switchedDirection, switchedDirectionRemapped, 5f * Time.deltaTime) ; // turn that .5f into a variable
DebugOverlayDrawer.ChangeValue("Movement", "Direction Change Dot", directionChangeDotLerp);
DebugOverlayDrawer.ChangeValue("Movement", "Direction Change Dot", directionChangeDotLerp);
// Smooth movement. Use deaccel smoothing if the input magnitude is lower, and accel smoothing if it's higher
// Also checks when grounded to only use Slerp on the ground
// Also checks when grounded to only use Slerp on the ground
Vector3 slerpedValue;
Vector2 lerpedValue;
Vector2 newDirection;
if (controller.isGrounded){
slerpedValue = Vector3.Slerp(currentDirection, targetDirection, data.softening.Value * Time.deltaTime); // This used to be a slerp. If rotational movement broke this is why
slerpedValue = Vector3.Slerp(currentDirection, targetDirection, data.softening.Value * Time.deltaTime);
lerpedValue = Vector2.Lerp(currentDirection, targetDirection, data.softening.Value * Time.deltaTime);
newDirection = Vector2.Lerp(slerpedValue, lerpedValue, directionChangeDotLerp);
@@ -139,29 +97,23 @@ namespace Reset.Units{
newDirection = Vector2.Lerp(currentDirection, targetDirection, data.softening.Value * data.airDirectionDecay.Value * Time.deltaTime);
}
// newDirection = Vector2.MoveTowards(currentDirection, targetDirection.Rotate(-Vector2.Angle(currentDirection, targetDirection)), 2f * Time.deltaTime);
// Commit move direction
// resolvedMovement.moveDirection.Local = Vector2.SmoothDamp(
// resolvedMovement.moveDirection.Local,
// newDirection,
// ref smoothing.moveSmoothing.refVel,
// smoothing.moveSmoothing.smoothing *Time.deltaTime); // TODO: Check this smoothing
resolvedMovement.moveDirection.Local = newDirection;
// Commit the new direction
resolvedMovement.moveDirection.World = newDirection;
}
// Update the speed, called every frame
private void UpdateCurrentSpeed(){
float speed;
// ""Smooth"" the speed
float smoothedSpeed;
if (resolvedMovement.moveDirection.Local.magnitude < controls.rawMoveInput.magnitude) {
speed = data.moveSpeed.Value * Time.deltaTime * data.acceleration.Value;
smoothedSpeed = Mathf.MoveTowards(resolvedMovement.moveSpeed, data.moveSpeed.Value, data.acceleration.Value * Time.deltaTime);
} else {
speed = data.moveSpeed.Value * Time.deltaTime * data.deacceleration.Value;
smoothedSpeed = Mathf.MoveTowards(resolvedMovement.moveSpeed, 0f, data.deacceleration.Value * Time.deltaTime);
}
resolvedMovement.moveSpeed = speed;
// Commit the speed
resolvedMovement.moveSpeed = smoothedSpeed;
DebugOverlayDrawer.ChangeValue("Movement", "Resolved Speed", resolvedMovement.moveSpeed);
}
@@ -173,75 +125,61 @@ namespace Reset.Units{
resolvedMovement.gravity -= data.gravityAcceleration.Value * Time.deltaTime;
}
// resolvedMovement.gravity = Mathf.Clamp(resolvedMovement.gravity, Mathf.NegativeInfinity, data.gravityMax.value);
// Apply a constant gravity if the player is grounded
if (controller.isGrounded) {
// resolvedMovement.gravity = -.3f;
}
// Create the final gravity value
float gravityMoveDirection = data.jumpPower.Value + (Physics.gravity.y * resolvedMovement.gravity);
// resolvedMovement.gravity = data.jumpPower.value + (Physics.gravity.y * data.gravityPower.currentValue);
// Commit gravity to move direction, ignoring XZ since those are done in UpdateMovementDirection
outputMoveDirection.y = Mathf.SmoothDamp(outputMoveDirection.y, gravityMoveDirection, ref gravitySmoothVelocityRef, .1f * Time.deltaTime);
float gravityMoveDirection = Physics.gravity.y * resolvedMovement.gravity;
}
// Update the rotation, called every frame
private void UpdateCurrentRotation(){
// Get input value
Vector3 inputMovement = new Vector3(controls.rawMoveInput.x, 0f, controls.rawMoveInput.y);
Quaternion targetRotation = Quaternion.identity;
// Switch the desired rotation based on current movement setting
switch (data.rotateFacing) {
switch (data.rotateFacing.Value) { // TODO: Check that this isn't broken
// Just look at target
case PlayerFacingDirection.TowardsTarget:
// Look directly at the target
outputRotation = Quaternion.LookRotation(transform.position.DirectionTo(lockOnManager.mainTarget.gameObject.transform.position));
targetRotation = Quaternion.LookRotation(transform.position.DirectionTo(lockOnManager.mainTarget.gameObject.transform.position));
break;
case PlayerFacingDirection.Momentum:
// Look towards the current direction the agent is moving
if (inputMovement.magnitude > .05f){
outputRotation = Camera.main.transform.rotation * Quaternion.LookRotation(outputMoveDirection);
targetRotation = Quaternion.LookRotation(resolvedMovement.moveDirection.RawWorld.ToVector3(), Vector3.up);
}
break;
case PlayerFacingDirection.MatchForward:
// Look towards the input direction....why??? I guess cause move direction is PlayerFacingDirection.Momentum.
if (controls.rawMoveInput.magnitude < 0.05f) { break; }
outputRotation = Camera.main.transform.rotation * Quaternion.LookRotation(inputMovement);
targetRotation = Camera.main.transform.rotation * Quaternion.LookRotation(inputMovement);
break;
case PlayerFacingDirection.MatchCamera:
// Look the same direction as the camera
outputRotation = Quaternion.Euler(Camera.main.transform.rotation.eulerAngles.Flatten(0, null, 0));
targetRotation = Quaternion.Euler(Camera.main.transform.rotation.eulerAngles.Flatten(0, null, 0));
break;
case PlayerFacingDirection.Static:
// Don't change
outputRotation = transform.rotation;
break;
case PlayerFacingDirection.SpecifiedDirection:
// Look at an inputed rotation
outputRotation = specifiedRotation;
targetRotation = transform.rotation;
break;
}
DebugOverlayDrawer.ChangeValue("Rotation", "Target Rotation", targetRotation.eulerAngles);
// Add the current input into the created rotation
if (inputMovement.magnitude > .05){
outputRotation = Quaternion.Lerp(outputRotation, Camera.main.transform.rotation * Quaternion.LookRotation(inputMovement), data.rotationInputBlending.Value);
if (inputMovement.magnitude > .05) {
// Quaternion inputRot = Camera.main.transform.rotation * Quaternion.LookRotation(inputMovement);
// resolvedMovement.rotation = Quaternion.RotateTowards(resolvedMovement.rotation, targetRotation, 10f);
resolvedMovement.rotation = targetRotation;
}
// Calculate rotation speed, as in how fast the fella rotates. This value has it's own smoothing to allow for gradual increasing/decreasing of the speed till it reaches the target
outputRotationSpeed = Mathf.Lerp(outputRotationSpeed, data.rotationSpeed.Value, data.softening.Value * Time.deltaTime);
// Set final rotation
transform.rotation = Quaternion.Slerp(transform.rotation, outputRotation, outputRotationSpeed * Time.deltaTime).Flatten(0, null, 0);
transform.rotation = Quaternion.Slerp(transform.rotation, resolvedMovement.rotation, data.rotationSpeed.Value * Time.deltaTime).Flatten(0, null, 0);
}
// Move with default settings
public void DoMovement(){
DoMovement(resolvedMovement.moveDirection.Local, resolvedMovement.moveSpeed, data.gravityScale.Value); // TODO: Gets multiplied a second time in DoMovement by gravity scale????
DoMovement(resolvedMovement.moveDirection.World, resolvedMovement.moveSpeed, data.gravityScale.Value); // TODO: Gets multiplied a second time in DoMovement by gravity scale????
}
// Custom move from input
@@ -249,63 +187,100 @@ namespace Reset.Units{
// Debug.Log($"moveDir: {moveDir}, agent velocity: {transform.InverseTransformDirection(controller.velocity.normalized)}");
// Seperate the different move directions. Additonal becomes it's own because it needs to be added independently of the other two
Vector2 moveXZDir = new Vector3(moveDir.x, moveDir.y);
Vector2 moveXZDir = moveDir;
float moveYDir = resolvedMovement.gravity;
Vector3 addDir = additionalMoveDirection;
// Add their related speeds
moveXZDir *= speed * Time.deltaTime;
moveYDir *= data.gravityScale.Value * Time.deltaTime;
addDir *= additionalSpeed * Time.deltaTime;
// Construct the direction and move
Vector3 finalDir = new Vector3(moveXZDir.x, moveYDir,moveXZDir.y) ;
controller.Move((Camera.main.transform.rotation.Flatten(0, null, 0) * finalDir) + addDir);
}
void LateUpdate(){
UpdateGravityLate();
DecayAdditionalDirection();
}
void DecayAdditionalDirection(){
// Get input value
Vector3 inputMovement = new Vector3(controls.rawMoveInput.x, 0f, controls.rawMoveInput.y);
// Ignore values under deadzone
if (inputMovement.magnitude < .1f) {
inputMovement = Vector3.zero;
}
// Remove Y from variables
Vector3 currentNoY = new Vector3(additionalMoveDirection.x, 0f, additionalMoveDirection.z);
// Decay the direction
if (inputMovement.magnitude < currentNoY.magnitude) {
additionalMoveDirection = Vector3.Slerp(additionalMoveDirection, Vector3.zero,data.acceleration.Value * Time.deltaTime);
} else {
// float deaccelValue = data.deaccelerationCurve.Evaluate(inputMovement.magnitude);
additionalMoveDirection = Vector3.Lerp(additionalMoveDirection, Vector3.zero, data.deacceleration.Value * Time.deltaTime);
}
// Decay the gravity
additionalMoveDirection.y -= data.gravityPower.Value;
additionalMoveDirection.y = Mathf.Max(0f, additionalMoveDirection.y);
Vector3 finalDir = new Vector3(moveXZDir.x, moveYDir, moveXZDir.y);
controller.Move(finalDir);
}
private void UpdateGravityLate(){
// Decay jump power
data.jumpPower.Value -= data.jumpPowerDecay.Value * Time.deltaTime;
data.jumpPower.Value = Mathf.Max(0f, data.jumpPower.Value);
// Setting absolute to true will cause the current gravity to snap to the new gravity value.
// Keeping it false will make it apply additively to the current gravity. Both options use relativty for linear interpolation.
public void SetNewGravity(float value, float relativity, bool absolute){ // new
if (absolute){
resolvedMovement.gravity = Mathf.Lerp(resolvedMovement.gravity, value, relativity);
} else {
resolvedMovement.gravity = Mathf.Lerp(resolvedMovement.gravity, resolvedMovement.gravity + value, relativity);
}
}
[Button("Initialize Settings")]
public void SetNewDirection(Vector2 value, float relativity, bool absolute){ // new
if (absolute){
resolvedMovement.moveDirection.World = Vector2.Lerp(resolvedMovement.moveDirection.World, value, relativity);
} else {
resolvedMovement.moveDirection.World = Vector2.Lerp(resolvedMovement.moveDirection.World, resolvedMovement.moveDirection.World + value, relativity);
}
}
public void SetNewRawDirection(Vector2 value, float relativity, bool absolute){ // new
if (absolute){
resolvedMovement.moveDirection.RawWorld = Vector2.Lerp(resolvedMovement.moveDirection.RawWorld, value, relativity);
} else {
resolvedMovement.moveDirection.RawWorld = Vector2.Lerp(resolvedMovement.moveDirection.RawWorld, resolvedMovement.moveDirection.RawWorld + value, relativity);
}
}
public void SetNewSpeed(float value, float relativity, bool absolute){ // new
if (absolute){
resolvedMovement.moveSpeed = Mathf.Lerp(resolvedMovement.moveSpeed, value, relativity);
} else {
resolvedMovement.moveSpeed = Mathf.Lerp(resolvedMovement.moveSpeed, resolvedMovement.moveSpeed + value, relativity);
}
}
public void SetNewRotation(Quaternion value, float relativity, bool absolute){ // new
if (absolute){
resolvedMovement.rotation = Quaternion.Lerp(resolvedMovement.rotation, value, relativity);
} else {
resolvedMovement.rotation = Quaternion.Lerp(resolvedMovement.rotation, resolvedMovement.rotation * value, relativity);
}
}
[Button("Initialize Settings", ButtonHeight = 30), PropertySpace(10,5 )]
void InitAllSettings(){
var newthing = data.GetAllSettings();
var settingsList = data.GetAllSettings();
foreach (IResettableSettingValue value in settingsList) {
value.Initialize();
value.Verify();
}
}
void SmoothAllSettings(){
var settingsList = data.GetAllSettings();
foreach (IResettableSettingValue value in settingsList) {
value.SmoothAndEase();
}
}
public void AddToCurrentDirection(Vector3 inputDirection, float power){ // Old
Debug.LogError("Using an old movement command! Switch to one of the new alternatives!");
}
public void SmoothToSpeed(float desiredSpeed, float smoothing){ // Old
Debug.LogError("Using an old movement command! Switch to one of the new alternatives!");
}
public void SetNewDirection(Vector3 inputDirection){ // NOTE: If smoothing desired add a default bool for smoothing maybe? // Old
Debug.LogError("Using an old movement command! Switch to one of the new alternatives!");
}
public void SetNewGravity(float value){
Debug.LogError("Using an old movement command! Switch to one of the new alternatives!");
}
public void SetSpecifiedRotation(Quaternion inputRotation){ // Old
Debug.LogError("Using an old movement command! Switch to one of the new alternatives!");
}
public void OverwriteDirectionFromInput(Vector2 value, float priority, float speed = Mathf.Infinity){ // Old
Debug.LogError("Using an old movement command! Switch to one of the new alternatives!");
}
}
}