Search Unity

Question How to bounce between 2 numbers forever

Discussion in 'Scripting' started by TimedMercury64, Mar 21, 2023.

  1. TimedMercury64

    TimedMercury64

    Joined:
    Feb 1, 2022
    Posts:
    17
    so i want the blend to bounce from 0 to 1 forever, how do i do that?
    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using Unity.VisualScripting;
    5. using UnityEngine;
    6.  
    7. public class SkyChanger : MonoBehaviour
    8. {
    9.     SkyboxBlender skyboxBlender;
    10.     [SerializeField] GameObject TimeController;
    11.  
    12.     void Awake()
    13.     {
    14.         skyboxBlender = TimeController.GetComponent<SkyboxBlender>();
    15.     }
    16.  
    17.     // Start is called before the first frame update
    18.     void Start()
    19.     {
    20.         skyboxBlender.blend = 0;
    21.     }
    22.  
    23.     // Update is called once per frame
    24.     void Update()
    25.     {
    26.         //skyboxBlender.blend = Mathf.PingPong(Time.time, 8);
    27.     }
    28. }
     
  2. mopthrow

    mopthrow

    Joined:
    May 8, 2020
    Posts:
    348
  3. TimedMercury64

    TimedMercury64

    Joined:
    Feb 1, 2022
    Posts:
    17
    ok i changed it to 1 and it works but it go's to 8 and comes back to 1, also do you know how to make it go slower?
     
  4. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,006
    Sure, just divide / mutiply Time.time by whatever factor you want it to be slower / faster. So
    Code (CSharp):
    1. Mathf.PingPong(Time.time * 0.5f, 1);
    2. // or
    3. Mathf.PingPong(Time.time / 2f, 1);
    would make it twice as slow.
     
  5. TimedMercury64

    TimedMercury64

    Joined:
    Feb 1, 2022
    Posts:
    17
    Ok one more thing do you know how to pause it for a certain amount of time at like halfway through?
     
  6. owrtho

    owrtho

    Joined:
    Sep 19, 2022
    Posts:
    5
    While a variety of methods could be used, they generally can boil down to either adjusting the time value that you input into pingpong, or adjusting the result (or theoretically a combination of the two).

    The thing to note is how PingPong actually works with its inputs, which are a float value 't' (where you are putting Time.time) and a float value 'length' (where you are putting 1). For the range t = 0 to t = length, PingPong will directly output the value of t. Meanwhile for the range of t = length to t = 2 * length, PingPong will output a value equal to 2 * length - t. This pattern of outputs will repeat, meaning you could replace t in the above outputs with "t % (2 * length)" (in case you are unfamiliar with the operator, % in this context means remainder, so for instance "5.5f % 2f" would give a value of 1.5f). A simple custom function to mimic Mathf.PingPong's functionality would be:
    Code (CSharp):
    1. float PingPong(float t, float length)
    2. {
    3.     t = t % (2 * length)
    4.     if(t < length)
    5.     {
    6.         return t;
    7.     }
    8.     return 2 * length - t;
    9. }
    Note that this is likely not the actual code used by the function, but it would result in the same outputs.

    Anyway, knowing what kind of output to expect from a given input means you could manipulate the t that you are putting in. Rather than directly inputting Time.time, you could make a variable that is updated regularly and paused as needed. While there are many ways to go about this, an example method would be to do something like:
    Code (CSharp):
    1. private float loopTime = 0f;
    2. private float pauseTime = 0f;
    3.  
    4. private float getLoopTime(float time, float loopDuration, float pauseDuration, float pauseWhen)
    5. {
    6.     // time is the value being adjusted.
    7.     // loopDuration is the total length of time you want the loop to last, including the pauses.
    8.     // pauseDuration is how long you want the pause to last.
    9.     // pauseWhen is what value (between 0 and 1) that you want the looping to pause at.
    10.         // This will happen twice per loop unless the value is 0 or 1 in which case it will happen once.
    11.  
    12.     float timeAdjustment = Time.deltaTime;
    13.  
    14.     if(pauseTime > 0f)
    15.     {
    16.         pauseTime -= timeAdjustment;
    17.         if(pauseTime <= 0f)
    18.         {
    19.             timeAdjustment = -pauseTime;    // This is so that if there's time left over from finishing the pause, it's properly applied.
    20.         }
    21.         else
    22.         {
    23.             timeAdjustment = 0f;
    24.         }
    25.     }
    26.  
    27.     if(timeAdjustment > 0f)
    28.     {
    29.         // Determine how many pauses will occur within a loop and thus how to adjust the time.
    30.         int pauseCount = (pauseWhen == 0f || pauseWhen == 1f) ? 1 : (pauseWhen > 0f && pauseWhen < 1f) ? 2 : 0;
    31.         float timeModifier = 2 / (loopDuration - (pauseCount * pauseDuration));
    32.         // This will adjust the speed at which the looping occurs to ensure it at the desired rate.
    33.         timeAdjustment = timeModifier * timeAdjustment
    34.  
    35.         bool beforePause = false;
    36.  
    37.         if((time < 1f && time < pauseWhen) || (time > 1f && time < 2f - pauseWhen))
    38.         {
    39.             beforePause = true;
    40.         }
    41.  
    42.         time += timeAdjustment;
    43.  
    44.         if(beforePause && ((time - timeAdjustment < 1f && time >= pauseWhen) || (time >= 2f - pauseWhen)))
    45.         {
    46.             pauseTime = pauseDuration;    // This will set the pause duration when at the correct points in the loop.
    47.  
    48.             // Ensure that time beyond the amount needed to reach the pause point is subtracted from pause duration.
    49.             if(time < 2f - pauseWhen)
    50.             {
    51.                 pauseTime -= (time - pauseWhen) / timeModifier;
    52.                 time = pauseWhen;
    53.             }
    54.             else
    55.             {
    56.                 pauseTime -= (time - (2f - pauseWhen) / timeModifier;
    57.                 time = 2f - pauseWhen;
    58.             }
    59.         }
    60.  
    61.         time = time % 2f;    // Keep time between 0f and 2f.
    62.     }
    63.  
    64.     return time;
    65. }
    66.  
    67. private void Update()
    68. {
    69.     loopTime = getLoopTime(loopTime, 8f, 1f, 0.5f);
    70.     skyboxBlender.blend = Mathf.PingPong(loopTime, 1f);
    71. }
    So, this should result in blend going back and fourth from 0 to 1 in a loop that takes 8 seconds to get from 0 back to 0, pausing at 0.5 for 1 second each way.

    If you wanted to instead handle things by adjusting the output, it could be done with something like this.
    Code (CSharp):
    1.  
    2. private float getLoopTime(float loopDuration, float pauseDuration, float pauseWhen)
    3. {
    4.     // loopDuration is the total length of time you want the loop to last, including the pauses.
    5.     // pauseDuration is how long you want the pause to last.
    6.     // pauseWhen is what value (between 0 and 1) that you want the looping to pause at.
    7.         // This will happen twice per loop unless the value is 0 or 1 in which case it will happen once.
    8.  
    9.     // Determine how many pauses will occur within a loop and thus how to adjust the time.
    10.     float pauseCount = (pauseWhen == 0f || pauseWhen == 1f) ? 0.5 : (pauseWhen > 0f && pauseWhen < 1f) ? 1f : 0f;
    11.  
    12.     float resultAdjustment = loopDuration / 2f;
    13.     float result = Mathf.PingPong(Time.time, resultAdjustment);
    14.  
    15.     resultAdjustment -= pauseDuration * pauseCount;
    16.  
    17.     if(pauseWhen == 0f)
    18.     {
    19.         if(result < pauseDuration / 2f)
    20.         {
    21.             return 0f;
    22.         }
    23.         result -= (pauseDuration / 2f)
    24.         return result / resultAdjustment;
    25.     }
    26.     else if(pauseWhen == 1f)
    27.     {
    28.         if(result > resultAdjustment)
    29.         {
    30.             return 1f;
    31.         }
    32.         return result / resultAdjustment;
    33.     }
    34.  
    35.     if(result < pauseWhen * resultAdjustment)
    36.     {
    37.         return result / resultAdjustment;
    38.     }
    39.     else if(result < (loopDuration / 2f) - (pauseWhen * resultAdjustment))
    40.     {
    41.         return pauseWhen;
    42.     }
    43.     return (result - pauseDuration) / resultAdjustment
    44. }
    45.  
    46. private void Update()
    47. {
    48.     skyboxBlender.blend = getLoopTime(8f, 1f, 0.5f);
    49. }
    In either case the code could be better optimized, particularly if you know what value you want it to pause at. Adjustments would also be needed if you want to have it pause at multiple points.

    Hope this helps.

    owrtho
     
    Bunny83 likes this.
  7. TimedMercury64

    TimedMercury64

    Joined:
    Feb 1, 2022
    Posts:
    17
    Thank you to all of you I finally got what I wanted