void DoInterpolate() { if (!mSpline.IsInitialized) { return; } GameObject go = Fsm.GetOwnerDefaultTarget(GameObject); if (go) { float tf = (PositionMode == CurvyPositionMode.Relative) ? CurvyUtility.ClampTF(Position.Value, Clamping) : mSpline.DistanceToTF(Position.Value, Clamping); Vector3 p = (UseCache.Value) ? mSpline.InterpolateFast(tf) : mSpline.Interpolate(tf); if (Space == Space.Self) { go.transform.localPosition = p; if (SetOrientation) { go.transform.localRotation = mSpline.GetOrientationFast(tf); } } else { go.transform.position = mSpline.transform.TransformPoint(p); go.transform.localRotation = mSpline.transform.rotation * mSpline.GetOrientationFast(tf); } } }
void doUpdate() { if (!Spline || !Spline.IsInitialized) { return; } // Runtime processing if (Application.isPlaying) { int dir = Dir; // get the TF of the current distance. // Note: It's recommended to use the TF based methods in consecutive calls, as the distance based // methods need to convert distance to TF internally each time! float tf = Spline.DistanceToTF(mDistance); // Move using cached values(slightly faster) or interpolate position now (more exact) // Note that we pass mTF and mDir by reference. These values will be changed by the Move methods mTransform.position = (FastInterpolation) ? Spline.MoveByFast(ref tf, ref dir, Speed * Time.deltaTime, Clamping) : Spline.MoveBy(ref tf, ref dir, Speed * Time.deltaTime, Clamping); mDistance = Spline.TFToDistance(tf); // Rotate the transform to match the spline's orientation if (SetOrientation) { transform.rotation = Spline.GetOrientationFast(tf); } Dir = dir; } else // Editor processing: continuously place the transform to reflect property changes in the editor { InitPosAndRot(); } }
public CurvyMeshSegmentInfo(SplinePathMeshBuilder mb, float tf, float distance, Vector3 scale) { Target = mb.Spline; TF = tf; mDistance = distance; Vector3 p = (mb.FastInterpolation) ? Target.InterpolateFast(TF) : Target.Interpolate(TF); if (mb.UseWorldPosition) Matrix = Matrix4x4.TRS(mb.Transform.InverseTransformPoint(p), Target.GetOrientationFast(TF), scale); else Matrix = Matrix4x4.TRS(Target.Transform.InverseTransformPoint(p), Target.GetOrientationFast(TF), scale); }
public CurvyMeshSegmentInfo(SplinePathMeshBuilder mb, float tf, float distance, Vector3 scale) { Target = mb.Spline; TF = tf; mDistance = distance; Vector3 p = (mb.FastInterpolation) ? Target.InterpolateFast(TF) : Target.Interpolate(TF); if (mb.UseWorldPosition) { Matrix = Matrix4x4.TRS(mb.Transform.InverseTransformPoint(p), Target.GetOrientationFast(TF), scale); } else { Matrix = Matrix4x4.TRS(Target.transform.InverseTransformPoint(p), Target.GetOrientationFast(TF), scale); } }
void Set() { float tf; // First get the TF if needed if (UseWorldUnits) { if (Distance >= Spline.Length) { Distance -= Spline.Length; } else if (Distance < 0) { Distance += Spline.Length; } tf = Spline.DistanceToTF(Distance); } else { if (Distance >= 1) { Distance -= 1; } else if (Distance < 0) { Distance += 1; } tf = Distance; } // Set the position if (transform.position != Spline.Interpolate(tf)) { transform.position = Spline.Interpolate(tf); } // Set the rotation if (SetOrientation && transform.rotation != Spline.GetOrientationFast(tf)) { transform.rotation = Spline.GetOrientationFast(tf); } }
// Update is called once per frame void doUpdate() { if (!Spline || !Spline.IsInitialized) { return; } // Runtime processing if (Application.isPlaying) { int dir = Dir; // Move at a constant speed? if (MoveByWorldUnits) { // either used cached values(slightly faster) or interpolate position now (more exact) // Note that we pass mTF and mDir by reference. These values will be changed by the Move methods mTransform.position = (FastInterpolation) ? Spline.MoveByFast(ref mTF, ref dir, Speed * Time.deltaTime, Clamping) : // linear interpolate cached values Spline.MoveBy(ref mTF, ref dir, Speed * Time.deltaTime, Clamping); // interpolate now } else // Move at constant F // either used cached values(slightly faster) or interpolate position now (more exact) // Note that we pass mTF and mDir by reference. These values will be changed by the Move methods { mTransform.position = (FastInterpolation) ? Spline.MoveFast(ref mTF, ref dir, Speed * Time.deltaTime, Clamping) : // linear interpolate cached values Spline.Move(ref mTF, ref dir, Speed * Time.deltaTime, Clamping); // interpolate now } // Rotate the transform to match the spline's orientation if (SetOrientation) { transform.rotation = Spline.GetOrientationFast(mTF); } Dir = dir; } else // Editor processing: continuously place the transform to reflect property changes in the editor { InitPosAndRot(); } }
void DoFindPoint() { if (!mSpline.IsInitialized || !SourcePoint.UseVariable) { return; } if (!StoreTF.UseVariable && !StorePosition.UseVariable && !StoreUpVector.UseVariable && !StoreRotation.UseVariable) { return; } Vector3 pos = (Space == Space.Self) ? SourcePoint.Value : mSpline.transform.InverseTransformPoint(SourcePoint.Value); float _tf = mSpline.GetNearestPointTF(pos); if (StoreTF.UseVariable) { StoreTF.Value = _tf; } if (StorePosition.UseVariable) { StorePosition.Value = (Space == Space.Self) ? mSpline.Interpolate(_tf) : mSpline.transform.TransformPoint(mSpline.Interpolate(_tf)); } if (StoreTangent.UseVariable) { StoreTangent.Value = (Space == Space.Self) ? mSpline.GetTangent(_tf) : mSpline.transform.TransformDirection(mSpline.GetTangent(_tf)); } if (StoreUpVector.UseVariable) { StoreUpVector.Value = (Space == Space.Self) ? mSpline.GetOrientationUpFast(_tf) : mSpline.transform.TransformDirection(mSpline.GetOrientationUpFast(_tf)); } if (StoreRotation.UseVariable) { if (Space == Space.Self) { StoreRotation.Value = (StoreUpVector.IsNone) ? mSpline.GetOrientationFast(_tf) : Quaternion.LookRotation(mSpline.GetTangent(_tf), StoreUpVector.Value); } else { StoreRotation.Value = Quaternion.LookRotation(mSpline.transform.TransformDirection(mSpline.GetTangent(_tf)), mSpline.transform.TransformDirection(mSpline.GetOrientationUpFast(_tf))); } } }
void DoInterpolate() { if (!mSpline.IsInitialized) { return; } System.Type metaType = System.Type.GetType(MetaDataType.Value); bool calc = !Input.IsNone; if (calc) { float f = (UseWorldUnits.Value) ? mSpline.DistanceToTF(Input.Value) : Input.Value; if (StorePosition.UseVariable) { StorePosition.Value = (UseCache.Value) ? mSpline.InterpolateFast(f) : mSpline.Interpolate(f); } if (StoreTangent.UseVariable) { StoreTangent.Value = mSpline.GetTangent(f); } if (StoreUpVector.UseVariable) { StoreUpVector.Value = mSpline.GetOrientationUpFast(f); } if (StoreRotation.UseVariable) { StoreRotation.Value = (StoreUpVector.IsNone) ? mSpline.GetOrientationFast(f) : Quaternion.LookRotation(mSpline.GetTangent(f), StoreUpVector.Value); } if (StoreScale.UseVariable) { StoreScale.Value = mSpline.InterpolateScale(f); } if (StoreTF.UseVariable) { StoreTF.Value = f; } if (StoreDistance.UseVariable) { StoreDistance.Value = (UseWorldUnits.Value) ? Input.Value : mSpline.TFToDistance(f); } if (metaType != null) { if (StoreMetadata.UseVariable) { StoreMetadata.Value = mSpline.GetMetadata(metaType, f); } if (StoreInterpolatedMetadata.useVariable) { StoreInterpolatedMetadata.SetValue(mSpline.InterpolateMetadata(metaType, f)); } } CurvySplineSegment seg = null; float segF = 0; if (StoreSegment.UseVariable) { seg = getSegment(f, out segF); StoreSegment.Value = seg.gameObject; } if (StoreSegmentF.UseVariable) { if (!seg) { seg = getSegment(f, out segF); } StoreSegmentF.Value = segF; } if (StoreSegmentDistance.UseVariable) { if (!seg) { seg = getSegment(f, out segF); } StoreSegmentDistance.Value = seg.LocalFToDistance(segF); } } // General if (StoreLength.UseVariable) { StoreLength.Value = mSpline.Length; } if (StoreCount.UseVariable) { StoreCount.Value = (mSpline is CurvySplineGroup) ? ((CurvySplineGroup)mSpline).Count : ((CurvySpline)mSpline).Count; } }
void Update() { Vector3 moveDelta = Vector3.zero; Vector3 oldPos = mTransform.position; // store old position float oldTF = TF; // store old tf float minY = mLastCurveY; // store old minimum height float moveaxis = Input.GetAxis("Horizontal"); bool jump = Input.GetButton("Jump"); // Handle Left/Right movement if (moveaxis != 0) { // Calculate new spline position, setting movement to x/z and storing minimum height int dir = (moveaxis > 0) ? -1 : 1; int newdir = dir; Vector3 newPos = Spline.MoveBy(ref TF, ref newdir, Mathf.Abs(moveaxis) * Speed * Time.smoothDeltaTime, CurvyClamping.Loop); // y-position needs extra handling, so just store x/z in moveDelta moveDelta.x = newPos.x - oldPos.x; moveDelta.z = newPos.z - oldPos.z; minY = newPos.y; } // Jumping (Y++) if (jump && mJumpDurationLeft > 0) { moveDelta += new Vector3(0, JumpSpeed * Time.smoothDeltaTime, 0); mJumpDurationLeft -= Time.deltaTime; } else // Gravity (Y--) { moveDelta += new Vector3(0, -Gravity * Time.smoothDeltaTime, 0); } // If we would move below the spline, restrict movement to stay above it if (oldPos.y + moveDelta.y < minY) { moveDelta.y = minY - oldPos.y; mJumpDurationLeft = JumpDuration; } // The actual moving if (moveDelta != Vector3.zero) { // Move and handle collision if (mController.Move(moveDelta) != CollisionFlags.None) { // If we're not on top of a collider => Halt and reset to last "valid" position if (mStopMoving) { mTransform.position = oldPos; TF = oldTF; minY = mLastCurveY; } } else { mStopMoving = false; } // Align rotation to spline mTransform.rotation = Spline.GetOrientationFast(TF); } mLastCurveY = minY; }
/// <summary> /// Rebuilds the path. /// </summary> /// <param name="force">If true, all existing clones will be destroyed, otherwise they will be reused</param> /// <remarks>If you change the Source array by code, call Refresh(true)</remarks> public void Refresh(bool force) { if (Spline == null || !Spline.IsInitialized) { return; } // we need a spline length if (Spline.Length == 0) { Spline.SetDirtyAll(); } checkSources(); if (Source.Length == 0) { Clear(); return; } // get size of clones and calculate number of clones needed float totaldepth; float[] depths = getSourceDepths(out totaldepth); int count = 0; if (!Mathf.Approximately(0, totaldepth)) { switch (Mode) { case SplinePathCloneBuilderMode.CloneGroup: count = Mathf.FloorToInt(Spline.Length / totaldepth) * Source.Length; break; default: // Individual float d = Spline.Length; int i = 0; while (d > 0 && count < MAXCLONES) { d -= depths[i++] + Gap; count++; if (i == Source.Length) { i = 0; } } if (count != MAXCLONES) { count--; } break; } } // Constrain max clones if (count >= MAXCLONES) { Debug.LogError("SplinePathCloneBuilder: MAXCLONES reached, ensure to have proper colliders in place! If you really want to clone more than " + MAXCLONES + " objects, increase MAXCLONES in SplinePathCloneBuilder.cs (Line 15)!"); } else { // Clear if (force) { Clear(); // Clear all clones } else { Clear(count); // Smart Clear only unneeded } int idx = 0; float distance = 0; int current = -1; int existing = ObjectCount; while (++current < count) { float tf = Spline.DistanceToTF(distance + depths[idx] / 2); if (current < existing) { Transform T = mTransform.GetChild(current); if (UseWorldPosition) { T.position = Spline.Interpolate(tf); } else { T.localPosition = Spline.Interpolate(tf); } T.rotation = Spline.GetOrientationFast(tf) * Source[idx].transform.rotation; } else { GameObject clone; if (OnGetClone != null) { clone = OnGetClone(this, Source[idx]); } else { clone = CloneObject(Source[idx]); } if (clone) { Transform T = clone.transform; T.parent = transform; clone.name = string.Format("{0:0000}", current) + clone.name; if (UseWorldPosition) { T.position = Spline.Interpolate(tf); } else { T.localPosition = Spline.Interpolate(tf); } T.rotation = Spline.GetOrientationFast(tf) * Source[idx].transform.rotation; } } distance += depths[idx] + Gap; if (++idx == Source.Length) { idx = 0; } } } }