예제 #1
0
 /// <summary>
 /// For UI we must calculate it differently
 /// </summary>
 protected override Quaternion CalculateTargetRotation(FTail_Point tailPoint)
 {
     if (Lock2D)
     {
         return(CalculateFor2D(tailPoint));
     }
     else
     {
         return(base.CalculateTargetRotation(tailPoint));
     }
 }
예제 #2
0
        /// <summary>
        /// 모든 꼬리 변환을 자유롭게 이동할 수 있도록 연결 해제
        /// </summary>
        protected virtual void PrepareTailPoints()
        {
            proceduralPoints = new List <FTail_Point>();

            for (int i = 0; i < TailTransforms.Count; i++)
            {
                FTail_Point p = new FTail_Point();
                p.index           = i;
                p.Position        = TailTransforms[i].position;
                p.Rotation        = TailTransforms[i].rotation;
                p.InitialPosition = TailTransforms[i].localPosition;
                p.InitialRotation = TailTransforms[i].localRotation;

                proceduralPoints.Add(p);
            }
        }
예제 #3
0
        // V1.1 and V1.1.1/2
        /// <summary>
        /// 꼬리 변환 위치 및 회전 설정 한 꼬리 세그먼트의 목표 회전을 계산합니다.
        /// 2D 회전과 같은 일부 예외 계산을 위해 재정의합니다.
        /// </summary>
        protected virtual Quaternion CalculateTargetRotation(Vector3 startLookPos, Vector3 currentPos, FTail_Point previousTailPoint = null, FTail_Point currentTailPoint = null, int lookDirectionFixIndex = 0)
        {
            Quaternion targetRotation;

            //V1.2.5
            int fixDirForw = lookDirectionFixIndex + 1;

            if (lookDirectionFixIndex == -1)
            {
                fixDirForw            = 0;
                lookDirectionFixIndex = 0;
            }

            if (FullCorrection)
            {
                targetRotation = Quaternion.identity;

                bool rotationCollision = false;

                if (UseCollision)
                {
                    if (collisionFlags[fixDirForw] > 0f)
                    {
                        if (collisionOffsets[fixDirForw] != Vector3.zero)
                        {
                            rotationCollision = true;
                        }
                    }
                }

                if (!rotationCollision)
                {
                    if (RolledBones)
                    {
                        targetRotation = Quaternion.LookRotation(startLookPos - currentPos, previousTailPoint.TransformDirection(-lookBackDirections[fixDirForw] * 0.99f));
                    }
                    else
                    {
                        targetRotation = Quaternion.LookRotation(startLookPos - currentPos, previousTailPoint.TransformDirection(AxisLookBack));
                    }
                }
                else
                {
                    //Quaternion target = Quaternion.LookRotation(collisionOffsets[fixDirForw], previousTailPoint.TransformDirection(AxisLookBack));
                    //// Quaternion target = Quaternion.LookRotation(collisionOffsets[fixDirForw], previousTailPoint.TransformDirection(AxisLookBack)) * Quaternion.FromToRotation(tailLookDirections[lookDirectionFixIndex], ExtraToDirection);
                    //targetRotation *= Quaternion.Slerp(Quaternion.identity, target, collisionFlags[fixDirForw]);

                    Vector3 tailDirection = (startLookPos - currentPos).normalized;
                    Vector3 upwards;

                    if (RolledBones)
                    {
                        upwards = previousTailPoint.TransformDirection(-lookBackDirections[fixDirForw] * 0.99f);
                    }
                    else
                    {
                        upwards = previousTailPoint.TransformDirection(AxisLookBack);
                    }

                    Vector3 smoothedDirection = Vector3.Slerp(tailDirection, (tailDirection + collisionOffsets[currentTailPoint.index]).normalized, collisionFlags[fixDirForw]);
                    targetRotation = Quaternion.LookRotation(smoothedDirection, upwards);
                }

                if (GravityPower != Vector2.zero)
                {
                    float mul = 10 / (fixDirForw * 2.5f + 1);
                    targetRotation *= Quaternion.Euler(GravityPower.y * mul, GravityPower.x * mul, 0f);
                }

                targetRotation *= Quaternion.FromToRotation(tailLookDirections[lookDirectionFixIndex], ExtraToDirection);

                if (AnimateCorrections)
                {
                    targetRotation *= animatedCorrections[fixDirForw];
                }
                else
                {
                    targetRotation *= lookBackOffsets[fixDirForw];
                }
            }
            else
            {
                targetRotation = Quaternion.identity;

                bool rotationCollision = false;
                if (UseCollision)
                {
                    if (collisionFlags[fixDirForw] > 0f)
                    {
                        if (collisionOffsets[fixDirForw] != Vector3.zero)
                        {
                            #region Experiments

                            //Quaternion target = Quaternion.LookRotation(collisionOffsets[fixDirForw], previousTailPoint.TransformDirection(AxisLookBack));
                            ////Quaternion target = Quaternion.LookRotation(collisionOffsets[fixDirForw], previousTailPoint.TransformDirection(AxisLookBack)) * Quaternion.FromToRotation(tailLookDirections[lookDirectionFixIndex], ExtraToDirection);
                            //targetRotation *= Quaternion.Slerp(Quaternion.identity, target, collisionFlags[fixDirForw]);

                            //Quaternion target = Quaternion.LookRotation(collisionOffsets[fixDirForw], previousTailPoint.TransformDirection(AxisLookBack));
                            //targetRotation *= Quaternion.Slerp(Quaternion.identity, target, collisionFlags[fixDirForw]);

                            //Vector3 tailDirection = (startLookPos - currentPos).normalized;
                            //Vector3 smoothedDirection = Vector3.Slerp(tailDirection, (tailDirection + collisionOffsets[fixDirForw]).normalized, collisionFlags[fixDirForw]);
                            //targetRotation = Quaternion.LookRotation(smoothedDirection, previousTailPoint.TransformDirection(AxisLookBack * Mathf.Sign(FVectorMethods.VectorSum(AxisCorrection))));

                            //Vector3 smoothedDirection = Vector3.Slerp(tailDirection, (tailDirection + collisionOffsets[fixDirForw]).normalized, collisionFlags[fixDirForw]);

                            //Vector3 upwards = previousTailPoint.TransformDirection(AxisLookBack * Mathf.Sign(FVectorMethods.VectorSum(AxisCorrection)));
                            //Vector3 tailDirection = (startLookPos - currentPos).normalized;
                            //targetRotation = Quaternion.LookRotation(tailDirection, upwards);
                            //targetRotation *= Quaternion.Slerp( Quaternion.identity, Quaternion.LookRotation(collisionOffsets[currentTailPoint.index], upwards), collisionFlags[fixDirForw]);

                            #endregion Experiments

                            Vector3 tailDirection     = (startLookPos - currentPos).normalized;
                            Vector3 smoothedDirection = Vector3.Slerp(tailDirection, (tailDirection + collisionOffsets[currentTailPoint.index]).normalized, collisionFlags[fixDirForw]);
                            targetRotation    = Quaternion.LookRotation(smoothedDirection, previousTailPoint.TransformDirection(AxisLookBack));
                            rotationCollision = true;
                        }
                    }
                }

                if (!rotationCollision)
                {
                    targetRotation = Quaternion.LookRotation(startLookPos - currentPos, previousTailPoint.TransformDirection(AxisLookBack * Mathf.Sign(FVectorMethods.VectorSum(AxisCorrection))));
                }

                if (GravityPower != Vector2.zero)
                {
                    float mul = 10 / (fixDirForw * 2.5f + 1);
                    targetRotation *= Quaternion.Euler(GravityPower.y * mul, GravityPower.x * mul, 0f);
                }

                if (ExtraCorrectionOptions)
                {
                    targetRotation *= Quaternion.FromToRotation(ExtraFromDirection, ExtraToDirection);
                }
            }

            return(targetRotation);
        }
예제 #4
0
        /// <summary>
        /// 주어진 변형 목록에 대한 꼬리 모양의 움직임 애니메이션 논리 계산하기
        /// </summary>
        protected virtual void MotionCalculations()
        {
            if (UseCollision)
            {
                if (collisionOffsets == null)
                {
                    AddColliders();
                }
            }

            if (preAutoCorrect != UseAutoCorrectLookAxis)
            {
                ApplyAutoCorrection();
                preAutoCorrect = UseAutoCorrectLookAxis;
            }

            if (AnimateCorrections)
            {
                for (int i = 0; i < TailTransforms.Count; i++)
                {
                    animatedCorrections[i] = TailTransforms[i].localRotation;
                }
            }

            // 애니메이션 변수 계산하기
            float posDelta;
            float rotDelta;

            if (UpdateClock == EFUpdateClock.FixedUpdate)
            {
                posDelta = Time.fixedDeltaTime * PositionSpeed;
                rotDelta = Time.fixedDeltaTime * RotationSpeed;
            }
            else
            {
                if (SmoothDeltaTime)
                {
                    posDelta = Time.smoothDeltaTime * PositionSpeed;
                    rotDelta = Time.smoothDeltaTime * RotationSpeed;
                }
                else
                {
                    posDelta = Time.deltaTime * PositionSpeed;
                    rotDelta = Time.deltaTime * RotationSpeed;
                }
            }

            if (!RootToParent)
            {
                proceduralPoints[0].Position = TailTransforms[0].position;
            }
            else
            {
                // Supporting root parent motion
                FTail_Point currentTailPoint  = proceduralPoints[0];
                Vector3     startLookPosition = TailTransforms[0].parent.position;
                Vector3     translationVector;

                translationVector = TailTransforms[0].parent.TransformDirection(tailLookDirections[0]);

                Vector3 targetPosition = TailTransforms[0].parent.transform.position + (translationVector * -1f * (distances[0] * StretchMultiplier));

                FTail_Point temporaryPoint = new FTail_Point
                {
                    index    = 0,
                    Position = TailTransforms[0].parent.position,
                    Rotation = TailTransforms[0].parent.rotation
                };

                Quaternion targetLookRotation = CalculateTargetRotation(startLookPosition, currentTailPoint.Position, temporaryPoint, currentTailPoint, -1);

                proceduralPoints[0].Position = Vector3.Lerp(currentTailPoint.Position, targetPosition, posDelta);
                proceduralPoints[0].Rotation = Quaternion.Lerp(currentTailPoint.Rotation, targetLookRotation, rotDelta);
            }

            for (int i = 1; i < proceduralPoints.Count; i++)
            {
                FTail_Point previousTailPoint = proceduralPoints[i - 1];
                FTail_Point currentTailPoint  = proceduralPoints[i];

                Vector3 startLookPosition = previousTailPoint.Position;

                Vector3 translationVector;

                if (FullCorrection)
                {
                    translationVector = previousTailPoint.TransformDirection(tailLookDirections[i - 1]);
                }
                else
                {
                    translationVector = previousTailPoint.TransformDirection(AxisCorrection);
                }

                Vector3 targetPosition = previousTailPoint.Position + (translationVector * -1f * (distances[i] * StretchMultiplier));

                Quaternion targetLookRotation = CalculateTargetRotation(startLookPosition, currentTailPoint.Position, previousTailPoint, currentTailPoint, i - 1);

                proceduralPoints[i].Position = Vector3.Lerp(currentTailPoint.Position, targetPosition, posDelta);
                proceduralPoints[i].Rotation = Quaternion.Lerp(currentTailPoint.Rotation, targetLookRotation, rotDelta);

                if (UseCollision)
                {
                    if (collisionFlags[i] > 0f)
                    {
                        collisionFlags[i] -= Time.deltaTime * 4f;
                    }
                    else
                    {
                        collisionOffsets[i] = Vector3.zero;
                    }
                }
            }

            if (UseCollision)
            {
                for (int i = 1; i < collisionContacts.Count; i++)
                {
                    UseCollisionContact(i);
                }
            }
            //if (UseCollision) for (int i = collisionContacts.Count-1; i >= 1; i--) UseCollisionContact(i);
        }
        /// <summary>
        /// Adding sinus wave rotation with limiting option for first bone before other calculations
        /// </summary>
        public override void CalculateOffsets()
        {
            // Just calculating animation variables
            float delta;

            if (UpdateClock == EFUpdateClock.FixedUpdate)
            {
                delta = Time.fixedDeltaTime;
            }
            else
            {
                delta = Time.deltaTime;
            }

            if (UseWaving)
            {
                waveTime += delta * (2 * WavingSpeed);

                // It turned out to be problematic
                // When using clamp setting rotation was flipping other axes
                // So we push rotation in x axis (most common to this problem)
                if (UseXLimitation)
                {
                    Vector3 worldRotation     = TailTransforms[0].rotation.eulerAngles;
                    float   wrappedWorldAngle = LimitAngle360(worldRotation.x);

                    if (wrappedWorldAngle < WorldXDontGoUnder)
                    {
                        pushTimer = PushTime;
                    }

                    if (pushTimer > 0f)
                    {
                        TrueTailRotationOffset = Vector3.Lerp(TrueTailRotationOffset, Vector3.zero, delta * PushPower);
                        pushTimer -= delta;
                    }
                    else
                    {
                        TrueTailRotationOffset = Vector3.Lerp(TrueTailRotationOffset, TailRotationOffset, delta * PushPower * 0.7f);
                    }
                }

                Vector3 rot = firstBoneInitialRotation + TrueTailRotationOffset;

                float sinVal = Mathf.Sin(waveTime) * (30f * WavingRange);
                rot += sinVal * WavingAxis;

                if (rootTransform)
                {
                    proceduralPoints[0].Rotation = rootTransform.rotation * Quaternion.Euler(rot);
                }
                else
                {
                    proceduralPoints[0].Rotation = TailTransforms[0].transform.rotation * Quaternion.Euler(rot);
                }
            }
            else
            {
                if (rootTransform)
                {
                    proceduralPoints[0].Rotation = rootTransform.rotation * Quaternion.Euler(firstBoneInitialRotation);
                }
                else
                {
                    proceduralPoints[0].Rotation = TailTransforms[0].transform.rotation * Quaternion.Euler(firstBoneInitialRotation);
                }
            }

            if (preAutoCorrect != UseAutoCorrectLookAxis)
            {
                ApplyAutoCorrection();
                preAutoCorrect = UseAutoCorrectLookAxis;
            }

            proceduralPoints[0].Position = TailTransforms[0].position;

            // Just calculating animation variables
            float posDelta;
            float rotDelta;

            if (UpdateClock == EFUpdateClock.FixedUpdate)
            {
                posDelta = Time.fixedDeltaTime * PositionSpeed;
                rotDelta = Time.fixedDeltaTime * RotationSpeed;
            }
            else
            {
                posDelta = Time.deltaTime * PositionSpeed;
                rotDelta = Time.deltaTime * RotationSpeed;
            }

            for (int i = 1; i < proceduralPoints.Count; i++)
            {
                FTail_Point previousTailPoint = proceduralPoints[i - 1];
                FTail_Point currentTailPoint  = proceduralPoints[i];

                Vector3 startLookPosition = previousTailPoint.Position;

                Vector3 translationVector;

                if (FullCorrection)
                {
                    translationVector = previousTailPoint.TransformDirection(tailLookDirections[i - 1]);
                }
                else
                {
                    translationVector = previousTailPoint.TransformDirection(AxisCorrection);
                }

                Vector3 targetPosition = previousTailPoint.Position + (translationVector * -1f * (distances[i] * StretchMultiplier));
                proceduralPoints[i].Position = Vector3.Lerp(currentTailPoint.Position, targetPosition, posDelta);

                Quaternion targetLookRotation = CalculateTargetRotation(startLookPosition, currentTailPoint.Position, previousTailPoint, currentTailPoint, i - 1);
                proceduralPoints[i].Rotation = Quaternion.Lerp(currentTailPoint.Rotation, targetLookRotation, rotDelta);
            }

            SetTailTransformsFromPoints();
        }
예제 #6
0
 protected override Quaternion CalculateTargetRotation(Vector3 startLookPos, Vector3 currentPos, FTail_Point previousTailPoint = null, FTail_Point currentTailPoint = null, int lookDirectionFixIndex = 0)
 {
     if (Lock2D)
     {
         return(FLogicMethods.TopDownAnglePosition2D(startLookPos, currentPos));
     }
     else
     {
         return(base.CalculateTargetRotation(startLookPos, currentPos, previousTailPoint, currentTailPoint, lookDirectionFixIndex));
     }
 }
예제 #7
0
        protected Quaternion CalculateFor2D(FTail_Point tailPoint)
        {
            Quaternion targetRotation;

            if (FullCorrection)
            {
                Vector3 startLookPos = tailPoint.BackPoint.Position;
                Vector3 lookingAt    = tailPoint.RotationTargetPos;

                targetRotation = Quaternion.identity;

                if (LookUpMethod != FELookUpMethod.Parental)
                {
                    startLookPos += tailPoint.BackPoint.TransformDirection(tailPoint.BackPoint.LookDirection) * tailPoint.InitBoneLength * tailPoint.ScaleFactor * sensitivityPower;
                    startLookPos -= (tailPoint.BackPoint.PreCollisionPosition - tailPoint.BackPoint.Position) * CollisionSwapping;

                    if (startLookPos - lookingAt != Vector3.zero)
                    {
                        targetRotation = FLogicMethods.TopDownAnglePosition2D(lookingAt, startLookPos);
                    }

                    targetRotation *= Quaternion.FromToRotation(tailPoint.BackPoint.LookDirection, ExtraToDirection);
                }
                else // Parental method
                {
                    startLookPos += tailPoint.BackPoint.TransformDirection(tailPoint.BackPoint.LookDirection) * tailPoint.InitBoneLength * tailPoint.ScaleFactor * sensitivityPower;

                    Vector3 targetPos = lookingAt - startLookPos;

                    Quaternion targetingRot = Quaternion.FromToRotation(tailPoint.BackPoint.TransformDirection(tailPoint.Transform.localPosition), targetPos);

                    targetRotation = targetingRot * tailPoint.BackPoint.Rotation;
                }

                if (Curving != Vector3.zero)
                {
                    float mul = 10 / ((float)tailPoint.index * 4.5f + 1f);
                    targetRotation *= Quaternion.Euler(Curving.y * mul, Curving.x * mul, 0f);
                }

                targetRotation *= tailPoint.Correction;
            }
            else
            {
                targetRotation = Quaternion.identity;
                Vector3 startLookPos = tailPoint.BackPoint.Position;
                Vector3 lookingAt    = tailPoint.RotationTargetPos;

                startLookPos += tailPoint.BackPoint.TransformDirection(tailPoint.BackPoint.LookDirection) * tailPoint.InitBoneLength * sensitivityPower;
                startLookPos -= (tailPoint.BackPoint.PreCollisionPosition - tailPoint.BackPoint.Position) * CollisionSwapping;

                if (startLookPos - lookingAt != Vector3.zero)
                {
                    targetRotation = FLogicMethods.TopDownAnglePosition2D(startLookPos, lookingAt);
                }
                //targetRotation = Quaternion.LookRotation(startLookPos - lookingAt, tailPoint.BackPoint.TransformDirection(AxisLookBack * Mathf.Sign(FVectorMethods.VectorSum(AxisCorrection))));

                if (Curving != Vector3.zero)
                {
                    float mul = 10f / ((float)tailPoint.index * 4.5f + 1f);
                    targetRotation *= Quaternion.Euler(Curving.y * mul, Curving.x * mul, 0f);
                }

                if (ExtraCorrectionOptions)
                {
                    targetRotation *= Quaternion.FromToRotation(ExtraFromDirection, ExtraToDirection);
                }
            }

            return(targetRotation);
        }