前后摇动一个物体,最后轻轻摇动
本文关键字:最后 一个 轻轻 | 更新日期: 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);
}