void OnValidate() { if (UpdateRate < 0) { UpdateRate = 0; } if (Application.isPlaying) { RefreshSegmentsColliders(); //lastCurving = Curving; lastCurving.x += 0.001f; if (UseIK) { IK_ApplyLimitBoneSettings(); } if (UseWind) { TailAnimatorWind.Refresh(this); } } if (UsePartialBlend) { ClampCurve(BlendCurve, 0f, 1f, 0f, 1f); } }
private void Awake() { if (!Application.isPlaying) { return; } if (_instance != null) { if (_instance != this) { GameObject.Destroy(_instance); _instance = this; DontDestroyOnLoad(gameObject); Debug.Log("[Tail Animator Wind] Override wind component instance! (" + name + ")"); } } else { _instance = this; DontDestroyOnLoad(gameObject); } }
private static void GenerateWindComponentInstance() { GameObject windObj = new GameObject("Tail Animator Wind"); _instance = windObj.AddComponent <TailAnimatorWind>(); }
/// <summary> /// Method to initialize component, to have more controll than waiting for Start() method, init can be executed before or after start, as programmer need it. /// </summary> protected virtual void Init() { if (initialized) { return; } // Checking if we have transform to create tail chain from if (_TransformsGhostChain == null || _TransformsGhostChain.Count == 0) { _TransformsGhostChain = new List <Transform>(); GetGhostChain(); } // Generating tail instances for procedural animation TailSegments = new List <TailSegment>(); for (int i = 0; i < _TransformsGhostChain.Count; i++) { if (_TransformsGhostChain[i] == null) { Debug.Log("[Tail Animator] Null bones in " + name + " !"); continue; } TailSegment b = new TailSegment(_TransformsGhostChain[i]); b.SetIndex(i, _TransformsGhostChain.Count); TailSegments.Add(b); } // Checking correctness if (TailSegments.Count == 0) { Debug.Log("[Tail Animator] Could not create tail bones chain in " + name + " !"); return; } _TC_TailLength = 0f; _baseTransform = _TransformsGhostChain[0]; //if (_baseTransform.parent) // _baseTransform = _baseTransform.parent; //else // IncludeParent = false; // Setting parent-child relation for tail logics for (int i = 0; i < TailSegments.Count; i++) { TailSegment current = TailSegments[i]; TailSegment parent; #region Defining Parent Bones if (i == 0) { if (current.transform.parent) { // Creating parent and setting safety parent parent = new TailSegment(current.transform.parent); parent.SetParentRef(new TailSegment(parent.transform.parent)); } else #region If first bone is parentless { parent = new TailSegment(current.transform); Vector3 toStartDir; if (_TransformsGhostChain.Count > 1) { toStartDir = _TransformsGhostChain[0].position - _TransformsGhostChain[1].position; if (toStartDir.magnitude == 0) { toStartDir = transform.position - _TransformsGhostChain[1].position; } } else { toStartDir = current.transform.position - _TransformsGhostChain[0].position; } if (toStartDir.magnitude == 0) { toStartDir = transform.position - _TransformsGhostChain[0].position; } if (toStartDir.magnitude == 0) { toStartDir = transform.forward; } parent.LocalOffset = parent.transform.InverseTransformPoint(parent.transform.position + toStartDir); parent.SetParentRef(new TailSegment(current.transform)); } #endregion //current.InitialLocalRotation = Quaternion.Inverse(current.transform.localRotation); GhostParent = parent; GhostParent.Validate(); current.SetParentRef(GhostParent); } else // i != 0 { parent = TailSegments[i - 1]; // If bones are removed manually from chain we support custom length of bone undependent from transform parenting chain structure current.ReInitializeLocalPosRot(parent.transform.InverseTransformPoint(current.transform.position), current.transform.localRotation); } #endregion #region Defining Last Child Bone if (i == TailSegments.Count - 1) { Transform childT = null; if (current.transform.childCount > 0) { childT = current.transform.GetChild(0); } GhostChild = new TailSegment(childT); // Scale ref for ghosting object position offset Vector3 scaleDir; if (FEngineering.VIsZero(EndBoneJointOffset)) { if (current.transform.parent) { scaleDir = current.transform.position - current.transform.parent.position; } else if (current.transform.childCount > 0) { scaleDir = current.transform.GetChild(0).position - current.transform.position; } else { scaleDir = current.transform.TransformDirection(Vector3.forward) * 0.05f; } } else { scaleDir = current.transform.TransformVector(EndBoneJointOffset); } GhostChild.ProceduralPosition = current.transform.position + scaleDir; GhostChild.ProceduralPositionWeightBlended = GhostChild.ProceduralPosition; GhostChild.PreviousPosition = GhostChild.ProceduralPosition; GhostChild.PosRefRotation = Quaternion.identity; GhostChild.PreviousPosReferenceRotation = Quaternion.identity; GhostChild.ReInitializeLocalPosRot(current.transform.InverseTransformPoint(GhostChild.ProceduralPosition), Quaternion.identity); GhostChild.RefreshFinalPos(GhostChild.ProceduralPosition); GhostChild.RefreshFinalRot(GhostChild.PosRefRotation); GhostChild.TrueTargetRotation = GhostChild.PosRefRotation; current.TrueTargetRotation = current.transform.rotation; current.SetChildRef(GhostChild); GhostChild.SetParentRef(current); } else { current.SetChildRef(TailSegments[i + 1]); } #endregion current.SetParentRef(parent); _TC_TailLength += Vector3.Distance(current.ProceduralPosition, parent.ProceduralPosition); } // List with ghosts for curves etc. GhostParent.SetIndex(-1, TailSegments.Count); GhostChild.SetIndex(TailSegments.Count, TailSegments.Count); GhostParent.SetChildRef(TailSegments[0]); previousWorldPosition = BaseTransform.position; WavingRotationOffset = Quaternion.identity; if (CollidersDataToCheck == null) { CollidersDataToCheck = new List <FImp_ColliderData_Base>(); } DynamicAlwaysInclude = new List <Component>(); if (UseCollision) { SetupSphereColliders(); } // List instance for deflection feature if (_defl_source == null) { _defl_source = new List <TailSegment>(); } Waving_Initialize(); if (DetachChildren) { DetachChildrenTransforms(); } initialized = true; if (TailSegments.Count == 1) { if (TailSegments[0].transform.parent == null) { Debug.Log("[Tail Animator] Can't initialize one-bone length chain on bone which don't have any parent!"); Debug.LogError("[Tail Animator] Can't initialize one-bone length chain on bone which don't have any parent!"); TailAnimatorAmount = 0f; initialized = false; return; } } if (UseWind) { TailAnimatorWind.Refresh(this); } if (PostProcessingNeeded()) { if (!_pp_initialized) { InitializePostProcessing(); } } #region Prewarming tail to target state if (Prewarm) { ShapingParamsUpdate(); ExpertParamsUpdate(); Update(); LateUpdate(); justDelta = rateDelta; secPeriodDelta = 1f; deltaForLerps = secPeriodDelta; rateDelta = 1f / 60f; CheckIfTailAnimatorShouldBeUpdated(); if (updateTailAnimator) { int loopCount = 60 + TailSegments.Count / 2; for (int d = 0; d < loopCount; d++) { PreCalibrateBones(); LateUpdate(); } } } #endregion }