c# - 最后用缓动来回摇动一个物体?

标签 c# unity3d

我几乎想要一个不和谐的动画,这样它会快速来回摇晃一秒钟,然后减慢速度,回到正常位置。只是继续摇晃有很多答案,但我怎样才能减少摇晃呢?我会 Lerp 真的很快,还是使用带有减慢功能的 PingPong

最佳答案

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

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

下面的函数是上述语句的完整示例。它需要三个参数,要摇动的游戏对象、摇动游戏对象的时间以及开始减少摇动的时间。

比如你传入myGameOBject,5f,3f给函数,它会摇动myGameOBject 总时间为 5 秒。在摇动 myGameOBject 并且计数器达到 3 时,它将开始降低摇动的速度(shakeAmount),直到计时器达到 5

如果要摇动的游戏对象是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);
}

关于c# - 最后用缓动来回摇动一个物体?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39380901/

相关文章:

c# - (Unity) 如何防止 MonoBehavior Awake() 函数在 child 中被覆盖

c# - 如何在 Unity AndroidJavaClass 中访问枚举

c# - 不一致的行为 : no exception is thrown in the List<T>. 在 foreach 循环中调用时的排序方法

c# - 如何避免 web.config 中的 session 超时

c# - 在 gridview 行命令中获取 BoundField 值

swift - 3D 模型看起来与 ARKit 中的大小不一样

Android 9 Pie 崩溃(com.google.android.gms ... ClassNotFoundException)

c# - 使用 mySQL 将 int 列表传递给 dapper

c# - MVC3 布局 - 重复部分

c# - 使用自定义检查器扩展 Unity UI 组件