/// <summary> /// Returns the percent from the spline at a given distance from the start point /// </summary> /// <param name="start">The start point</param> /// /// <param name="distance">The distance to travel</param> /// <param name="direction">The direction towards which to move</param> /// <returns></returns> public double Travel(double start, float distance, Spline.Direction direction) { float moved = 0f; float lastMoved = 0f; Vector3 lastPoint = EvaluatePosition(start); Vector3 currentPoint = lastPoint; int step = DMath.FloorInt(start / moveStep); double percent = moveStep * (step + 1); double lastPercent = start; while (moved < distance) { if (direction == Spline.Direction.Forward) { step++; } else { step--; } lastPercent = percent; percent = moveStep * step; if (percent < 0.0 || percent > 1.0) { break; } currentPoint = EvaluatePosition(percent); lastMoved = moved; moved += Vector3.Distance(currentPoint, lastPoint); lastPoint = currentPoint; } double distancePercent = DMath.InverseLerp(lastMoved, moved, distance); return(DMath.Lerp(lastPercent, percent, distancePercent)); }
/// <summary> /// Returns the percent from the spline at a given distance from the start point /// </summary> /// <param name="start">The start point</param> /// /// <param name="distance">The distance to travel</param> /// <param name="direction">The direction towards which to move</param> /// <returns></returns> public double Travel(double start, float distance, Spline.Direction direction) { float moved = 0f; float lastMoved = 0f; Vector3 lastPoint = EvaluatePosition(start); Vector3 currentPoint = lastPoint; int step = GetSampleIndex(start); while (moved < distance) { if (direction == Spline.Direction.Forward) { step++; } else { step--; } if (step < 0 || step >= samples.Length) { break; } currentPoint = samples[step].position; lastMoved = moved; moved += Vector3.Distance(currentPoint, lastPoint); lastPoint = currentPoint; } double distancePercent = DMath.InverseLerp(lastMoved, moved, distance); return(DMath.Lerp(samples[Mathf.Max(0, step - 1)].percent, samples[step].percent, distancePercent)); }
public SplineSegment(SplineSegment input) { spline = input.spline; start = input.start; end = input.end; direction = input.direction; }
public void AddSpline(Node node, int connectionIndex, Spline.Direction direction = Spline.Direction.Forward) { if (root == null) { return; } Node.Connection[] connections = node.GetConnections(); Element newElement = new Element(); foreach (Node.Connection connection in connections) { if (connection.computer == _elements[_elements.Length - 1].computer) { if ((connection.pointIndex >= _elements[_elements.Length - 1].startPoint && connection.pointIndex <= _elements[_elements.Length - 1].endPoint) || (connection.pointIndex >= _elements[_elements.Length - 1].endPoint && connection.pointIndex <= _elements[_elements.Length - 1].startPoint)) { if (_elements[_elements.Length - 1].startPoint < 0) { _elements[_elements.Length - 1].startPoint = 0; } _elements[_elements.Length - 1].endPoint = connection.pointIndex; newElement.computer = connections[connectionIndex].computer; newElement.startPoint = connections[connectionIndex].pointIndex; if (direction == Spline.Direction.Backward) { newElement.endPoint = 0; } AddElement(newElement); return; } } } Debug.LogError("Connection not valid. Node must have computer " + _elements[_elements.Length - 1].computer.name + " in order to connect"); }
public void SetDistance(float distance) { _followResult = Evaluate(0.0); Spline.Direction dir = direction; direction = Spline.Direction.Forward; Move(distance); direction = dir; }
protected override double Travel(double start, float distance, Spline.Direction direction, out float traveled) { if (usePreviousLane) { return(_segment.customPaths[_lastLane - 1].Travel(start, distance, direction, out traveled)); } return(_segment.customPaths[_lane - 1].Travel(start, distance, direction, out traveled)); }
/// <summary> /// Returns the percent from the spline at a given distance from the start point /// </summary> /// <param name="start">The start point</param> /// <param name="distance">The distance to travel</param> /// <param name="direction">The direction towards which to move</param> /// <param name="traveled">Returns the distance actually traveled. Usually equal to distance but could be less if the travel distance exceeds the remaining spline length.</param> /// <param name="mode">If set to EvaluateMode.Accurate, the actual spline will be evaluated instead of the cached samples.</param> /// <returns></returns> public virtual double Travel(double start, float distance, Spline.Direction direction, out float traveled, EvaluateMode mode = EvaluateMode.Cached) { traveled = 0f; if (mode == EvaluateMode.Accurate) { return(spline.Travel(start, distance, direction)); } if (samples.Length <= 1) { return(0.0); } if (direction == Spline.Direction.Forward && start >= 1.0) { return(1.0); } else if (direction == Spline.Direction.Backward && start <= 0.0) { return(0.0); } if (distance == 0f) { return(DMath.Clamp01(start)); } Vector3 lastPosition = EvaluatePosition(start); double lastPercent = start; int nextSampleIndex = direction == Spline.Direction.Forward ? DMath.CeilInt(start * (samples.Length - 1)) : DMath.FloorInt(start * (samples.Length - 1)); float lastDistance = 0f; while (true) { lastDistance = Vector3.Distance(samples[nextSampleIndex].position, lastPosition); lastPosition = samples[nextSampleIndex].position; traveled += lastDistance; if (traveled >= distance) { break; } lastPercent = samples[nextSampleIndex].percent; if (direction == Spline.Direction.Forward) { if (nextSampleIndex == samples.Length - 1) { break; } nextSampleIndex++; } else { if (nextSampleIndex == 0) { break; } nextSampleIndex--; } } return(DMath.Lerp(lastPercent, samples[nextSampleIndex].percent, 1f - (traveled - distance) / lastDistance)); }
public double Travel(double percent, float distance, Spline.Direction direction, out float moved, bool loop) { double max = direction == Spline.Direction.Forward ? 1.0 : 0.0; if (start >= 0) { max = spline.GetPointPercent(start); } return(TravelClamped(percent, distance, direction, max, out moved, loop)); }
protected virtual double Travel(double start, float distance, Spline.Direction direction, out float traveled) { if (_segment.type == LevelSegment.Type.Custom && _segment.customMainPath >= 0 && _segment.customPaths.Length > 0) { return(_segment.customPaths[_segment.customMainPath].Travel(start, distance, direction, out traveled)); } else { return(_segment.Travel(start, distance, direction, out traveled)); } }
static void InvertDirection(ref Spline.Direction direction) { if (direction == Spline.Direction.Forward) { direction = Spline.Direction.Backward; } else { direction = Spline.Direction.Forward; } }
public override void EnterAddress(Node node, int pointIndex, Spline.Direction direction = Spline.Direction.Forward) { int element = _address.GetElementIndex(_followResult.percent); double localPercent = _address.PathToLocalPercent(_followResult.percent, element); base.EnterAddress(node, pointIndex, direction); double newPercent = _address.LocalToPathPercent(localPercent, element); SetPercent(newPercent); percentSet = false; }
public override void EnterAddress(Node node, int pointIndex, Spline.Direction direction = Spline.Direction.Forward) { int elementIndex = _address.GetElementIndex(_result.percent); double localPercent = _address.PathToLocalPercent(_result.percent, elementIndex); base.EnterAddress(node, pointIndex, direction); double num = _address.LocalToPathPercent(localPercent, elementIndex); setPercentOnRebuild = true; targetPercentOnRebuild = num; }
public virtual void EnterAddress(Node node, int connectionIndex, Spline.Direction direction = Spline.Direction.Forward) { if (!sampleUser) { int depth = _address.depth; address.AddSpline(node, connectionIndex, direction); if (_address.depth != depth) { Rebuild(sampleComputer: true); } } }
public virtual double Travel(double start, float distance, Spline.Direction direction) { if (samples.Length <= 1) { return(0.0); } if (direction == Spline.Direction.Forward && start >= 1.0) { return(1.0); } if (direction == Spline.Direction.Backward && start <= 0.0) { return(0.0); } if (distance == 0f) { return(DMath.Clamp01(start)); } float num = 0f; Vector3 b = EvaluatePosition(start); double a = start; int num2 = (direction != Spline.Direction.Forward) ? DMath.FloorInt(start * (double)(samples.Length - 1)) : DMath.CeilInt(start * (double)(samples.Length - 1)); float num3 = 0f; while (true) { num3 = Vector3.Distance(samples[num2].position, b); b = samples[num2].position; num += num3; if (num >= distance) { break; } a = samples[num2].percent; if (direction == Spline.Direction.Forward) { if (num2 == samples.Length - 1) { break; } num2++; } else { if (num2 == 0) { break; } num2--; } } return(DMath.Lerp(a, samples[num2].percent, 1f - (num - distance) / num3)); }
void ApplyTracer(SplineComputer spline, double percent, Spline.Direction direction) { bool rebuild = tracer.spline != spline; tracer.spline = spline; if (rebuild) { tracer.RebuildImmediate(); } tracer.direction = direction; tracer.SetPercent(tracer.ClipPercent(percent)); }
/// <summary> /// Get the available node in front or behind the follower /// </summary> /// <returns></returns> public Node GetNextNode() { SplineComputer comp; double evaluatePercent = 0.0; Spline.Direction dir = Spline.Direction.Forward; _address.GetEvaluationValues(_result.percent, out comp, out evaluatePercent, out dir); if (_direction == Spline.Direction.Backward) { if (dir == Spline.Direction.Forward) { dir = Spline.Direction.Backward; } else { dir = Spline.Direction.Forward; } } int[] links = comp.GetAvailableNodeLinksAtPosition(evaluatePercent, dir); if (links.Length == 0) { return(null); } //Find the closest one if (dir == Spline.Direction.Forward) { int min = comp.pointCount - 1; int index = 0; for (int i = 0; i < links.Length; i++) { if (comp.nodeLinks[links[i]].pointIndex < min) { min = comp.nodeLinks[links[i]].pointIndex; index = i; } } return(comp.nodeLinks[links[index]].node); } else { int max = 0; int index = 0; for (int i = 0; i < links.Length; i++) { if (comp.nodeLinks[links[i]].pointIndex > max) { max = comp.nodeLinks[links[i]].pointIndex; index = i; } } return(comp.nodeLinks[links[index]].node); } }
/// <summary> /// Enter a junction address. /// </summary> /// <param name="element">The address element to add to the address</param> public virtual void EnterAddress(Node node, int connectionIndex, Spline.Direction direction = Spline.Direction.Forward) { if (sampleUser) { return; } int lastDepth = _address.depth; address.AddSpline(node, connectionIndex, direction); if (_address.depth != lastDepth) { Rebuild(true); } }
public static void OnGUI() { if (!loaded) { LoadPrefs(); } EditorGUILayout.LabelField("Newly created splines:", EditorStyles.boldLabel); startInCreationMode = EditorGUILayout.Toggle("Start in Creation Mode", startInCreationMode); defaultComputerSpace = (SplineComputer.Space)EditorGUILayout.EnumPopup("Space", defaultComputerSpace); defaultType = (Spline.Type)EditorGUILayout.EnumPopup("Type", defaultType); defaultAlwaysDraw = EditorGUILayout.Toggle("Always draw", defaultAlwaysDraw); defaultShowThickness = EditorGUILayout.Toggle("Show thickness", defaultShowThickness); default2D = EditorGUILayout.Toggle("2D Mode", default2D); defaultColor = EditorGUILayout.ColorField("Spline color", defaultColor); EditorGUILayout.Space(); EditorGUILayout.LabelField("Newly created points:", EditorStyles.boldLabel); createPointSize = EditorGUILayout.FloatField("Default Size", createPointSize); createPointColor = EditorGUILayout.ColorField("Default Color", createPointColor); EditorGUILayout.Space(); EditorGUILayout.LabelField("Editor", EditorStyles.boldLabel); highlightColor = EditorGUILayout.ColorField("Highlight color", highlightColor); highlightContentColor = EditorGUILayout.ColorField("Highlight content color", highlightContentColor); duplicationDirection = (Spline.Direction)EditorGUILayout.EnumPopup("Duplicate Direction", duplicationDirection); showPointNumbers = EditorGUILayout.Toggle("Show point numbers", showPointNumbers); if (GUILayout.Button("Use Defaults", GUILayout.Width(120))) { duplicationDirection = Spline.Direction.Forward; defaultAlwaysDraw = false; defaultShowThickness = false; default2D = false; startInCreationMode = true; defaultColor = Color.white; highlightColor = new Color(0f, 0.564f, 1f, 1f); highlightContentColor = new Color(1f, 1f, 1f, 0.95f); showPointNumbers = false; defaultComputerSpace = SplineComputer.Space.Local; defaultType = Spline.Type.CatmullRom; createPointSize = 1f; createPointColor = Color.white; SavePrefs(); } if (GUI.changed) { SavePrefs(); } }
public double Travel(double start, float distance, Spline.Direction direction, int iterations) { if (GetTotalPointCount() <= 1) { return(0.0); } float num = 0f; Vector3 b = EvaluatePosition(start); double a = start; int num2 = iterations - 1; int num3 = (direction != Spline.Direction.Forward) ? DMath.FloorInt(start * (double)num2) : DMath.CeilInt(start * (double)num2); float num4 = 0f; Vector3 zero = Vector3.zero; double num5; while (true) { num5 = (double)num3 / (double)num2; zero = EvaluatePosition(num5); num4 = Vector3.Distance(zero, b); b = zero; num += num4; if (num >= distance) { break; } a = num5; if (direction == Spline.Direction.Forward) { if (num3 == num2) { break; } num3++; } else { if (num3 == 0) { break; } num3--; } } return(DMath.Lerp(a, num5, 1f - (num - distance) / num4)); }
/// <summary> /// Returns the percent from the spline at a given distance from the start point /// </summary> /// <param name="start">The start point</param> /// /// <param name="distance">The distance to travel</param> /// <param name="direction">The direction towards which to move</param> /// <returns></returns> public double Travel(double start, float distance, Spline.Direction direction, int iterations) { if (GetTotalPointCount() <= 1) { return(0.0); } float moved = 0f; Vector3 lastPosition = EvaluatePosition(start); double lastPercent = start; int i = iterations - 1; int nextSampleIndex = direction == Spline.Direction.Forward ? DMath.CeilInt(start * i) : DMath.FloorInt(start * i); float lastDistance = 0f; Vector3 pos = Vector3.zero; double percent = start; while (true) { percent = (double)nextSampleIndex / i; pos = EvaluatePosition(percent); lastDistance = Vector3.Distance(pos, lastPosition); lastPosition = pos; moved += lastDistance; if (moved >= distance) { break; } lastPercent = percent; if (direction == Spline.Direction.Forward) { if (nextSampleIndex == i) { break; } nextSampleIndex++; } else { if (nextSampleIndex == 0) { break; } nextSampleIndex--; } } return(DMath.Lerp(lastPercent, percent, 1f - (moved - distance) / lastDistance)); }
void ApplyOffset() { if (isEngine) { ResetSegments(); return; } float totalMoved = 0f, moved = 0f; double start = front.tracer.UnclipPercent(front.tracer.result.percent); //Travel backwards along the front wagon's spline Spline.Direction inverseDirection = front.segment.direction; InvertDirection(ref inverseDirection); SplineComputer spline = front.segment.spline; double percent = front.segment.Travel(start, offset, inverseDirection, out moved, front.segment.spline.isClosed); totalMoved += moved; //Finalize if moved fully without reaching a spline end or a junction if (Mathf.Approximately(totalMoved, offset)) { if (segment != front.segment) { if (back != null) { back.segment = segment; } } if (segment != front.segment) { segment = front.segment; } ApplyTracer(spline, percent, front.tracer.direction); return; } //Otherwise, move along the current recorded spline segment if (segment != front.segment) { inverseDirection = segment.direction; InvertDirection(ref inverseDirection); spline = segment.spline; percent = segment.Travel(offset - totalMoved, inverseDirection, out moved, segment.spline.isClosed); totalMoved += moved; } ApplyTracer(spline, percent, segment.direction); }
public double TravelClipped(double start, float distance, Spline.Direction direction) { if (clippedSamples.Length <= 1) { return(0.0); } if (distance == 0f) { return(start); } float moved = 0f; Vector3 lastPosition = EvaluatePositionClipped(start); double lastPercent = start; int nextSampleIndex = direction == Spline.Direction.Forward ? DMath.CeilInt(start * (clippedSamples.Length - 1)) : DMath.FloorInt(start * (clippedSamples.Length - 1)); float lastDistance = 0f; while (true) { lastDistance = Vector3.Distance(clippedSamples[nextSampleIndex].position, lastPosition); lastPosition = clippedSamples[nextSampleIndex].position; moved += lastDistance; if (moved >= distance) { break; } lastPercent = ClipPercent(clippedSamples[nextSampleIndex].percent); if (direction == Spline.Direction.Forward) { if (nextSampleIndex == clippedSamples.Length - 1) { break; } nextSampleIndex++; } else { if (nextSampleIndex == 0) { break; } nextSampleIndex--; } } return(DMath.Lerp(lastPercent, ClipPercent(clippedSamples[nextSampleIndex].percent), 1f - (moved - distance) / lastDistance)); }
public double TravelClipped(double start, float distance, Spline.Direction direction) { if (base.clippedSamples.Length <= 1) { return(0.0); } if (distance == 0f) { return(start); } float num = 0f; Vector3 b = EvaluatePositionClipped(start); double a = start; int num2 = (direction != Spline.Direction.Forward) ? DMath.FloorInt(start * (double)(base.clippedSamples.Length - 1)) : DMath.CeilInt(start * (double)(base.clippedSamples.Length - 1)); float num3 = 0f; while (true) { num3 = Vector3.Distance(base.clippedSamples[num2].position, b); b = base.clippedSamples[num2].position; num += num3; if (num >= distance) { break; } a = ClipPercent(base.clippedSamples[num2].percent); if (direction == Spline.Direction.Forward) { if (num2 == base.clippedSamples.Length - 1) { break; } num2++; } else { if (num2 == 0) { break; } num2--; } } return(DMath.Lerp(a, ClipPercent(base.clippedSamples[num2].percent), 1f - (num - distance) / num3)); }
public static void LoadPrefs() { defaultAlwaysDraw = EditorPrefs.GetBool("Dreamteck.Splines.defaultAlwaysDraw", false); defaultShowThickness = EditorPrefs.GetBool("Dreamteck.Splines.defaultShowThickness", false); default2D = EditorPrefs.GetBool("Dreamteck.Splines.default2D", false); startInCreationMode = EditorPrefs.GetBool("Dreamteck.Splines.startInCreationMode", true); showPointNumbers = EditorPrefs.GetBool("Dreamteck.Splines.showPointNumbers", false); pointEditSpace = (SplineComputer.Space)EditorPrefs.GetInt("Dreamteck.Splines.pointEditSpace", 1); defaultColor = LoadColor("Dreamteck.Splines.defaultColor", Color.white); highlightColor = LoadColor("Dreamteck.Splines.highlightColor", new Color(0f, 0.564f, 1f, 1f)); highlightContentColor = LoadColor("Dreamteck.Splines.highlightContentColor", new Color(1f, 1f, 1f, 0.95f)); defaultComputerSpace = (SplineComputer.Space)EditorPrefs.GetInt("Dreamteck.Splines.defaultComputerSpace", 0); defaultType = (Spline.Type)EditorPrefs.GetInt("Dreamteck.Splines.defaultType", 0); duplicationDirection = (Spline.Direction)EditorPrefs.GetInt("Dreamteck.Splines.duplicationDirection", 0); createPointSize = EditorPrefs.GetFloat("Dreamteck.Splines.createPointSize", 1f); createPointColor = LoadColor("Dreamteck.Splines.createPointColor", Color.white); loaded = true; }
public double Travel(double start, float distance, Spline.Direction direction, out float moved) { moved = 0f; if (direction == Spline.Direction.Forward && start >= 1.0) { return(1.0); } else if (direction == Spline.Direction.Backward && start <= 0.0) { return(0.0); } if (distance == 0f) { return(DMath.Clamp01(start)); } double result = sampleCollection.Travel(start, distance, direction, out moved); return(ClipPercent(result)); }
public double TravelWithOffset(double start, float distance, Spline.Direction direction, Vector3 offset, out float moved) { moved = 0f; if (direction == Spline.Direction.Forward && start >= 1.0) { return(1.0); } else if (direction == Spline.Direction.Backward && start <= 0.0) { return(0.0); } if (distance == 0f) { return(DMath.Clamp01(start)); } double result = sampleCollection.TravelWithOffset(UnclipPercent(start), distance, direction, offset, out moved, clipFrom, clipTo); return(ClipPercent(result)); }
public Node GetNextNode() { double percent = 0.0; Spline.Direction direction = Spline.Direction.Forward; _address.GetEvaluationValues(_result.percent, out SplineComputer computer, out percent, out direction); if (_direction == Spline.Direction.Backward) { direction = ((direction != Spline.Direction.Forward) ? Spline.Direction.Forward : Spline.Direction.Backward); } int[] availableNodeLinksAtPosition = computer.GetAvailableNodeLinksAtPosition(percent, direction); if (availableNodeLinksAtPosition.Length == 0) { return(null); } if (direction == Spline.Direction.Forward) { int num = computer.pointCount - 1; int num2 = 0; for (int i = 0; i < availableNodeLinksAtPosition.Length; i++) { if (computer.nodeLinks[availableNodeLinksAtPosition[i]].pointIndex < num) { num = computer.nodeLinks[availableNodeLinksAtPosition[i]].pointIndex; num2 = i; } } return(computer.nodeLinks[availableNodeLinksAtPosition[num2]].node); } int num3 = 0; int num4 = 0; for (int j = 0; j < availableNodeLinksAtPosition.Length; j++) { if (computer.nodeLinks[availableNodeLinksAtPosition[j]].pointIndex > num3) { num3 = computer.nodeLinks[availableNodeLinksAtPosition[j]].pointIndex; num4 = j; } } return(computer.nodeLinks[availableNodeLinksAtPosition[num4]].node); }
void GetAvailable() { if (user == null) { return; } currentComputer = user.address.elements[user.address.depth - 1].computer; if (currentComputer == null) { return; } double startPercent = (double)user.address.elements[user.address.depth - 1].startPoint / (currentComputer.pointCount - 1); Spline.Direction dir = Spline.Direction.Forward; if (user.address.elements[user.address.depth - 1].startPoint > user.address.elements[user.address.depth - 1].endPoint) { dir = Spline.Direction.Backward; } int[] available = currentComputer.GetAvailableNodeLinksAtPosition(startPercent, dir); nodes = new List <Node>(); connectionIndices = new List <int>(); pointIndices = new List <int>(); for (int i = 0; i < available.Length; i++) { Node node = currentComputer.nodeLinks[available[i]].node; if (currentComputer.nodeLinks[available[i]].pointIndex == user.address.elements[user.address.depth - 1].startPoint) { continue; } Node.Connection[] connections = node.GetConnections(); for (int n = 0; n < connections.Length; n++) { if (connections[n].computer == currentComputer) { continue; } nodes.Add(node); connectionIndices.Add(n); pointIndices.Add(currentComputer.nodeLinks[available[i]].pointIndex); } } }
/// <summary> /// Used to get the available junctions. Call this to update the junction list on the GUI. /// </summary> public void GetAvailableJunctions() { //Get the last SplineComputer in the junction address currentComputer = follower.address.elements[follower.address.depth - 1].computer; if (currentComputer == null) { return; } //Get the available junctions at the current address double startPercent = (double)follower.address.elements[follower.address.depth - 1].startPoint / (currentComputer.pointCount - 1); Spline.Direction dir = Spline.Direction.Forward; if (follower.address.elements[follower.address.depth - 1].startPoint > follower.address.elements[follower.address.depth - 1].endPoint) { dir = Spline.Direction.Backward; } int[] available = currentComputer.GetAvailableNodeLinksAtPosition(startPercent, dir); nodes.Clear(); connectionIndices.Clear(); pointIndices.Clear(); //Make a list of the available junctions which to use in OnGUI for the buttons for (int i = 0; i < available.Length; i++) { Node node = currentComputer.nodeLinks[available[i]].node; if (currentComputer.nodeLinks[available[i]].pointIndex == follower.address.elements[follower.address.depth - 1].startPoint) { continue; } Node.Connection[] connections = node.GetConnections(); for (int n = 0; n < connections.Length; n++) { if (connections[n].computer == currentComputer) { continue; } nodes.Add(node); connectionIndices.Add(n); pointIndices.Add(currentComputer.nodeLinks[available[i]].pointIndex); } } }
Vector3 HandleVelocity(Vector3 velocity) { Vector3 idealVelocity = Vector3.zero; Vector3 direction = Vector3.right; switch (velocityHandleMode) { case VelocityHandleMode.Preserve: idealVelocity = velocity; break; case VelocityHandleMode.Align: direction = _splineResult.direction; if (Vector3.Dot(velocity, direction) < 0f) { direction *= -1f; } idealVelocity = direction * velocity.magnitude; break; case VelocityHandleMode.AlignRealistic: direction = _splineResult.direction; if (Vector3.Dot(velocity, direction) < 0f) { direction *= -1f; } idealVelocity = direction * velocity.magnitude * Vector3.Dot(velocity.normalized, direction); break; } if (applyPositionX) { velocity.x = idealVelocity.x; } if (applyPositionY) { velocity.y = idealVelocity.y; } if (applyPositionZ) { velocity.z = idealVelocity.z; } return(velocity); }