I wrote a couple of scripts for my 2D fighting game and I’m having a couple of issues I can’t wrap my head around. Firstly, I wrote a Camera Shake function and I increment the counter using time.deltatime but it’s so fast, I also tried the same function on another computer with the same parameters it ran differently and in the way I wanted it too, here is the code
Secondly, I wrote a squeeze function which essentially lerps the scale of a gameobject to a new scale to give the illusion of squeezing, again same issue but when I use time.deltatime it’s too slow so I had to hardcode values to increment the counter and again it behaves differently on my other pc, here is the code
public static IEnumerator Squeeze(Transform @gameObject)
{
float counter = 0.0f;
Vector3 originalSize = gameObject.localScale;
Vector3 squeezeSize = new Vector3(1.5f, 0.5f, gameObject.localScale.z);
//Linearly interpolate from original scale to the new scale by incrementing the counter
while(counter <= 1)
{
counter += 0.01f;
gameObject.localScale = Vector3.Lerp(originalSize, squeezeSize, counter);
yield return null;
}
//Reset counter
counter = 0.0f;
//Return to the original scale by reversing the interpolation
while(counter <= 1)
{
counter += 0.01f;
gameObject.localScale = Vector3.Lerp(squeezeSize, originalSize, counter);
yield return null;
}
}
Use Time.deltaTime. If it’s “too slow”, make it faster by a fixed multiplier you can choose. Dont just hardcode values. That’s bound to run different on every PC due to different framerates.
If someValue * Time.deltaTime
is to low a value, just add some multiplier
someValue * Time.deltaTime * valueMultiplier
where valueMultiplier > 1 or < 1 can be used to artificially scale the result value in whatever way you want.
Currently you simply add a flat value, like 0.01, per cycle. Which happens once a frame due to yield. So with 300 FPS that’s a different value (per second) than with just 60 FPS, which you generally do not want. This is why we multiply with Time.deltaTime, to scale calculations over the framerate, making the same effect happen over one second no matter the framerate.
Without using Time.deltaTime, you can not guarantee the same behavior on different framerates.
The problem is that you calculate the random position once, and then set that position a bunch of times in the while-loop.
You’re also moving the camera directly in a direction instead of shaking it.
So you want to change to this:
public static IEnumerator CameraShake(Camera sceneCamera, float duration, float magnitude)
{
float counter = 0.0f;
Vector3 originalPos = sceneCamera.transform.position;
while(counter <= duration)
{
// change 1, grab a random value each frame
float x = UnityEngine.Random.Range(-1f, 1f) * magnitude;
float y = UnityEngine.Random.Range(-1f, 1f) * magnitude;
Vector3 shakePos = new Vector3(x, y, 0);
// change 2, shake around the origin instead of moving in a direction
sceneCamera.transform.position = originalPos + shakePos;
counter += Time.deltaTime;
yield return null;
}
sceneCamera.transform.position = originalPos;
}
That’ll probably be too erratic - you probably want to update the camera position once every .1 seconds or something instead of each frame, but you’ve got to fix the code just being straight up wrong first.