added: initial seperation of movement from gravity and rotation

This commit is contained in:
Chris
2025-08-08 15:13:48 -04:00
parent ed84c33ba1
commit 8f1edd94ed
8 changed files with 245 additions and 119 deletions

View File

@@ -0,0 +1,73 @@
using NodeCanvas.Framework;
using ParadoxNotion.Design;
using ParadoxNotion.Services;
using UnityEngine;
namespace Reset.Movement {
[Category("Reset/Movement")]
[Description("Process Y-axis movement for the agent")]
public class ProcessGravity : ActionTask<CharacterController>{
public BBParameter<Vector3> moveDirection;
public BBParameter<float> jumpPower;
public BBParameter<float> jumpPowerDecay;
[Space(5)]
public BBParameter<float> gravityAcceleration = 1f;
public BBParameter<float> gravityMax = 8f;
public BBParameter<float> gravityPower;
//Use for initialization. This is called only once in the lifetime of the task.
//Return null if init was successfull. Return an error string otherwise
protected override string OnInit() {
MonoManager.current.onLateUpdate += LateUpdate;
return null;
}
//This is called once each time the task is enabled.
//Call EndAction() to mark the action as finished, either in success or failure.
//EndAction can be called from anywhere.
protected override void OnExecute() {
}
//Called once per frame while the action is active.
protected override void OnUpdate() {
// Accelerate gravity
gravityPower.value += gravityAcceleration.value * Time.deltaTime;
gravityPower.value = Mathf.Min(gravityPower.value, gravityMax.value);
Vector3 gravityMoveDirection;
gravityMoveDirection = new(0f, jumpPower.value + (Physics.gravity.y * gravityPower.value), 0f);
// Reset gravity power when grounded
agent.Move((gravityMoveDirection) * Time.deltaTime);
if (agent.isGrounded) {
gravityPower.value = 0f;
jumpPower.value = 0f;
}
EndAction(true);
}
public void LateUpdate(){
// Decay jump power
jumpPower.value = Mathf.Lerp(jumpPower.value, 0f, jumpPowerDecay.value * Time.deltaTime);
}
//Called when the task is disabled.
protected override void OnStop() {
}
//Called when the task is paused.
protected override void OnPause() {
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 5531fbd949d33204690c98dd89a5e97f

View File

@@ -6,9 +6,9 @@ using ParadoxNotion.Services;
using Unity.Cinemachine;
using Unity.Mathematics;
using UnityEngine;
using Reset.Player.Movement;
using Reset.Movement;
namespace Reset.Player.Movement{
namespace Reset.Movement{
public enum PlayerFacingDirection{
Target = 0,
Movement,
@@ -25,40 +25,30 @@ namespace NodeCanvas.Tasks.Actions {
public class ProcessMovement : ActionTask<CharacterController>{
public BBParameter<Vector3> groundMoveDirection;
public BBParameter<Vector3> airMoveDirection;
[Space(5)]
public BBParameter<float> gravityAcceleration = 1f;
public BBParameter<float> gravityMax = 8f;
public BBParameter<float> jumpPower;
public BBParameter<float> jumpPowerDecay;
// Rotation
public BBParameter<PlayerFacingDirection> playerFacingDirection;
[ShowIf("playerFacingDirection", 0)]
public Vector3 rotationTargetPosition;
public BBParameter<float> rotationSpeed = 5f;
public BBParameter<float> rotationSmoothing;
private float currentRotSpeed;
private float lastLookMagnitude;
private Quaternion targetRotation;
private Vector3 currentMoveDir;
// References
private PlayerControls controls;
public BBParameter<float> gravityPower;
//Use for initialization. This is called only once in the lifetime of the task.
//Return null if init was successfull. Return an error string otherwise
protected override string OnInit() {
// Append the late update method to actually happen on late update
MonoManager.current.onLateUpdate += LateUpdate;
// Set ingitial rotation power
currentRotSpeed = rotationSpeed.value;
// Reference to controls
controls = agent.GetComponent<PlayerControls>();
@@ -75,88 +65,45 @@ namespace NodeCanvas.Tasks.Actions {
//Called once per frame while the action is active.
protected override void OnUpdate(){
// Accelerate gravity
gravityPower.value += gravityAcceleration.value * Time.deltaTime;
gravityPower.value = Mathf.Min(gravityPower.value, gravityMax.value);
// Calculate rotation speed
currentRotSpeed = Mathf.Lerp(currentRotSpeed, rotationSpeed.value, rotationSmoothing.value * Time.deltaTime);
switch (playerFacingDirection.value) {
case PlayerFacingDirection.Target:
// Set rotation to just the direction of the target
targetRotation = Quaternion.LookRotation((agent.transform.position.DirectionTo(rotationTargetPosition)).Flatten(null, 0, null));
break;
case PlayerFacingDirection.Movement:
// Check magnitude to avoid the "Look rotation viewing vector is zero" debug
// Set desired rotation to input direction, with respect to camera rotation
if (agent.isGrounded){
if (controls.rawMoveInput.magnitude == 0) { break; }
targetRotation = Quaternion.LookRotation(currentMoveDir) *
Quaternion.Euler(Camera.main.transform.rotation.eulerAngles.Flatten(0f, null, 0f));
} else {
if (airMoveDirection.value.magnitude == 0) { break; }
targetRotation = Quaternion.LookRotation(airMoveDirection.value);
}
break;
case PlayerFacingDirection.MatchCamera:
// Craft a new rotation that flattens the camera's rotation to the ground
// Needed to keep the character from inheriting the camera's height-rotation
targetRotation = Quaternion.Euler(Camera.main.transform.rotation.eulerAngles.Flatten(0, null, 0));
break;
case PlayerFacingDirection.Static:
targetRotation = agent.transform.rotation;
break;
}
// Construct move direction
Vector3 finalMoveDir = Vector3.zero;
Vector3 gravityMoveDirection;
// Change how input is managed based on facing state
currentMoveDir = Vector3.Slerp(currentMoveDir, groundMoveDirection.value, currentRotSpeed * Time.deltaTime);
currentMoveDir = Vector3.Slerp(currentMoveDir, groundMoveDirection.value, 1f * Time.deltaTime); // NOTE: This used to be t: currentRotSpeed * Time.deltaTime.
// See how it feels with a hard set value and go fro there.
// Add input movement
if (agent.isGrounded){
finalMoveDir += currentMoveDir + Vector3.down * .03f;
gravityMoveDirection = new(0f, jumpPower.value + (Physics.gravity.y *.3f), 0f);
finalMoveDir += currentMoveDir; // + Vector3.down * .03f;
} else {
finalMoveDir += airMoveDirection.value;
gravityMoveDirection = new(0f, jumpPower.value + Physics.gravity.y * gravityPower.value, 0f);
finalMoveDir += currentMoveDir;
}
// Reset gravity power when grounded
if (agent.isGrounded) {
gravityPower.value = 0f;
switch (playerFacingDirection.value) {
}
finalMoveDir += new Vector3(controls.rawMoveInput.x, 0f, controls.rawMoveInput.y);
// Do final movement
if (agent.isGrounded) {
agent.Move((Quaternion.Euler(Camera.main.transform.rotation.eulerAngles.Flatten(0f, null, 0f)) * finalMoveDir + gravityMoveDirection) * Time.deltaTime);
agent.Move((Quaternion.Euler(Camera.main.transform.rotation.eulerAngles.Flatten(0f, null, 0f)) * finalMoveDir) * Time.deltaTime);
} else {
agent.Move((finalMoveDir + gravityMoveDirection) * Time.deltaTime);
agent.Move((Quaternion.Euler(Camera.main.transform.rotation.eulerAngles.Flatten(0f, null, 0f)) * finalMoveDir) * Time.deltaTime);
// agent.Move((finalMoveDir) * Time.deltaTime);
}
// Set final rotation
agent.transform.rotation = Quaternion.Lerp(agent.transform.rotation, targetRotation, 10f * Time.deltaTime).Flatten(0, null, 0);
// ???? Moved this above but don't remember if this needs to be here still
if (agent.isGrounded) {
jumpPower.value = 0f;
}
// if (agent.isGrounded) {
// jumpPower.value = 0f;
// }
EndAction(true);
}
// Gravity is processed in LateUpdate (added to MonoManager's onLateUpdate in OnInit())
public void LateUpdate(){
// Decay jump power
jumpPower.value = Mathf.Lerp(jumpPower.value, 0f, jumpPowerDecay.value * Time.deltaTime);
}
//Called when the task is disabled.
protected override void OnStop() {

View File

@@ -0,0 +1,102 @@
using NodeCanvas.Framework;
using ParadoxNotion.Design;
using Reset.Movement;
using UnityEngine;
using UnityEngine.TextCore.Text;
namespace Reset.Player.Movement {
[Category("Reset/Movement")]
[Description("Finalizes the character rotation and commits it to the Transform")]
public class ProcessRotation : ActionTask<CharacterController> {
// Rotation
public BBParameter<Vector3> moveDirection;
public BBParameter<PlayerFacingDirection> playerFacingDirection;
public BBParameter<float> rotationSpeed = 5f;
public BBParameter<float> rotationSmoothing;
private Vector3 currentMoveDir;
private PlayerControls controls;
private Quaternion targetRotation;
private float currentRotSpeed;
[ShowIf("playerFacingDirection", 0)]
public Vector3 rotationTargetPosition;
//Use for initialization. This is called only once in the lifetime of the task.
//Return null if init was successfull. Return an error string otherwise
protected override string OnInit() {
controls = agent.GetComponent<PlayerControls>();
return null;
}
//This is called once each time the task is enabled.
//Call EndAction() to mark the action as finished, either in success or failure.
//EndAction can be called from anywhere.
protected override void OnExecute() {
}
//Called once per frame while the action is active.
protected override void OnUpdate() {
// Calculate rotation speed
currentRotSpeed = Mathf.Lerp(currentRotSpeed, rotationSpeed.value, rotationSmoothing.value * Time.deltaTime);
// Set ingitial rotation power
currentRotSpeed = rotationSpeed.value;
switch (playerFacingDirection.value) {
case PlayerFacingDirection.Target:
// Set rotation to just the direction of the target
targetRotation = Quaternion.LookRotation((agent.transform.position.DirectionTo(rotationTargetPosition)).Flatten(null, 0));
break;
case PlayerFacingDirection.Movement:
// Check magnitude to avoid the "Look rotation viewing vector is zero" debug
// Set desired rotation to input direction, with respect to camera rotation
if (agent.isGrounded){
if (controls.rawMoveInput.magnitude == 0) { break; }
targetRotation = Quaternion.LookRotation(currentMoveDir) *
Quaternion.Euler(Camera.main.transform.rotation.eulerAngles.Flatten(0f, null, 0f));
} else {
if (moveDirection.value.magnitude == 0) { break; }
targetRotation = Quaternion.LookRotation(moveDirection.value);
}
break;
case PlayerFacingDirection.MatchCamera:
// Craft a new rotation that flattens the camera's rotation to the ground
// Needed to keep the character from inheriting the camera's height-rotation
targetRotation = Quaternion.Euler(Camera.main.transform.rotation.eulerAngles.Flatten(0, null, 0));
break;
case PlayerFacingDirection.Static:
targetRotation = agent.transform.rotation;
break;
}
// Set final rotation
agent.transform.rotation = Quaternion.Lerp(agent.transform.rotation, targetRotation, 10f * Time.deltaTime).Flatten(0, null, 0);
EndAction(true);
}
//Called when the task is disabled.
protected override void OnStop() {
}
//Called when the task is paused.
protected override void OnPause() {
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 7a0fd0ebfb8888b4e8ab4c81fb3aa6c0

View File

@@ -1,7 +1,7 @@
using System;
using NodeCanvas.Framework;
using ParadoxNotion.Design;
using Reset.Player.Movement;
using Reset.Movement;
using UnityEngine;
namespace NodeCanvas.Tasks.Actions {