change: clean-up and tweaks to some swinging behavior

This commit is contained in:
Chris
2025-08-30 18:10:57 -04:00
parent 7d1ee7da7d
commit 29a608f298
4 changed files with 79 additions and 155 deletions

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,5 @@
using System;
using Drawing;
using log4net.Appender;
using NodeCanvas.Framework;
using ParadoxNotion.Design;
using ParadoxNotion.Services;
@@ -17,33 +16,19 @@ namespace NodeCanvas.Tasks.Actions {
[Description("Pulls the agent towards a position with a spring-like effect")]
public class DoGrapplePull : ActionTask<UnitMovementHandler>{
public BBParameter<Vector3> grapplePoint;
public BBParameter<Vector3> offset;
public BBParameter<float> pullAccelerationSpeed;
public BBParameter<float> pullDeaccelerationSpeed;
[Tooltip("X is minimum speed, Y is maximum speed")]
public BBParameter<Vector2> pullTimeRange;
[Tooltip("X is the distance where the curve will first be evaluated, Y is the distance where the curve will last be evaluated")]
public BBParameter<Vector2> pullSpeedRange;
public BBParameter<float> slowdownDistance;
public BBParameter<AnimationCurve> pullSpeedCurve;
public BBParameter<AnimationCurve> endDeaccelerationCurve;
private float startTime;
private Vector3 velocityOnStart;
private Vector3 directionOnStart;
private Vector3 originalDirection;
public float breakAtDistance;
[Tooltip("The dot product between the current direction to the grapple point, and the direction to the grapple point when started. Starts at 1 and gradually gets closer to -1, with 0 being 90 degrees perpendicular.")]
public float breakAtDotProduct;
public float speed;
public float minDistance;
[Tooltip("The dot product between the current direction to the grapple point, and the direction to the grapple point when started. Starts at 1 and gradually gets closer to -1, with 0 being 90 degrees perpendicular. Only for Y")]
public float horizontalDotBreak;
[Tooltip("The dot product between the current direction to the grapple point, and the direction to the grapple point when started. Starts at 1 and gradually gets closer to -1, with 0 being 90 degrees perpendicular. Only for XZ")]
public float verticalDotBreak;
private float currentSpeed;
private Vector3 smoothedInput;
private Vector3 smoothedInputRefVelocity;
@@ -57,8 +42,6 @@ namespace NodeCanvas.Tasks.Actions {
Vector3 smoothedSwingDirection;
private float referenceSpeed;
private Vector3 finalDirection;
private float yChangeMultipler;
@@ -66,8 +49,6 @@ namespace NodeCanvas.Tasks.Actions {
//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.
@@ -91,9 +72,6 @@ namespace NodeCanvas.Tasks.Actions {
// Set the intial swing direction to the same thing, so it starts swinging withing snapping on start
smoothedSwingDirection = finalDirection.Flatten(null, .4f, null);
startTime = Time.time;
currentSpeed = pullSpeedCurve.value[0].value * pullSpeedRange.value.y;
// smoothedInput = agent.GetComponent<CharacterController>().velocity.normalized.Flatten(null, 0f, 0f);
smoothedInput = Vector3.zero;
}
@@ -117,17 +95,15 @@ namespace NodeCanvas.Tasks.Actions {
Physics.Raycast(agent.transform.position, Vector3.down, out RaycastHit hit);
float distanceToGround = hit.distance;
float downwardsSwingAngle = Mathf.Lerp(30, 100, distanceToGround / 20f);
float downwardsSwingAngle = Mathf.Lerp(5, 100, distanceToGround / 20f);
// Altered swing angle based on distance to the grapple point, used to keep the player not too close or far
float inwardsAngle = Mathf.Lerp(0f, -60f, currentDist / -15f);
float outwardsAngle = Mathf.Lerp(0f, -60f, currentDist / 15f);
float outputAngle = inwardsAngle + outwardsAngle;
DebugOverlayDrawer.ChangeValue("Grapple", "Output Angle", outputAngle.ToString() + $"({inwardsAngle.ToString()} + {outwardsAngle.ToString()})");
// Calculate the swing direction.
// Vector3 swingDirection = Quaternion.LookRotation(smoothedInput) * directionToPoint * smoothedInput.magnitude; // Old
Vector3 pointDirectionXZStable = agent.transform.position.DirectionTo(grapplePoint.value.Flatten(null, agent.transform.position.y));
@@ -139,12 +115,12 @@ namespace NodeCanvas.Tasks.Actions {
// Get the target swing direction. This is the direction "around" the point based on context
Vector3 targetSwingDirection;
// Start with up and down
Vector3 yAxisTargetDirection;
if (Vector3.Dot(-directionOnStart, directionToPoint) > 0) { // More than 90 degrees from the start angle, just start going forward from the swing
targetSwingDirection = finalDirection;
} else {
// Start with up and down
Vector3 yAxisTargetDirection;
if (Mathf.Abs(input.y) > 0.1f) { // Input exists on up and down, switch direction based on input
yAxisTargetDirection = Vector3.Slerp(upwardsSwingDirection, downwardsSwingDirection, Mathf.Abs((input.y - 1f) / 2f));
} else { // No input on up/down controller, so swing relative to the point
@@ -155,64 +131,36 @@ namespace NodeCanvas.Tasks.Actions {
}
}
if (directionToPoint.y > -.5f) {
// yAxisTargetDirection += Vector3.up * 4f; // This works but it's making downward motion not work
}
// Finalize the up and down by setting it based on y input
targetSwingDirection = yAxisTargetDirection * Mathf.Abs((input.y));
// Start doing left and right now
if (Mathf.Abs(input.x) > 0.1f) {
// Pick between swinging left or right
Vector3 xAxisTargetDirection = Vector3.Lerp(rightSwingDirectin, leftSwingDirectin, Mathf.Abs((input.x - 1f) / 2f));
// Add a little guaranteed up swing to the left and right swings
xAxisTargetDirection += (Vector3.up * .1f) * Mathf.Abs((input.x));
// Now finalize the left and right, adding it to the target swing direciton based on x input
targetSwingDirection = Vector3.Slerp(targetSwingDirection, xAxisTargetDirection, Mathf.Abs((input.x)));
// targetSwingDirection = xAxisTargetDirection;
DebugOverlayDrawer.ChangeValue("Grapple", "LR Input Dot", Mathf.Abs((input.x - 1f) / 2f).ToString());
}
// Normalize
targetSwingDirection = targetSwingDirection.normalized;
}
// Smooth it, but don't smooth it as well if the dot product between the new direction and current direction are too large
// Turn the difference in direction between what's now and what's targetted, to kneecap the smoothing
float newDirDot = Vector3.Dot(smoothedSwingDirection, targetSwingDirection);
// Normalize the dot
newDirDot = (newDirDot + 1f) / 2f;
// Smooth the swinging
smoothedSwingDirection = Vector3.Slerp(smoothedSwingDirection, targetSwingDirection, 2f * Time.deltaTime * newDirDot);
// DebugOverlayDrawer.ChangeValue("Grapple", "Downwards Swing Angle", downwardsSwingDirection.ToString());
// DebugOverlayDrawer.ChangeValue("Grapple", "Upwards Swing Angle", upwardsSwingDirection.ToString());
// DebugOverlayDrawer.ChangeValue("Grapple", "Right Swing Angle", rightSwingDirectin.ToString());
// DebugOverlayDrawer.ChangeValue("Grapple", "Left Swing Angle", leftSwingDirectin.ToString());
// Some math for getting the Y
yChangeMultipler = Mathf.Lerp(yChangeMultipler, 0f, elapsedTime * .5f); // Starts at 1 so that the player has more ability to change height on start of swing, then smooths to zero
DebugOverlayDrawer.ChangeValue("Grapple", "Composite Swing Direction", smoothedSwingDirection.ToString());
// Speed
float evaluatedSpeed = pullSpeedCurve.value.Evaluate(Mathf.Clamp((Time.time - startTime) / 6f, 0f, Mathf.Infinity));
float speedAgainstCurve = Mathf.Lerp(pullSpeedRange.value.x, pullSpeedRange.value.y, evaluatedSpeed);
// Find how far from 0-1 the player is from the max and minimum distance
// Get the base distance then account for the minimum distance to the point so that being the minimum away will Lerp to 1
// float currentDistMinimumAccounted = (currentDist - pullSpeedDistances.value.x);
if (currentDist < slowdownDistance.value) {
float change = endDeaccelerationCurve.value.Evaluate((slowdownDistance.value - currentDist) / slowdownDistance.value);
speedAgainstCurve = speedAgainstCurve * change;
// Debug.Log($"prev: {speedAgainstCurve}, norm: {(slowdownDistance.value - currentDist) / slowdownDistance.value}, change: {change}, output: {speedAgainstCurve * change} ");
}
// Evaluate the normalized value
// float normaled = Mathf.Lerp(0, 1f, 1f - elapsedTime / (pullSpeedDistances.value.y - pullSpeedDistances.value.x));
// Use the curve evaluation to set the speed
// float outputSpeed = Mathf.Lerp(pullTimeRange.value.x, pullTimeRange.value.y, evaluatedSpeed);
// Soften the speed changes
currentSpeed = Mathf.Lerp(currentSpeed, speedAgainstCurve, 10f * Time.deltaTime);
// Test
finalDirection = Vector3.Slerp(finalDirection, smoothedSwingDirection, (elapsedTime / 1f) + Mathf.Max(0f, smoothedInput.magnitude)); // Set to smoothedSwingDirection when done testing
// Set the output direction direction
finalDirection = Vector3.Slerp(finalDirection, smoothedSwingDirection, (elapsedTime / 1f) + Mathf.Max(0f, smoothedInput.magnitude));
// Gizmos
gizmoVertValue = finalDirection.y;
@@ -221,21 +169,27 @@ namespace NodeCanvas.Tasks.Actions {
gizmoSwingDirection = smoothedSwingDirection; // Set to smoothedSwingDirection when done testing
gizmoFinalDirection = finalDirection;
// Finalize the movement to the controller
agent.SetNewDirection(Vector3.Lerp(agent.additionalMoveDirection, finalDirection.Flatten(null, 0), 1f * Time.deltaTime));
agent.SetNewGravity(finalDirection.y);
agent.SmoothToSpeed(30f, 20f * Time.deltaTime, out referenceSpeed);
// agent.SmoothToDirection(finalDirection.Flatten(null, 0).normalized * evaluatedSpeed, 1f * Time.deltaTime, out referenceDirection);
// agent.SmoothToGravitation(finalDirection.y, 1f, out referenceGravity);
agent.SmoothToSpeed(speed, 25f * Time.deltaTime);
// Calculate dot products for using to end the action
float xzDot = Vector3.Dot(directionOnStart.Flatten(null, 0f), directionToPoint.normalized.Flatten(null, 0f));
float yDot = Vector3.Dot(directionOnStart.Flatten(0f, null, 0f), directionToPoint.normalized.Flatten(0f, null, 0f));
float xzDot = Vector3.Dot(-directionOnStart.Flatten(null, 0).normalized, -directionToPoint.Flatten(null, 0).normalized);
float yDot = Vector3.Dot( // This one has to be rotated around the XZ
Quaternion.LookRotation(directionToPoint) * -directionOnStart.Flatten(null, null, 0).normalized,
Quaternion.LookRotation(directionToPoint) * -directionToPoint.Flatten(null, null, 0).normalized
);
if (xzDot < breakAtDotProduct || yDot < -.9) { // TODO: Change .8 to a variable
DebugOverlayDrawer.ChangeValue("Grapple", "Horizontal Dot", xzDot.ToString());
DebugOverlayDrawer.ChangeValue("Grapple", "Vertical Dot", yDot.ToString());
// Check if done
if (xzDot < horizontalDotBreak || yDot < verticalDotBreak) {
if (elapsedTime > 2f){
EndAction(true);
} else if (currentDist < breakAtDistance) {
}
} else if (currentDist < minDistance) {
EndAction(true);
}
}
@@ -252,7 +206,6 @@ namespace NodeCanvas.Tasks.Actions {
float downwardsSwingAngle = Mathf.Lerp(30, 100, distanceToGround / 20f);
// Altered swing angle based on distance to the grapple point, used to keep the player not too close or far
float inwardsAngle = Mathf.Lerp(0f, -60f, currentDist / -15f);
float outwardsAngle = Mathf.Lerp(0f, -60f, currentDist / 15f);
float outputAngle = inwardsAngle + outwardsAngle;
@@ -349,7 +302,6 @@ namespace NodeCanvas.Tasks.Actions {
// Up and down
using (Draw.WithColor(Color.yellow)) {
Vector3 vertGizmoPosition = agent.transform.position + camera.rotation * Vector3.left;
float vertGizmoWidth = .25f;
float vertGizmoHeight = 1.75f;
Vector3 vertGizmoStart = vertGizmoPosition + Vector3.up * vertGizmoHeight;

View File

@@ -1,5 +1,9 @@
using System;
#if UNITY_EDITOR
using NodeCanvas.Editor;
#endif
using NodeCanvas.Framework;
using ParadoxNotion.Design;
using UnityEditor;

View File

@@ -3,7 +3,6 @@ using NUnit.Framework.Internal;
using UnityEngine;
using ParadoxNotion.Design;
using Sirenix.OdinInspector;
using UnityEditor.Rendering;
using UnityEngine.Serialization;
using Quaternion = UnityEngine.Quaternion;
@@ -126,25 +125,10 @@ namespace Reset.Units{
additionalSpeed = power;
}
public void SmoothToDirection(Vector3 desiredDirection, float value, out Vector3 referenceDirection){
// referenceDirection = outputMoveDirection;
additionalMoveDirection = Vector3.Slerp(outputMoveDirection, desiredDirection, value);
referenceDirection = outputMoveDirection;
}
public void SmoothToSpeed(float desiredSpeed, float smoothing, out float referenceSpeed){
public void SmoothToSpeed(float desiredSpeed, float smoothing){
additionalSpeed = Mathf.Lerp(additionalSpeed, desiredSpeed, smoothing * Time.deltaTime);
referenceSpeed = additionalSpeed;
}
// public void SmoothToGravity(float desiredGravity, float smoothing, out float referenceGravity){
// outputMoveDirection.y = Mathf.Lerp(outputMoveDirection.y, desiredGravity, smoothing);
// referenceGravity = desiredGravity;
// }
public void SetNewDirection(Vector3 inputDirection){ // NOTE: If smoothing desired add a default bool for smoothing maybe?
additionalMoveDirection = inputDirection.Flatten(null, 0f, null);
}
@@ -208,7 +192,6 @@ namespace Reset.Units{
// 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
if (targetNoY.magnitude > currentNoY.magnitude) {
if (controller.isGrounded){
slerpedValue = Vector3.Slerp(currentNoY, targetNoY, data.accelerationSmoothing * Time.deltaTime);
@@ -332,10 +315,7 @@ namespace Reset.Units{
// Construct the direction and move
Vector3 finalDir = moveXZDir + moveYDir;
controller.Move((Camera.main.transform.rotation.Flatten(0, null, 0) * finalDir) + addDir);
}
void LateUpdate(){
@@ -366,9 +346,6 @@ namespace Reset.Units{
// Decay the direction
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);