feat: version 1.0 grapple
This commit is contained in:
@@ -147,7 +147,7 @@ namespace NodeCanvas.Tasks.Actions {
|
||||
public void UpdateFloatValue(FloatValueGroup valueGroup, ref CameraSettingSingleValue<float> targetProperty){
|
||||
switch (valueGroup.changeValue) {
|
||||
case ValueChangeAction.NewValue:
|
||||
targetProperty.targetValue = valueGroup.value;
|
||||
targetProperty.targetValue = valueGroup.value.value;
|
||||
break;
|
||||
case ValueChangeAction.ResetValue:
|
||||
targetProperty.targetValue = targetProperty.originalValue;
|
||||
|
||||
@@ -40,6 +40,7 @@ namespace Reset.Core {
|
||||
public FloatValueGroup gravityMax = new (newLabel: "Gravity Max");
|
||||
public FloatValueGroup gravityAcceleration = new (newLabel: "Gravity Acceleration Speed");
|
||||
public FloatValueGroup gravityScale = new (newLabel: "Gravity Scale");
|
||||
public FloatValueGroup settingsChangeSmoothing = new(newLabel: "Settings Change Smoothing");
|
||||
|
||||
// Rotation
|
||||
[ParadoxNotion.Design.Header("Rotation")]
|
||||
@@ -97,6 +98,7 @@ namespace Reset.Core {
|
||||
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);
|
||||
UpdateFloatValue(settingsChangeSmoothing, ref agent.data.settingsChangeSmoothing, ref agent.defaultData.settingsChangeSmoothing);
|
||||
|
||||
// Rotation
|
||||
UpdateEnumValue(rotateFacing, ref agent.data.rotateFacing, ref agent.defaultData.rotateFacing);
|
||||
@@ -222,7 +224,7 @@ namespace Reset.Core {
|
||||
public void UpdateFloatValue(FloatValueGroup valueGroup, ref float targetProperty, ref float defaultProperty){
|
||||
switch (valueGroup.changeValue) {
|
||||
case ValueChangeAction.NewValue:
|
||||
targetProperty = valueGroup.value;
|
||||
targetProperty = valueGroup.value.value;
|
||||
break;
|
||||
case ValueChangeAction.ResetValue:
|
||||
targetProperty = defaultProperty;
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
using System;
|
||||
using Drawing;
|
||||
using NodeCanvas.Framework;
|
||||
using ParadoxNotion.Design;
|
||||
using ParadoxNotion.Services;
|
||||
using Reset.Core.Tools;
|
||||
using Reset.Units;
|
||||
using Sirenix.Serialization;
|
||||
using Unity.Cinemachine;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
@@ -9,34 +14,41 @@ namespace NodeCanvas.Tasks.Actions {
|
||||
|
||||
[Category("Reset/Movement")]
|
||||
[Description("Pulls the agent towards a position with a spring-like effect")]
|
||||
public class DoGrapplePull : ActionTask<CharacterController>{
|
||||
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 Vector3 velocityOnStart;
|
||||
private Vector3 directionOnStart;
|
||||
private Vector3 originalDirection;
|
||||
private Vector3 locationOnStart;
|
||||
|
||||
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 startTime;
|
||||
|
||||
private float currentSpeed;
|
||||
private Vector3 smoothedInput;
|
||||
private Vector3 smoothedInputRefVelocity;
|
||||
|
||||
private Vector3 gizmoSwingDirection;
|
||||
private Vector3 gizmoPointDirection;
|
||||
private Vector3 gizmoFinalDirection;
|
||||
private Vector3 gizmosSmoothedInput;
|
||||
private float gizmoVertValue;
|
||||
|
||||
private Transform camera;
|
||||
|
||||
//Use for initialization. This is called only once in the lifetime of the task.
|
||||
Vector3 smoothedSwingDirection;
|
||||
|
||||
private Vector3 finalDirection;
|
||||
private float yChangeMultipler;
|
||||
|
||||
//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 += DrawGrappleGizmo;
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -44,79 +56,306 @@ namespace NodeCanvas.Tasks.Actions {
|
||||
//Call EndAction() to mark the action as finished, either in success or failure.
|
||||
//EndAction can be called from anywhere.
|
||||
protected override void OnExecute(){
|
||||
startTime = Time.time;
|
||||
currentSpeed = pullSpeedCurve.value[0].value * pullSpeedRange.value.y;
|
||||
// Some startup stuff
|
||||
camera = Camera.main.transform;
|
||||
MonoManager.current.onLateUpdate += DrawGrappleGizmo;
|
||||
MonoManager.current.onLateUpdate += UpdateLineRenderer;
|
||||
|
||||
// Add the renderer
|
||||
agent.gameObject.AddComponent<LineRenderer>();
|
||||
|
||||
// Set original direction and locoation
|
||||
locationOnStart = agent.transform.position;
|
||||
directionOnStart = agent.transform.position.DirectionTo(grapplePoint.value);
|
||||
|
||||
// Get the current move direction
|
||||
velocityOnStart = agent.outputMoveDirection;
|
||||
|
||||
// For setting finalDirection's initial value, first compose the swing variables one-time
|
||||
Vector3 velocityWhenMoving = CalculateSwingDirections(Vector3.Distance(agent.transform.position, grapplePoint.value), directionOnStart);
|
||||
|
||||
// Lerp the initial direction more towards the point of the grapple and less towards current momentum if not moving fast
|
||||
finalDirection = Vector3.Lerp(velocityOnStart, velocityWhenMoving, velocityOnStart.magnitude / 2f); // This isn't working
|
||||
|
||||
// Set the intial swing direction to the same thing, so it starts swinging withing snapping on start
|
||||
smoothedSwingDirection = finalDirection.Flatten(null, .4f, null);
|
||||
|
||||
// smoothedInput = agent.GetComponent<CharacterController>().velocity.normalized.Flatten(null, 0f, 0f);
|
||||
smoothedInput = Vector3.zero;
|
||||
}
|
||||
|
||||
//Called once per frame while the action is active.
|
||||
protected override void OnUpdate(){
|
||||
// Create the distance variables
|
||||
Vector3 dirToPoint = agent.transform.position.DirectionTo(grapplePoint.value);
|
||||
|
||||
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);
|
||||
protected override void OnUpdate(){
|
||||
agent.outputMoveDirection = Vector3.MoveTowards(agent.outputMoveDirection, Vector3.zero, .5f);
|
||||
|
||||
// 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 currentDist = Vector3.Distance(agent.transform.position, grapplePoint.value);
|
||||
// float currentDistMinimumAccounted = (currentDist - pullSpeedDistances.value.x);
|
||||
|
||||
if (currentDist < slowdownDistance.value) {
|
||||
float change = endDeaccelerationCurve.value.Evaluate((slowdownDistance.value - currentDist) / slowdownDistance.value);
|
||||
speedAgainstCurve = speedAgainstCurve * change;
|
||||
// Basic variables, direction to point and current distnace
|
||||
Vector3 directionToPoint = agent.transform.position.DirectionTo(grapplePoint.value);
|
||||
float currentDist = Vector3.Distance(agent.transform.position, grapplePoint.value);
|
||||
|
||||
// Calculate input
|
||||
Vector2 rawInput = agent.GetComponent<PlayerControls>().rawMoveInput;
|
||||
Vector3 input = new(rawInput.x, rawInput.y, 0f);
|
||||
|
||||
smoothedInput = Vector3.SmoothDamp(smoothedInput, input, ref smoothedInputRefVelocity, 1f);
|
||||
DebugOverlayDrawer.ChangeValue("Grapple", "Smoothed Input", smoothedInput.ToString());
|
||||
|
||||
// The swing angle needs to change for the downwards swing, based on distance to the ground
|
||||
Physics.Raycast(agent.transform.position, Vector3.down, out RaycastHit hit);
|
||||
float distanceToGround = hit.distance;
|
||||
|
||||
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));
|
||||
Vector3 rightSwingDirectin = Quaternion.AngleAxis(100f + outputAngle, Vector3.up) * pointDirectionXZStable; // Working
|
||||
Vector3 leftSwingDirectin = Quaternion.AngleAxis(-100f - outputAngle, Vector3.up) * pointDirectionXZStable; // Working
|
||||
Vector3 upwardsSwingDirection = Quaternion.AngleAxis(-140f - outputAngle, Quaternion.LookRotation(directionToPoint) * Vector3.right) * directionToPoint; // Working
|
||||
Vector3 downwardsSwingDirection = Quaternion.AngleAxis(downwardsSwingAngle, Quaternion.LookRotation(directionOnStart) * Vector3.right) * directionToPoint; // WORKING NOW!! Note: this has to rotate by directionOnStart because else it just moves towards the point
|
||||
|
||||
// Get the target swing direction. This is the direction "around" the point based on context
|
||||
Vector3 targetSwingDirection;
|
||||
|
||||
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;
|
||||
|
||||
// Debug.Log($"prev: {speedAgainstCurve}, norm: {(slowdownDistance.value - currentDist) / slowdownDistance.value}, change: {change}, output: {speedAgainstCurve * change} ");
|
||||
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
|
||||
if (directionToPoint.y < 0) { // Since you're under the point swing downwards
|
||||
yAxisTargetDirection = downwardsSwingDirection;
|
||||
} else { // Since you're over the point, swing upwards
|
||||
yAxisTargetDirection = upwardsSwingDirection;
|
||||
}
|
||||
}
|
||||
|
||||
// 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)));
|
||||
}
|
||||
|
||||
// Normalize
|
||||
targetSwingDirection = targetSwingDirection.normalized;
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// Set the output direction direction
|
||||
finalDirection = Vector3.Slerp(finalDirection, smoothedSwingDirection, (elapsedTime / 1f) + Mathf.Max(0f, smoothedInput.magnitude));
|
||||
|
||||
// Gizmos
|
||||
gizmoVertValue = finalDirection.y;
|
||||
gizmosSmoothedInput = smoothedInput;
|
||||
gizmoPointDirection = targetSwingDirection;
|
||||
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(speed, 25f * Time.deltaTime);
|
||||
|
||||
|
||||
// Calculate dot products for using to end the action
|
||||
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
|
||||
);
|
||||
|
||||
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 < minDistance) {
|
||||
EndAction(true);
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 CalculateSwingDirections(float currentDist, Vector3 directionToPoint){
|
||||
// Get input
|
||||
Vector2 rawInput = agent.GetComponent<PlayerControls>().rawMoveInput;
|
||||
Vector3 input = new(rawInput.x, rawInput.y, 0f);
|
||||
|
||||
// The swing angle needs to change for the downwards swing, based on distance to the ground
|
||||
Physics.Raycast(agent.transform.position, Vector3.down, out RaycastHit hit);
|
||||
float distanceToGround = hit.distance;
|
||||
|
||||
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;
|
||||
|
||||
DebugOverlayDrawer.ChangeValue("Grapple", "Output Angle", outputAngle.ToString() + $"({inwardsAngle.ToString()} + {outwardsAngle.ToString()})");
|
||||
|
||||
Vector3 pointDirectionXZStable = agent.transform.position.DirectionTo(grapplePoint.value.Flatten(null, agent.transform.position.y));
|
||||
Vector3 rightSwingDirectin = Quaternion.AngleAxis(100f + outputAngle, Vector3.up) * pointDirectionXZStable; // Working
|
||||
Vector3 leftSwingDirectin = Quaternion.AngleAxis(-100f - outputAngle, Vector3.up) * pointDirectionXZStable; // Working
|
||||
Vector3 upwardsSwingDirection = Quaternion.AngleAxis(-140f - outputAngle, Quaternion.LookRotation(directionToPoint) * Vector3.right) * directionToPoint; // Working
|
||||
Vector3 downwardsSwingDirection = Quaternion.AngleAxis(downwardsSwingAngle, Quaternion.LookRotation(directionOnStart) * Vector3.right) * directionToPoint; // WORKING NOW!! Note: this has to rotate by directionOnStart because else it just moves towards the point
|
||||
|
||||
// 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 (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
|
||||
if (directionToPoint.y < 0) { // Since you're under the point swing downwards
|
||||
yAxisTargetDirection = downwardsSwingDirection;
|
||||
} else { // Since you're over the point, swing upwards
|
||||
yAxisTargetDirection = downwardsSwingDirection;
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate the normalized value
|
||||
// float normaled = Mathf.Lerp(0, 1f, 1f - elapsedTime / (pullSpeedDistances.value.y - pullSpeedDistances.value.x));
|
||||
if (directionToPoint.y > -.5f) {
|
||||
// yAxisTargetDirection += Vector3.up * 4f; // This works but it's making downward motion not work
|
||||
}
|
||||
|
||||
// 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);
|
||||
targetSwingDirection = yAxisTargetDirection * Mathf.Abs((input.y));
|
||||
|
||||
// Add input changes
|
||||
Vector2 rawInput = agent.GetComponent<PlayerControls>().rawMoveInput;
|
||||
Vector3 input = Quaternion.LookRotation(dirToPoint) * new Vector3(rawInput.x, rawInput.y, 0f);
|
||||
|
||||
smoothedInput = Vector3.SmoothDamp(smoothedInput, input, ref smoothedInputRefVelocity, 30f * Time.deltaTime);
|
||||
if (Mathf.Abs(input.x) > 0.1f) {
|
||||
Vector3 xAxisTargetDirection = Vector3.Lerp(rightSwingDirectin, leftSwingDirectin, Mathf.Abs((input.x - 1f) / 2f));
|
||||
targetSwingDirection = Vector3.Slerp(targetSwingDirection, xAxisTargetDirection, Mathf.Abs((input.x)));
|
||||
// targetSwingDirection = xAxisTargetDirection;
|
||||
DebugOverlayDrawer.ChangeValue("Grapple", "LR Input Dot", Mathf.Abs((input.x - 1f) / 2f).ToString());
|
||||
}
|
||||
|
||||
Debug.Log(input);
|
||||
return targetSwingDirection.normalized;
|
||||
}
|
||||
|
||||
dirToPoint.y *= 2.5f;
|
||||
public void UpdateLineRenderer(){
|
||||
// Update the Line Renderer
|
||||
var lr = agent.GetComponent<LineRenderer>();
|
||||
|
||||
agent.Move((dirToPoint.normalized + smoothedInput) * currentSpeed * Time.deltaTime);
|
||||
// Debug.Log( $"{ endDeaccelerationCurve.value.Evaluate(((slowdownDistance.value - currentDist)) )}");
|
||||
lr.positionCount = 2;
|
||||
|
||||
// Very shoddy position setting
|
||||
lr.SetPositions(new []{
|
||||
agent.transform.position,
|
||||
grapplePoint.value}
|
||||
);
|
||||
|
||||
lr.startWidth = .1f;
|
||||
lr.endWidth = .1f;
|
||||
|
||||
// EndAction(true);
|
||||
}
|
||||
|
||||
public void DrawGrappleGizmo(){
|
||||
// Vector3 dirToPoint = agent.transform.position.DirectionTo(grapplePoint.value);
|
||||
//
|
||||
// using (Draw.WithColor(Color.yellow)){
|
||||
// Draw.Line(agent.transform.position + Vector3.up, grapplePoint.value);
|
||||
//
|
||||
// // Draw Gizmo for minimum distance
|
||||
// Vector3 minLocation = agent.transform.position + (Vector3.up * 1) + (dirToPoint * pullSpeedDistances.value.x);
|
||||
// Vector3 minToScreen = minLocation.DirectionTo(Camera.main.transform.position);
|
||||
//
|
||||
// Draw.SolidCircle(minLocation,minToScreen , .2f);
|
||||
//
|
||||
// // Draw Gizmo for minimum distance
|
||||
// Vector3 maxLocation = agent.transform.position + (Vector3.up * .8f) + (dirToPoint * pullSpeedDistances.value.y);
|
||||
// Vector3 maxToScreen = maxLocation.DirectionTo(Camera.main.transform.position);
|
||||
//
|
||||
// Draw.SolidCircle(maxLocation,maxToScreen , .2f);
|
||||
// }
|
||||
// Destination gizmos
|
||||
using (Draw.WithColor(Color.blue)){
|
||||
Vector3 offsetTowardsCamera = grapplePoint.value.DirectionTo(camera.transform.position);
|
||||
|
||||
// Grapple Point
|
||||
Draw.SolidCircle(grapplePoint.value + offsetTowardsCamera, grapplePoint.value.DirectionTo(camera.transform.position), .4f);
|
||||
Draw.Label2D(grapplePoint.value + offsetTowardsCamera * 2f + Vector3.up, "Grapple Point");
|
||||
|
||||
using (Draw.WithLineWidth(1.5f)) {
|
||||
// Final Direction
|
||||
Draw.Line(agent.transform.position + Vector3.up, agent.transform.position + Vector3.up + gizmoFinalDirection.normalized * 2f);
|
||||
Draw.ArrowheadArc(agent.transform.position + Vector3.up, gizmoFinalDirection.normalized, 2f, 15f);
|
||||
|
||||
// Colors for faded arrows
|
||||
Color swingColor = Color.Lerp(Color.blue, Color.blue.Alpha(.4f), (elapsedTime * .6f));
|
||||
Color dirColor = Color.Lerp(Color.blue.Alpha(.4f), Color.blue, (elapsedTime * .6f));
|
||||
|
||||
// Swing Direction
|
||||
using (Draw.WithColor(swingColor)) {
|
||||
float swingLength = 2.2f;
|
||||
Vector3 swingStart = agent.transform.position + Vector3.up * .4f;
|
||||
Vector3 swingDir = swingStart + gizmoSwingDirection.normalized * swingLength;
|
||||
Draw.DashedLine(swingStart, swingDir, .2f, .2f);
|
||||
Draw.ArrowheadArc(swingStart, gizmoSwingDirection.normalized, swingLength, 15f);
|
||||
Draw.Label2D(swingDir + Vector3.up * .4f, "Swing Direction");
|
||||
}
|
||||
|
||||
// Point Direction
|
||||
using (Draw.WithColor(dirColor)) {
|
||||
float pointLength = 1.2f;
|
||||
Vector3 pointStart = agent.transform.position + Vector3.up * .2f;
|
||||
Vector3 pointDir = grapplePoint.value;
|
||||
Draw.DashedLine(pointStart, pointDir, .2f, .2f);
|
||||
Draw.ArrowheadArc(pointStart, gizmoPointDirection.normalized, pointLength, 15f);
|
||||
Draw.Label2D(pointDir + Vector3.up * .4f, "Grapple Point Direction");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Input Gizmos
|
||||
using (Draw.WithColor(Color.red)) {
|
||||
// Input left and right, up and down for size
|
||||
Vector3 inputGizmoOffset = (agent.transform.position + camera.rotation * Vector3.back + Vector3.up * .5f);
|
||||
Vector3 inputGizmoPosition = inputGizmoOffset + camera.rotation * Vector3.Lerp(Vector3.left, Vector3.right, (gizmosSmoothedInput.x - 1 ) / 2f + 1f);
|
||||
Draw.Line(inputGizmoOffset + camera.rotation * Vector3.left, inputGizmoOffset + camera.rotation * Vector3.right);
|
||||
Draw.SolidCircle(inputGizmoPosition, inputGizmoPosition.DirectionTo(camera.position), Mathf.Lerp(.2f, .6f, (gizmosSmoothedInput.y - 1 ) / 2f + 1f));
|
||||
}
|
||||
|
||||
// Up and down
|
||||
using (Draw.WithColor(Color.yellow)) {
|
||||
Vector3 vertGizmoPosition = agent.transform.position + camera.rotation * Vector3.left;
|
||||
float vertGizmoHeight = 1.75f;
|
||||
|
||||
Vector3 vertGizmoStart = vertGizmoPosition + Vector3.up * vertGizmoHeight;
|
||||
Vector3 vertGizmoEnd = vertGizmoPosition + Vector3.up * .35f;
|
||||
|
||||
Vector3 circlePos = Vector3.Lerp(vertGizmoEnd, vertGizmoStart, gizmoVertValue);
|
||||
|
||||
Draw.Line(vertGizmoStart, vertGizmoEnd);
|
||||
Draw.SolidCircle(circlePos, circlePos.DirectionTo(camera.position), .4f);
|
||||
Draw.Label2D(vertGizmoStart + camera.rotation * Vector3.left * 1.5f, gizmoVertValue.ToString());
|
||||
|
||||
Vector3 vertArrowUpPosition = vertGizmoStart + camera.rotation * Vector3.left * 1f + Vector3.up * .2f;
|
||||
Vector3 vertArrowDownPosition = vertGizmoStart + camera.rotation * Vector3.left * 1f + Vector3.down * .2f;
|
||||
|
||||
if (gizmoVertValue > 0) {
|
||||
Draw.SolidTriangle(vertArrowUpPosition + camera.rotation * Vector3.left/4, vertArrowUpPosition + Vector3.up/2, vertArrowUpPosition + camera.rotation * Vector3.right/4);
|
||||
} else {
|
||||
Draw.SolidTriangle(vertArrowDownPosition + camera.rotation * Vector3.left/4, vertArrowDownPosition + Vector3.down/2, vertArrowDownPosition + camera.rotation * Vector3.right/4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Called when the task is disabled.
|
||||
protected override void OnStop() {
|
||||
|
||||
MonoManager.current.onLateUpdate -= DrawGrappleGizmo;
|
||||
MonoManager.current.onLateUpdate -= UpdateLineRenderer;
|
||||
|
||||
GameObject.Destroy(agent.gameObject.GetComponent<LineRenderer>());
|
||||
}
|
||||
|
||||
//Called when the task is paused.
|
||||
|
||||
@@ -4,7 +4,7 @@ MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 5000
|
||||
executionOrder: 95
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
using System;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using NodeCanvas.Editor;
|
||||
#endif
|
||||
|
||||
using NodeCanvas.Framework;
|
||||
using ParadoxNotion.Design;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
@@ -97,13 +103,14 @@ namespace Reset.Core{
|
||||
|
||||
public struct FloatValueGroup{
|
||||
public string label;
|
||||
public float value;
|
||||
// public float value;
|
||||
public BBParameter<float> value;
|
||||
|
||||
public ValueChangeAction changeValue;
|
||||
|
||||
public FloatValueGroup(string newLabel){
|
||||
label = newLabel;
|
||||
value = 0f;
|
||||
value = new BBParameter<float>().value = 0f;
|
||||
changeValue = ValueChangeAction.NoChange;
|
||||
}
|
||||
}
|
||||
@@ -123,7 +130,7 @@ namespace Reset.Core{
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public class BoolValueGroupDrawer : ObjectDrawer<BoolValueGroup> {
|
||||
public override BoolValueGroup OnGUI(GUIContent content, BoolValueGroup _instance){
|
||||
public override BoolValueGroup OnGUI(GUIContent _content, BoolValueGroup _instance){
|
||||
// Remove label for floats
|
||||
EditorGUIUtility.labelWidth = 50;
|
||||
|
||||
@@ -274,9 +281,11 @@ namespace Reset.Core{
|
||||
// Create the x settings enum
|
||||
_instance.changeValue = (ValueChangeAction)EditorGUILayout.EnumPopup("", instance.changeValue);
|
||||
|
||||
|
||||
// Create the value/disabled information field
|
||||
if (_instance.changeValue == ValueChangeAction.NewValue){
|
||||
_instance.value = EditorGUILayout.FloatField(_instance.value, floatOptions);
|
||||
// _instance.value = EditorGUILayout.FloatField(_instance.value, floatOptions);
|
||||
BBParameterEditor.ParameterField("", _instance.value);
|
||||
} else {
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
EditorGUILayout.TextField(_instance.changeValue == ValueChangeAction.NoChange ? "Unchanged" : "Reset", floatOptions);
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using NUnit.Framework.Internal;
|
||||
using UnityEngine;
|
||||
using ParadoxNotion.Design;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine.Serialization;
|
||||
using Quaternion = UnityEngine.Quaternion;
|
||||
|
||||
public enum PlayerFacingDirection{
|
||||
TowardsTarget = 0,
|
||||
@@ -42,6 +44,7 @@ namespace Reset.Units{
|
||||
public float gravityMax = 8f;
|
||||
public float gravityAcceleration = 1f;
|
||||
public float gravityScale = 1f;
|
||||
public float settingsChangeSmoothing = 6f;
|
||||
|
||||
// Rotation
|
||||
[ShowInInspector, SerializeReference]
|
||||
@@ -61,21 +64,35 @@ namespace Reset.Units{
|
||||
// public float value;
|
||||
// }
|
||||
|
||||
// Debug viewing
|
||||
[ShowInInspector, ReadOnly] private float outputSpeed;
|
||||
[ShowInInspector, ReadOnly] private float additionalSpeed;
|
||||
[ShowInInspector, ReadOnly] public Vector3 outputMoveDirection;
|
||||
[ShowInInspector, ReadOnly] private Vector3 additionalMoveDirection;
|
||||
[ShowInInspector, ReadOnly] private Quaternion outputRotation;
|
||||
[ShowInInspector, ReadOnly] private Quaternion specifiedRotation;
|
||||
[ShowInInspector, ReadOnly] private float outputRotationSpeed;
|
||||
//
|
||||
[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;
|
||||
|
||||
// Used by graph to gradually shift into new values rather than dump them. Even if they're smoothed values they need to be eased into
|
||||
[FoldoutGroup("Smoothed Values"), ShowInInspector, ReadOnly] private float smoothedJumpDecay;
|
||||
[FoldoutGroup("Smoothed Values"), ShowInInspector, ReadOnly] private float smoothedGravityAccel;
|
||||
[FoldoutGroup("Smoothed Values"), ShowInInspector, ReadOnly] private float smoothedGravityScale;
|
||||
[FoldoutGroup("Smoothed Values"), ShowInInspector, ReadOnly] private float settingsChangeRotationSpeed;
|
||||
|
||||
private float directionChangeDot;
|
||||
private bool moveCallDisabledNextFrame;
|
||||
|
||||
private bool movedThisFrame;
|
||||
|
||||
private CharacterController controller;
|
||||
private PlayerControls controls;
|
||||
private LockOnManager lockOnManager;
|
||||
|
||||
private Vector3 moveSmooth;
|
||||
public float gravitySmooth;
|
||||
|
||||
private bool relativeToCamera;
|
||||
|
||||
[ShowInInspector, PropertyOrder(2)]
|
||||
public UnitMovementData data = new();
|
||||
|
||||
@@ -94,8 +111,9 @@ namespace Reset.Units{
|
||||
|
||||
void Update(){
|
||||
UpdateCurrentDirection();
|
||||
UpdateCurrentSpeed();
|
||||
UpdateCurrentGravity();
|
||||
UpdateCurrentSpeed();
|
||||
|
||||
UpdateCurrentRotation();
|
||||
|
||||
DoMovement();
|
||||
@@ -106,6 +124,18 @@ namespace Reset.Units{
|
||||
additionalMoveDirection += inputDirection.normalized;
|
||||
additionalSpeed = power;
|
||||
}
|
||||
|
||||
public void SmoothToSpeed(float desiredSpeed, float smoothing){
|
||||
additionalSpeed = Mathf.Lerp(additionalSpeed, desiredSpeed, smoothing * Time.deltaTime);
|
||||
}
|
||||
|
||||
public void SetNewDirection(Vector3 inputDirection){ // NOTE: If smoothing desired add a default bool for smoothing maybe?
|
||||
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){
|
||||
@@ -130,7 +160,7 @@ namespace Reset.Units{
|
||||
if (float.IsPositiveInfinity(speed)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
outputSpeed = Mathf.Lerp(outputSpeed, Mathf.Max(data.moveSpeed, speed), priority);
|
||||
}
|
||||
|
||||
@@ -162,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);
|
||||
@@ -184,19 +213,20 @@ namespace Reset.Units{
|
||||
}
|
||||
|
||||
// Commit move direction
|
||||
outputMoveDirection = new Vector3(currentNoY.x, outputMoveDirection.y, currentNoY.z);
|
||||
outputMoveDirection = Vector3.SmoothDamp(outputMoveDirection, new Vector3(currentNoY.x, outputMoveDirection.y, currentNoY.z),ref moveSmooth , .5f *Time.deltaTime);
|
||||
}
|
||||
|
||||
// Update the speed, called every frame
|
||||
private void UpdateCurrentSpeed(){
|
||||
Debug.Log(data.moveSpeed);
|
||||
outputSpeed = Mathf.Lerp(outputSpeed, data.moveSpeed, data.moveSpeedSoothing * Time.deltaTime);
|
||||
}
|
||||
|
||||
// Update the gravity, called every frame
|
||||
private void UpdateCurrentGravity(){
|
||||
// Accelerate gravity
|
||||
data.gravityPower += data.gravityAcceleration * Time.deltaTime;
|
||||
data.gravityPower = Mathf.Min(data.gravityPower, data.gravityMax);
|
||||
data.gravityPower += smoothedGravityAccel * Time.deltaTime;
|
||||
data.gravityPower = Mathf.Clamp(data.gravityPower, Mathf.NegativeInfinity, data.gravityMax);
|
||||
|
||||
// Apply a constant gravity if the player is grounded
|
||||
if (controller.isGrounded) {
|
||||
@@ -207,7 +237,7 @@ namespace Reset.Units{
|
||||
float gravityMoveDirection = data.jumpPower + (Physics.gravity.y * data.gravityPower);
|
||||
|
||||
// Commit gravity to move direction, ignoring XZ since those are done in UpdateMovementDirection
|
||||
outputMoveDirection.y = gravityMoveDirection;
|
||||
outputMoveDirection.y = Mathf.SmoothDamp(outputMoveDirection.y, gravityMoveDirection, ref gravitySmooth, .1f * Time.deltaTime);
|
||||
}
|
||||
|
||||
// Update the rotation, called every frame
|
||||
@@ -254,7 +284,7 @@ namespace Reset.Units{
|
||||
}
|
||||
|
||||
// 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, data.rotationSmoothing * Time.deltaTime);
|
||||
outputRotationSpeed = Mathf.Lerp(outputRotationSpeed, data.rotationSpeed, settingsChangeRotationSpeed * Time.deltaTime);
|
||||
|
||||
// Set final rotation
|
||||
transform.rotation = Quaternion.Slerp(transform.rotation, outputRotation, outputRotationSpeed * Time.deltaTime).Flatten(0, null, 0);
|
||||
@@ -264,9 +294,15 @@ namespace Reset.Units{
|
||||
public void DoMovement(){
|
||||
DoMovement(outputMoveDirection, outputSpeed, data.gravityScale);
|
||||
}
|
||||
|
||||
public void DisableNextMoveCall(){
|
||||
moveCallDisabledNextFrame = true;
|
||||
}
|
||||
|
||||
// Custom move from input
|
||||
public void DoMovement(Vector3 moveDir, float speed, float gravity){
|
||||
public void DoMovement(Vector3 moveDir, float speed, float gravityScale){
|
||||
// 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
|
||||
Vector3 moveXZDir = new Vector3(moveDir.x, 0f, moveDir.z);
|
||||
Vector3 moveYDir = new Vector3(0f, moveDir.y, 0f);
|
||||
@@ -274,18 +310,25 @@ namespace Reset.Units{
|
||||
|
||||
// Add their related speeds
|
||||
moveXZDir *= speed * Time.deltaTime;
|
||||
moveYDir *= gravity * Time.deltaTime;
|
||||
moveYDir *= smoothedGravityScale * Time.deltaTime;
|
||||
addDir *= additionalSpeed * Time.deltaTime;
|
||||
|
||||
// Construct the direction and move
|
||||
Vector3 finalDir = moveXZDir + moveYDir;
|
||||
|
||||
controller.Move((Camera.main.transform.rotation.Flatten(0, null, 0) * finalDir) + addDir);
|
||||
controller.Move((Camera.main.transform.rotation.Flatten(0, null, 0) * finalDir) + addDir);
|
||||
}
|
||||
|
||||
void LateUpdate(){
|
||||
UpdateGravityLate();
|
||||
DecayAdditionalDirection();
|
||||
SmoothingSettingsChanges();
|
||||
}
|
||||
|
||||
private void SmoothingSettingsChanges(){
|
||||
smoothedJumpDecay = Mathf.Lerp(smoothedJumpDecay, data.jumpPowerDecay, data.settingsChangeSmoothing * Time.deltaTime);
|
||||
smoothedGravityAccel = Mathf.Lerp(smoothedGravityAccel, data.gravityAcceleration, data.settingsChangeSmoothing * Time.deltaTime);
|
||||
smoothedGravityScale = Mathf.Lerp(smoothedGravityScale, data.gravityScale, data.settingsChangeSmoothing * Time.deltaTime);
|
||||
settingsChangeRotationSpeed = Mathf.Lerp(settingsChangeRotationSpeed, data.rotationSpeed, data.settingsChangeSmoothing * Time.deltaTime);
|
||||
}
|
||||
|
||||
void DecayAdditionalDirection(){
|
||||
@@ -303,16 +346,19 @@ 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);
|
||||
}
|
||||
|
||||
// Decay the gravity
|
||||
additionalMoveDirection.y -= data.gravityPower;
|
||||
additionalMoveDirection.y = Mathf.Max(0f, additionalMoveDirection.y);
|
||||
}
|
||||
|
||||
private void UpdateGravityLate(){
|
||||
// Decay jump power
|
||||
data.jumpPower -= data.jumpPowerDecay * Time.deltaTime;
|
||||
data.jumpPower -= smoothedJumpDecay * Time.deltaTime;
|
||||
data.jumpPower = Mathf.Max(0f, data.jumpPower);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b3b4e13d59527d1429a62dde97c6a001
|
||||
guid: b3b4e13d59527d1429a62dde97c6a001
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 98
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
Reference in New Issue
Block a user