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(); } }
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); } }
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 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 Prepare() { #if UNITY_EDITOR mPerfWatch.Reset(); mPerfWatch.Start(); #endif if (Spline && StartMesh && ExtrusionParameter > 0) { StartMeshInfo = new MeshInfo(StartMesh, true, false); if (EndMesh) { EndMeshInfo = new MeshInfo(EndMesh, false, true); } else { EndMeshInfo = new MeshInfo(StartMesh, false, true); } // Calculate Steps float tf = FromTF; mSegmentInfo.Clear(); FromTF = Mathf.Clamp01(FromTF); ToTF = Mathf.Max(FromTF, Mathf.Clamp01(ToTF)); Vector3 scale; if (FromTF != ToTF) { switch (Extrusion) { case MeshExtrusion.FixedF: while (tf < ToTF) { scale = getScale(tf); mSegmentInfo.Add(new CurvyMeshSegmentInfo(this, tf, scale)); tf += ExtrusionParameter; } break; case MeshExtrusion.FixedDistance: float d = Spline.TFToDistance(FromTF); tf = Spline.DistanceToTF(d); while (tf < ToTF) { scale = getScale(tf); mSegmentInfo.Add(new CurvyMeshSegmentInfo(this, tf, d, scale)); d += ExtrusionParameter; tf = Spline.DistanceToTF(d); } break; case MeshExtrusion.Adaptive: while (tf < ToTF) { scale = getScale(tf); mSegmentInfo.Add(new CurvyMeshSegmentInfo(this, tf, scale)); int dir = 1; Spline.MoveByAngle(ref tf, ref dir, ExtrusionParameter, CurvyClamping.Clamp, 0.005f); } break; } if (!Mathf.Approximately(tf, ToTF)) { tf = ToTF; } scale = getScale(tf); mSegmentInfo.Add(new CurvyMeshSegmentInfo(this, tf, scale)); } } #if UNITY_EDITOR mPerfWatch.Stop(); DebugPerfPrepare = mPerfWatch.ElapsedTicks / (double)System.TimeSpan.TicksPerMillisecond; mPerfWatch.Reset(); #endif }
/// <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; } } } }