added: movement settings changing within graph

This commit is contained in:
Chris
2025-08-13 17:04:40 -04:00
parent 7355d0c0fa
commit 524fa610f2
6 changed files with 721 additions and 342 deletions

View File

@@ -1,11 +1,10 @@
using NodeCanvas.Framework; using NodeCanvas.Framework;
using ParadoxNotion.Design; using ParadoxNotion.Design;
using Reset.Core;
using Unity.Cinemachine; using Unity.Cinemachine;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
namespace NodeCanvas.Tasks.Actions { namespace NodeCanvas.Tasks.Actions {
[Category("Reset")] [Category("Reset")]
[Description("Change Cinemachine camera settings for the player")] [Description("Change Cinemachine camera settings for the player")]

View File

@@ -0,0 +1,214 @@
using System;
using NodeCanvas.Framework;
using ParadoxNotion.Design;
using Reset.Units;
using UnityEngine;
namespace Reset.Core {
[Category("Reset")]
[Description("Commits movement unit changes to the handler.")]
public class ChangeMovementSettings : ActionTask<UnitMovementHandler> {
//Use for initialization. This is called only once in the lifetime of the task.
// Move Speed
[ParadoxNotion.Design.Header("Speed")]
public FloatValueGroup moveSpeedTarget = new (newLabel: "Move Speed");
public FloatValueGroup moveSpeedSoothing = new (newLabel: "Move Speed Smoothing");
[ParadoxNotion.Design.Header("Speed")]
public Vector3ValueGroup feedNewDirection = new Vector3ValueGroup("Feed New Direction");
public float newDirectionPower;
public FloatValueGroup accelerationSmoothing = new (newLabel: "Acceleration Smoothing");
public FloatValueGroup deaccelerationSmoothing = new (newLabel: "Deacceleration Smoothing");
public CurveValueGroup deaccelerationCurve = new (newLabel: "Deacceleration Curve");
// Jumping
[ParadoxNotion.Design.Header("Jumping")]
public FloatValueGroup jumpPower = new (newLabel: "Jump Power");
public FloatValueGroup jumpPowerDecay = new (newLabel: "Jump Decay Speed");
// Gravity
[ParadoxNotion.Design.Header("Gravity")]
public FloatValueGroup gravityPower = new (newLabel: "Gravity Power");
public FloatValueGroup gravityMax = new (newLabel: "Gravity Max");
public FloatValueGroup gravityAcceleration = new (newLabel: "Gravity Acceleration Speed");
public FloatValueGroup gravityScale = new (newLabel: "Gravity Scale");
// Rotation
[ParadoxNotion.Design.Header("Rotation")]
public EnumValueGroup rotateFacing = new EnumValueGroup("Facing Direction", PlayerFacingDirection.TowardsTarget);
public FloatValueGroup rotationSpeedTarget = new (newLabel: "Rotation Speed");
public FloatValueGroup rotationSmoothing = new (newLabel: "Rotation Smoothing");
public BBParameter<Vector3> feedNewRotation;
public BBParameter<Vector3> feedRelativeTo;
public Space rotationRelativeSpace;
private Vector3 feedDir;
//Return null if init was successfull. Return an error string otherwise
protected override string OnInit() {
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() {
UpdateFloatValue(accelerationSmoothing, ref agent.data.accelerationSmoothing, ref agent.defaultData.accelerationSmoothing);
UpdateFloatValue(deaccelerationSmoothing, ref agent.data.deaccelerationSmoothing, ref agent.defaultData.deaccelerationSmoothing);
UpdateCurveProperty(deaccelerationCurve, ref agent.data.deaccelerationCurve, ref agent.defaultData.deaccelerationCurve);
UpdateFloatValue(moveSpeedTarget, ref agent.data.moveSpeedTarget, ref agent.defaultData.moveSpeedTarget);
UpdateFloatValue(moveSpeedSoothing, ref agent.data.moveSpeedSoothing, ref agent.defaultData.moveSpeedSoothing);
UpdateFloatValue(jumpPower, ref agent.data.jumpPower, ref agent.defaultData.jumpPower);
UpdateFloatValue(jumpPowerDecay, ref agent.data.jumpPowerDecay, ref agent.defaultData.jumpPowerDecay);
UpdateFloatValue(gravityPower, ref agent.data.gravityPower, ref agent.defaultData.gravityPower);
UpdateFloatValue(gravityMax, ref agent.data.gravityMax, ref agent.defaultData.gravityMax);
UpdateFloatValue(gravityAcceleration, ref agent.data.gravityAcceleration, ref agent.defaultData.gravityAcceleration);
UpdateFloatValue(gravityScale, ref agent.data.gravityScale, ref agent.defaultData.gravityScale);
UpdateEnumValue(rotateFacing, ref agent.data.rotateFacing, ref agent.defaultData.rotateFacing);
UpdateFloatValue(rotationSpeedTarget, ref agent.data.rotationSpeedTarget, ref agent.defaultData.rotationSpeedTarget);
UpdateFloatValue(rotationSmoothing, ref agent.data.rotationSmoothing, ref agent.defaultData.rotationSmoothing);
UpdateVector3Value(feedNewDirection, ref feedDir, ref feedDir);
// Debug.Log(feedDir);
if (feedDir != Vector3.zero) {
agent.AddToCurrentDirection(agent.transform.rotation * feedDir.normalized, newDirectionPower);
feedDir = Vector3.zero;
}
if (feedNewRotation.value != Vector3.zero) {
if (rotationRelativeSpace == Space.World) {
Debug.Log(Quaternion.LookRotation(feedRelativeTo.value));
agent.SetSpecifiedRotation(Quaternion.Euler(feedNewRotation.value) * Quaternion.LookRotation(feedRelativeTo.value));
} else {
agent.SetSpecifiedRotation(agent.transform.rotation * Quaternion.Euler(feedNewRotation.value) * Quaternion.LookRotation(feedRelativeTo.value));
}
}
EndAction(true);
}
//Called once per frame while the action is active.
protected override void OnUpdate() {
}
//Called when the task is disabled.
protected override void OnStop() {
}
//Called when the task is paused.
protected override void OnPause() {
}
public void UpdateCurveProperty(CurveValueGroup valueGroup, ref AnimationCurve targetProperty, ref AnimationCurve defaultProperty){
switch (valueGroup.changeValue) {
case ValueChangeAction.NoChange:
break;
case ValueChangeAction.NewValue:
targetProperty = valueGroup.newValue;
break;
case ValueChangeAction.ResetValue:
targetProperty = defaultProperty;
break;
default:
throw new ArgumentOutOfRangeException();
}
}
public void UpdateVector3Value(Vector3ValueGroup valueGroup, ref Vector3 targetProperty, ref Vector3 defaultProperty){
switch (valueGroup.changeX) {
case ValueChangeAction.NewValue:
targetProperty.x = valueGroup.newValue.x;
break;
case ValueChangeAction.ResetValue:
targetProperty.x = defaultProperty.x;
break;
}
switch (valueGroup.changeY) {
case ValueChangeAction.NewValue:
targetProperty.y = valueGroup.newValue.y;
break;
case ValueChangeAction.ResetValue:
targetProperty.y = defaultProperty.y;
break;
}
switch (valueGroup.changeZ) {
case ValueChangeAction.NewValue:
targetProperty.z = valueGroup.newValue.z;
break;
case ValueChangeAction.ResetValue:
targetProperty.z = defaultProperty.z;
break;
}
}
public void UpdateVector2Value(Vector2ValueGroup valueGroup, ref Vector2 targetProperty, ref Vector2 defaultProperty){
switch (valueGroup.changeX) {
case ValueChangeAction.NewValue:
targetProperty.x = valueGroup.newValue.x;
break;
case ValueChangeAction.ResetValue:
targetProperty.x = defaultProperty.x;
break;
}
switch (valueGroup.changeY) {
case ValueChangeAction.NewValue:
targetProperty.y = valueGroup.newValue.y;
break;
case ValueChangeAction.ResetValue:
targetProperty.y = defaultProperty.y;
break;
}
}
public void UpdateBoolValue(BoolValueGroup valueGroup, ref bool targetProperty, ref bool defaultProperty){
switch (valueGroup.changeValue) {
case ValueChangeAction.NewValue:
targetProperty = valueGroup.value;
break;
case ValueChangeAction.ResetValue:
targetProperty = defaultProperty;
break;
}
}
public void UpdateEnumValue(EnumValueGroup valueGroup, ref Enum targetProperty, ref Enum defaultProperty){
switch (valueGroup.changeValue) {
case ValueChangeAction.NewValue:
targetProperty = valueGroup.newValue;
break;
case ValueChangeAction.ResetValue:
targetProperty = defaultProperty;
break;
}
}
public void UpdateFloatValue(FloatValueGroup valueGroup, ref float targetProperty, ref float defaultProperty){
switch (valueGroup.changeValue) {
case ValueChangeAction.NewValue:
targetProperty = valueGroup.value;
break;
case ValueChangeAction.ResetValue:
targetProperty = defaultProperty;
break;
}
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 5132a76af4f722e49bc7fbbc75edcaf1

View File

@@ -65,6 +65,7 @@ namespace Reset.Player.Movement {
case PlayerFacingDirection.Static: case PlayerFacingDirection.Static:
targetRotation = agent.transform.rotation; targetRotation = agent.transform.rotation;
break; break;
} }
// Set final rotation // Set final rotation

View File

@@ -1,9 +1,12 @@
using System;
using ParadoxNotion.Design; using ParadoxNotion.Design;
using Reset.Core;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
namespace Reset.Core{
// Individual bool setting for each ring. Three of these will be used. // Individual bool setting for each ring. Three of these will be used.
public struct OrbitalFollowValueGroup : IValueGroup{ public struct OrbitalFollowValueGroup{
public string label; public string label;
public ValueChangeAction changeHeight; public ValueChangeAction changeHeight;
@@ -29,11 +32,37 @@ public enum ValueChangeAction{
RelativeValue, // Placeholder for using as altering existing value RelativeValue, // Placeholder for using as altering existing value
} }
public interface IValueGroup{ public struct CurveValueGroup{
public string label;
public AnimationCurve newValue;
public ValueChangeAction changeValue;
public CurveValueGroup(string newLabel){
changeValue = ValueChangeAction.NoChange;
newValue = new AnimationCurve();
label = newLabel;
}
} }
public struct Vector3ValueGroup : IValueGroup{ public struct EnumValueGroup{
public string label;
public Enum newValue;
public ValueChangeAction changeValue;
public EnumValueGroup(string newLabel, Enum enumType){
changeValue = ValueChangeAction.NoChange;
newValue = enumType;
label = newLabel;
}
}
public struct Vector3ValueGroup{
public string label; public string label;
public Vector3 newValue; public Vector3 newValue;
@@ -51,7 +80,7 @@ public struct Vector3ValueGroup : IValueGroup{
} }
} }
public struct Vector2ValueGroup : IValueGroup{ public struct Vector2ValueGroup{
public string label; public string label;
public Vector2 newValue; public Vector2 newValue;
@@ -67,7 +96,7 @@ public struct Vector2ValueGroup : IValueGroup{
} }
} }
public struct FloatValueGroup : IValueGroup{ public struct FloatValueGroup{
public string label; public string label;
public float value; public float value;
@@ -80,7 +109,7 @@ public struct FloatValueGroup : IValueGroup{
} }
} }
public struct BoolValueGroup : IValueGroup{ public struct BoolValueGroup{
public string label; public string label;
public bool value; public bool value;
@@ -137,6 +166,91 @@ public class BoolValueGroupDrawer : ObjectDrawer<BoolValueGroup> {
} }
} }
public class CurveVlueGroupDrawer : ObjectDrawer<CurveValueGroup> {
public override CurveValueGroup OnGUI(GUIContent _content, CurveValueGroup _instance){
// Remove label for floats
EditorGUIUtility.labelWidth = 50;
// Set layout options for the label and the float fields
GUILayoutOption[] floatOptions = new GUILayoutOption[] {
GUILayout.Width(80.0f),
GUILayout.MinWidth(20.0f),
GUILayout.ExpandWidth(true),
};
GUILayoutOption[] labelOptions = new GUILayoutOption[]{
GUILayout.Width(200.0f),
};
// Start the Vertical layout then add the label before adding a horizontal so the label will be on top of side-by-side options
GUILayout.BeginVertical();
GUILayout.Label(_instance.label, labelOptions);
GUILayout.BeginHorizontal();
// Create the x settings enum
_instance.changeValue = (ValueChangeAction)EditorGUILayout.EnumPopup("", instance.changeValue);
// Create the value/disabled information field
if (_instance.changeValue == ValueChangeAction.NewValue){
_instance.newValue = EditorGUILayout.CurveField(_instance.newValue, floatOptions);
} else {
EditorGUI.BeginDisabledGroup(true);
EditorGUILayout.TextField(_instance.changeValue == ValueChangeAction.NoChange ? "Unchanged" : "Reset", floatOptions);
EditorGUI.EndDisabledGroup();
}
// Close this line up
GUILayout.EndHorizontal();
GUILayout.EndVertical();
// Reset to default so the rest of things don't get messed up
EditorGUIUtility.labelWidth = 0;
return _instance;
}
}
public class EnumValueGroupDrawer : ObjectDrawer<EnumValueGroup>{
public override EnumValueGroup OnGUI(GUIContent _content, EnumValueGroup _instance){
// Set layout options for the label and the float fields
GUILayoutOption[] floatOptions = new GUILayoutOption[] {
GUILayout.Width(200.0f),
GUILayout.MinWidth(100.0f),
GUILayout.ExpandWidth(true),
};
GUILayoutOption[] labelOptions = new GUILayoutOption[]{
GUILayout.Width(200.0f),
};
// Start the Vertical layout then add the label before adding a horizontal so the label will be on top of side-by-side options
GUILayout.BeginVertical();
GUILayout.Label(_instance.label, labelOptions);
GUILayout.BeginHorizontal();
// Create the x settings enum
_instance.changeValue = (ValueChangeAction)EditorGUILayout.EnumPopup("", instance.changeValue);
// Create the value/disabled information field
if (_instance.changeValue == ValueChangeAction.NewValue){
_instance.newValue = EditorGUILayout.EnumPopup("", instance.newValue, floatOptions);
} else {
EditorGUI.BeginDisabledGroup(true);
EditorGUILayout.TextField(_instance.changeValue == ValueChangeAction.NoChange ? "Unchanged" : "Reset", floatOptions);
EditorGUI.EndDisabledGroup();
}
// Close this line up
GUILayout.EndHorizontal();
GUILayout.EndVertical();
// Reset to default so the rest of things don't get messed up
EditorGUIUtility.labelWidth = 0;
return _instance;
}
}
public class FloatValueGroupDrawer : ObjectDrawer<FloatValueGroup> { public class FloatValueGroupDrawer : ObjectDrawer<FloatValueGroup> {
public override FloatValueGroup OnGUI(GUIContent _content, FloatValueGroup _instance){ public override FloatValueGroup OnGUI(GUIContent _content, FloatValueGroup _instance){
// Remove label for floats // Remove label for floats
@@ -370,3 +484,5 @@ public class OrbitalFollowValueGroupDrawer : ObjectDrawer<OrbitalFollowValueGrou
} }
} }
#endif #endif
}

View File

@@ -10,7 +10,8 @@ public enum PlayerFacingDirection{
MatchForward, MatchForward,
MatchCamera, MatchCamera,
Static, Static,
Momentum Momentum,
SpecifiedDirection
} }
namespace Reset.Units{ namespace Reset.Units{
@@ -41,14 +42,11 @@ namespace Reset.Units{
public float gravityScale = 1f; public float gravityScale = 1f;
// Rotation // Rotation
public PlayerFacingDirection rotateFacing; [ShowInInspector, SerializeReference]
public Enum rotateFacing;
public float rotationSpeedTarget = 5f; public float rotationSpeedTarget = 5f;
public float rotationSmoothing = 1f; public float rotationSmoothing = 1f;
// Smoothing
public Quaternion targetRotation;
public float currentRotSpeed;
public object Clone(){ public object Clone(){
return this.MemberwiseClone(); return this.MemberwiseClone();
} }
@@ -63,16 +61,23 @@ namespace Reset.Units{
// Debug viewing // Debug viewing
// Smoothed Values // Smoothed Values
[ShowInInspector, ReadOnly] private float outputSpeed; [ShowInInspector, ReadOnly] private float outputSpeed;
[ShowInInspector, ReadOnly] private float additionalSpeed;
[ShowInInspector, ReadOnly] private Vector3 outputMoveDirection; [ShowInInspector, ReadOnly] private Vector3 outputMoveDirection;
[ShowInInspector, ReadOnly] private Vector3 additionalMoveDirection;
[ShowInInspector, ReadOnly] private Quaternion outputRotation; [ShowInInspector, ReadOnly] private Quaternion outputRotation;
[ShowInInspector, ReadOnly] private Quaternion specifiedRotation;
[ShowInInspector, ReadOnly] private float outputRotationSpeed; [ShowInInspector, ReadOnly] private float outputRotationSpeed;
private CharacterController controller; private CharacterController controller;
public PlayerControls controls; public PlayerControls controls;
[ShowInInspector, PropertyOrder(2)] [ShowInInspector, PropertyOrder(2)]
public UnitMovementData data = new UnitMovementData(); public UnitMovementData data = new UnitMovementData();
[HideInInspector]
public UnitMovementData defaultData;
[Button, PropertyOrder(1)] [Button, PropertyOrder(1)]
void ResetMovementData(){ void ResetMovementData(){
data = new UnitMovementData(); data = new UnitMovementData();
@@ -82,6 +87,10 @@ namespace Reset.Units{
controller = GetComponent<CharacterController>(); controller = GetComponent<CharacterController>();
} }
private void Start(){
defaultData = (UnitMovementData)data.Clone();
}
void Update(){ void Update(){
UpdateCurrentDirection(); UpdateCurrentDirection();
UpdateCurrentSpeed(); UpdateCurrentSpeed();
@@ -91,6 +100,15 @@ namespace Reset.Units{
DoMovement(); DoMovement();
} }
public void AddToCurrentDirection(Vector3 inputDirection, float power){
additionalMoveDirection += inputDirection.normalized;
additionalSpeed = power;
}
public void SetSpecifiedRotation(Quaternion inputRotation){
specifiedRotation = inputRotation;
}
private void UpdateCurrentDirection(){ private void UpdateCurrentDirection(){
// Get input value // Get input value
Vector3 inputMovement = new Vector3(controls.rawMoveInput.x, 0f, controls.rawMoveInput.y); Vector3 inputMovement = new Vector3(controls.rawMoveInput.x, 0f, controls.rawMoveInput.y);
@@ -167,6 +185,9 @@ namespace Reset.Units{
case PlayerFacingDirection.Static: case PlayerFacingDirection.Static:
outputRotation = transform.rotation; outputRotation = transform.rotation;
break; break;
case PlayerFacingDirection.SpecifiedDirection:
outputRotation = specifiedRotation;
break;
} }
// Calculate rotation speed // Calculate rotation speed
@@ -184,22 +205,48 @@ namespace Reset.Units{
// Commit the move, with respect to the camera's rotation // Commit the move, with respect to the camera's rotation
Vector3 moveXZDir = new Vector3(moveDir.x, 0f, moveDir.z); Vector3 moveXZDir = new Vector3(moveDir.x, 0f, moveDir.z);
Vector3 moveYDir = new Vector3(0f, moveDir.y, 0f); Vector3 moveYDir = new Vector3(0f, moveDir.y, 0f);
Vector3 addDir = additionalMoveDirection;
moveXZDir *= speed * Time.deltaTime; moveXZDir *= speed * Time.deltaTime;
moveYDir *= gravity * Time.deltaTime; moveYDir *= gravity * Time.deltaTime;
addDir *= additionalSpeed * Time.deltaTime;
Vector3 finalDir = moveXZDir + moveYDir; Vector3 finalDir = moveXZDir + moveYDir;
controller.Move((Camera.main.transform.rotation.Flatten(0, null, 0) * finalDir)); controller.Move((Camera.main.transform.rotation.Flatten(0, null, 0) * finalDir) + addDir);
} }
public void LateUpdate(){ void LateUpdate(){
UpdateGravityLate(); 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);
if (inputMovement.magnitude < currentNoY.magnitude) {
additionalMoveDirection = Vector3.Slerp(additionalMoveDirection, Vector3.zero,data.accelerationSmoothing * Time.deltaTime);
} else {
// float deaccelValue = data.deaccelerationCurve.Evaluate(inputMovement.magnitude);
additionalMoveDirection = Vector3.Lerp(additionalMoveDirection, Vector3.zero, data.deaccelerationSmoothing * Time.deltaTime);
}
} }
private void UpdateGravityLate(){ private void UpdateGravityLate(){
// Decay jump power // Decay jump power
data.jumpPower -= data.jumpPowerDecay * Time.deltaTime; data.jumpPower -= data.jumpPowerDecay * Time.deltaTime;
data.jumpPower = Mathf.Max(0f, data.jumpPower);
} }
public void AssignNewData(UnitMovementData movementData){ public void AssignNewData(UnitMovementData movementData){