Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
966 views
in Technique[技术] by (71.8m points)

c# - Shake an object back and forth with easing at the end?

I almost want a jarring animation, such that it shakes back and forth rapidly for a second, and then slows back down, easing back into its normal position. There are tons of answers for just continues shaking, but how would I decrease the shake? Would I Lerp really fast, or use PingPong with a function that slows?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You simply can simply shake a GameObject with by getting the original position then in a coroutine function, do YourObjTransform.position = defaultPos + UnityEngine.Random.insideUnitSphere * shakeAmount; in a while loop for a certain time. After shaking the GameObject, reset the value back to its default position.

As for decreasing the shake, you do shakeAmount += Time.deltaTime; in the while loop. This will decrease the shake speed in the while loop.

The function below is a complete example of the above statement. It takes three parameters, the GameObject to shake, how long to shake the GameObject and what time to start decreasing the shake.

For example,if you pass in myGameOBject, 5f, 3f to the function, it will shake the myGameOBject for a total time of 5 seconds. While shaking the myGameOBject and the counter reaches 3, it will start to decrease the speed(shakeAmount) of the shake until timer reaches 5.

Pass true to the last parameter if the GameObject to shake is a SpriteRender so that the z axis won't move and it will only rotate in Z axis when shaking.

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);
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...