Search Unity

Function execution is too fast

Discussion in 'Scripting' started by Fudegracoon, Sep 24, 2020.

  1. Fudegracoon

    Fudegracoon

    Joined:
    May 28, 2020
    Posts:
    13
    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

    Code (CSharp):
    1. public static IEnumerator CameraShake(Camera sceneCamera, float duration, float magnitude)
    2.         {
    3.             float counter = 0.0f;
    4.             float x = UnityEngine.Random.Range(-1f, 1f) * magnitude;
    5.             float y = UnityEngine.Random.Range(-1f, 1f) * magnitude;
    6.             Vector3 originalPos = sceneCamera.transform.position;
    7.             Vector3 shakePos = new Vector3(x, y, 0);
    8.  
    9.             while(counter <= duration)
    10.             {
    11.                 sceneCamera.transform.position += shakePos;
    12.                 counter += Time.deltaTime;
    13.                 yield return null;
    14.             }
    15.  
    16.             sceneCamera.transform.position = originalPos;
    17.         }  
    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

    Code (CSharp):
    1. public static IEnumerator Squeeze(Transform @gameObject)
    2.         {
    3.             float counter = 0.0f;
    4.             Vector3 originalSize = gameObject.localScale;
    5.             Vector3 squeezeSize = new Vector3(1.5f, 0.5f, gameObject.localScale.z);
    6.  
    7.             //Linearly interpolate from original scale to the new scale by incrementing the counter
    8.             while(counter <= 1)
    9.             {
    10.                 counter += 0.01f;
    11.                 gameObject.localScale = Vector3.Lerp(originalSize, squeezeSize, counter);
    12.                 yield return null;
    13.             }
    14.            
    15.             //Reset counter
    16.             counter = 0.0f;
    17.            
    18.             //Return to the original scale by reversing the interpolation
    19.             while(counter <= 1)
    20.             {
    21.                 counter += 0.01f;
    22.                 gameObject.localScale = Vector3.Lerp(squeezeSize, originalSize, counter);
    23.                 yield return null;
    24.             }
    25.         }
     
  2. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    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.
     
    PraetorBlue likes this.
  3. Fudegracoon

    Fudegracoon

    Joined:
    May 28, 2020
    Posts:
    13
    What do you mean by a fixed multiplier, can you elaborate more please?
     
  4. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    If
    Code (CSharp):
    1. someValue * Time.deltaTime
    is to low a value, just add some multiplier
    Code (CSharp):
    1. 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.
     
    PraetorBlue likes this.
  5. Fudegracoon

    Fudegracoon

    Joined:
    May 28, 2020
    Posts:
    13
    Okay, thanks for the help. I'll try it out now.
     
  6. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    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:

    Code (csharp):
    1.  
    2. public static IEnumerator CameraShake(Camera sceneCamera, float duration, float magnitude)
    3.         {
    4.             float counter = 0.0f;
    5.             Vector3 originalPos = sceneCamera.transform.position;
    6.  
    7.             while(counter <= duration)
    8.             {
    9.                 // change 1, grab a random value each frame
    10.                 float x = UnityEngine.Random.Range(-1f, 1f) * magnitude;
    11.                 float y = UnityEngine.Random.Range(-1f, 1f) * magnitude;
    12.                 Vector3 shakePos = new Vector3(x, y, 0);
    13.  
    14.                 // change 2, shake around the origin instead of moving in a direction
    15.                 sceneCamera.transform.position = originalPos + shakePos;
    16.                 counter += Time.deltaTime;
    17.                 yield return null;
    18.             }
    19.  
    20.             sceneCamera.transform.position = originalPos;
    21.         }
    22.  
    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.