前后摇动一个物体,最后轻轻摇动

本文关键字:最后 一个 轻轻 | 更新日期: 2023-09-27 18:06:18

我几乎想要一个不和谐的动画,这样它就会快速地来回摇晃一秒钟,然后减速,放松到正常位置。对于持续震动有很多答案,但我该如何减少震动呢?我将Lerp非常快,或使用PingPong的功能减慢?

前后摇动一个物体,最后轻轻摇动

你可以简单地通过在协程函数中获得原始位置来震动GameObject,然后在一定时间内循环执行YourObjTransform.position = defaultPos + UnityEngine.Random.insideUnitSphere * shakeAmount;。摇动游戏对象后,将值重置回其默认位置。

为了减少抖动,您可以在while循环中执行shakeAmount += Time.deltaTime;。这将降低while循环中的震动速度。

下面的函数是上述语句的完整示例。它需要三个参数,震动GameObject,震动GameObject多长时间,以及何时开始减少震动。

例如,如果你将myGameOBject, 5f, 3f传递给函数,它将震动myGameOBject总共5秒。当摇myGameOBject时,计数器到达3,它将开始降低摇的速度(shakeAmount),直到计时器到达5

如果要震动的GameObject是SpriteRender,则将true传递到最后一个参数,这样z轴不会移动,它只会在震动时在z轴上旋转。

public GameObject GameObjectToShake;
bool shaking = false;
IEnumerator shakeGameObjectCOR(GameObject objectToShake, float totalShakeDuration, float decreasePoint, bool objectIs2D = false)
{
    if (decreasePoint >= totalShakeDuration)
    {
        Debug.LogError("decreasePoint must be less than totalShakeDuration...Exiting");
        yield break; //Exit!
    }
    //Get Original Pos and rot
    Transform objTransform = objectToShake.transform;
    Vector3 defaultPos = objTransform.position;
    Quaternion defaultRot = objTransform.rotation;
    float counter = 0f;
    //Shake Speed
    const float speed = 0.1f;
    //Angle Rotation(Optional)
    const float angleRot = 4;
    //Do the actual shaking
    while (counter < totalShakeDuration)
    {
        counter += Time.deltaTime;
        float decreaseSpeed = speed;
        float decreaseAngle = angleRot;
        //Shake GameObject
        if (objectIs2D)
        {
            //Don't Translate the Z Axis if 2D Object
            Vector3 tempPos = defaultPos + UnityEngine.Random.insideUnitSphere * decreaseSpeed;
            tempPos.z = defaultPos.z;
            objTransform.position = tempPos;
            //Only Rotate the Z axis if 2D
            objTransform.rotation = defaultRot * Quaternion.AngleAxis(UnityEngine.Random.Range(-angleRot, angleRot), new Vector3(0f, 0f, 1f));
        }
        else
        {
            objTransform.position = defaultPos + UnityEngine.Random.insideUnitSphere * decreaseSpeed;
            objTransform.rotation = defaultRot * Quaternion.AngleAxis(UnityEngine.Random.Range(-angleRot, angleRot), new Vector3(1f, 1f, 1f));
        }
        yield return null;

        //Check if we have reached the decreasePoint then start decreasing  decreaseSpeed value
        if (counter >= decreasePoint)
        {
            Debug.Log("Decreasing shake");
            //Reset counter to 0 
            counter = 0f;
            while (counter <= decreasePoint)
            {
                counter += Time.deltaTime;
                decreaseSpeed = Mathf.Lerp(speed, 0, counter / decreasePoint);
                decreaseAngle = Mathf.Lerp(angleRot, 0, counter / decreasePoint);
                Debug.Log("Decrease Value: " + decreaseSpeed);
                //Shake GameObject
                if (objectIs2D)
                {
                    //Don't Translate the Z Axis if 2D Object
                    Vector3 tempPos = defaultPos + UnityEngine.Random.insideUnitSphere * decreaseSpeed;
                    tempPos.z = defaultPos.z;
                    objTransform.position = tempPos;
                    //Only Rotate the Z axis if 2D
                    objTransform.rotation = defaultRot * Quaternion.AngleAxis(UnityEngine.Random.Range(-decreaseAngle, decreaseAngle), new Vector3(0f, 0f, 1f));
                }
                else
                {
                    objTransform.position = defaultPos + UnityEngine.Random.insideUnitSphere * decreaseSpeed;
                    objTransform.rotation = defaultRot * Quaternion.AngleAxis(UnityEngine.Random.Range(-decreaseAngle, decreaseAngle), new Vector3(1f, 1f, 1f));
                }
                yield return null;
            }
            //Break from the outer loop
            break;
        }
    }
    objTransform.position = defaultPos; //Reset to original postion
    objTransform.rotation = defaultRot;//Reset to original rotation
    shaking = false; //So that we can call this function next time
    Debug.Log("Done!");
}

void shakeGameObject(GameObject objectToShake, float shakeDuration, float decreasePoint, bool objectIs2D = false)
{
    if (shaking)
    {
        return;
    }
    shaking = true;
    StartCoroutine(shakeGameObjectCOR(objectToShake, shakeDuration, decreasePoint, objectIs2D));
}
void Start()
{
    shakeGameObject(GameObjectToShake, 5, 3f, false);
}