/// <summary> /// Putting additional tail transform in chain list (added to the end of tail) /// </summary> public TailSegment User_AddTailTransform(Transform transform) { TailSegment newSeg = new TailSegment(transform); TailSegment last = TailSegments[TailSegments.Count - 1]; newSeg.ParamsFromAll(last); newSeg.RefreshFinalPos(newSeg.transform.position); newSeg.RefreshFinalRot(newSeg.transform.rotation); newSeg.ProceduralPosition = newSeg.transform.position; newSeg.PosRefRotation = newSeg.transform.rotation; _TransformsGhostChain.Add(transform); TailSegments.Add(newSeg); last.SetChildRef(newSeg); newSeg.SetParentRef(last); newSeg.SetChildRef(GhostChild); GhostChild.SetParentRef(newSeg); // Resetting indexes for curves for (int i = 0; i < TailSegments.Count; i++) { TailSegments[i].SetIndex(i, TailSegments.Count); } return(newSeg); }
/// <summary> /// Syncing tail with current transforms positions and rotations /// </summary> public void User_ReposeTail() { GhostParent.Reset(); for (int i = 0; i < TailSegments.Count; i++) { TailSegments[i].Reset(); } GhostChild.Reset(); }
/// <summary> /// Dynamically removing tail segments from chain /// </summary> /// <param name="fromLastTo"> Segment with this index will be removed too but used as ghosting child </param> public void User_CutEndSegmentsTo(int fromLastTo) { if (fromLastTo < TailSegments.Count) { GhostChild = TailSegments[fromLastTo]; GhostChild.SetChildRef(null); for (int i = TailSegments.Count - 1; i >= fromLastTo; i--) { TailSegments.RemoveAt(i); _TransformsGhostChain.RemoveAt(i); } } else { Debug.Log("[Tail Animator Cutting] Wrong index, you want cut from end to " + fromLastTo + " segment but there are only " + TailSegments.Count + " segments!"); } }
void UpdateTailAlgorithm() { TailCalculations_Begin(); // Root definition if (framesToSimulate != 0) // If framerate not defined then framesToSimulate is always == 1 { if (UseCollision) { BeginCollisionsUpdate(); // Updating colliders to collide with } // If post processing is needed we computing reference coordinates bool postProcesses = PostProcessingNeeded(); MotionInfluenceLimiting(); for (int i = 0; i < framesToSimulate; i++) // Simulating update frames { SimulateTailMotionFrame(postProcesses); } // Updating root bone position TailSegments[_tc_startI].transform.position = TailSegments[_tc_startI].ProceduralPositionWeightBlended; TailSegments[_tc_startI].RefreshFinalPos(TailSegments[_tc_startI].ProceduralPositionWeightBlended); //TailSegments[_tc_startI].RefreshFinalLocalPos(TailSegments[_tc_startI].transform.localPosition); // Applying calculated coords to transforms if (_tc_startII > -1) { TailSegment child = TailSegments[_tc_startII]; // Used in while() loops below while (child != GhostChild) { // Calculate rotation TailCalculations_SegmentRotation(child, child.LastKeyframeLocalPosition); // Apply coords to segments TailCalculations_ApplySegmentMotion(child); child = child.ChildBone; } } // If ghost child has transform let's apply motion too (change rotation of last bone) TailCalculations_SegmentRotation(GhostChild, GhostChild.LastKeyframeLocalPosition); GhostChild.ParentBone.transform.rotation = GhostChild.ParentBone.TrueTargetRotation; GhostChild.ParentBone.RefreshFinalRot(GhostChild.ParentBone.TrueTargetRotation); if (GhostChild.transform) { GhostChild.RefreshFinalPos(GhostChild.transform.position); GhostChild.RefreshFinalRot(GhostChild.transform.rotation); } } else // Skipping tail motion simulation and just applying coords computed lately // Executed only when using target UpdateRate { if (InterpolateRate) { secPeriodDelta = rateDelta / 24f; deltaForLerps = secPeriodDelta; // Unify delta value not amplified -> 1f / rate SimulateTailMotionFrame(PostProcessingNeeded()); if (_tc_startII > -1) { TailSegment child = TailSegments[_tc_startII]; while (child != GhostChild) { TailCalculations_SegmentRotation(child, child.LastKeyframeLocalPosition); TailCalculations_ApplySegmentMotion(child); child = child.ChildBone; } } TailCalculations_SegmentRotation(GhostChild, GhostChild.LastKeyframeLocalPosition); GhostChild.ParentBone.transform.rotation = GhostChild.ParentBone.TrueTargetRotation; GhostChild.ParentBone.RefreshFinalRot(GhostChild.ParentBone.TrueTargetRotation); } else { if (_tc_startI > -1) { TailSegment segment = TailSegments[_tc_startI]; while (segment != null) { if (segment.transform) { segment.transform.position = segment.LastFinalPosition; segment.transform.rotation = segment.LastFinalRotation; } else { break; } segment = segment.ChildBone; } } else { } } } }