Search code examples
c#unity-game-engineienumerator

How to keep current multiplier after multiplying your current multiplier by two for 30 seconds with a coroutine


As the title says I would like to give my player a temporary 2x multiplier and then take it away after. So far I have a button they click that sets their current multiplier x2 and then after 10 seconds take it away, the issue is if they buy an increase to their multiplier during that time it messes things up and I am not sure how to handle it. GameManager.The multiplier is set to 1 at the start of the game and can be added to by purchasing an "upgrade".

Edit: I have two scripts one that keeps track of how much Iron you have and What your current click multiplier is it also handles displaying both to the screen with text it's called GameManager.

My game has 3 buttons one takes 10 Iron and gives the player plus 1 to their click multiplier the other 2 do the same thing, but requires more Iron and gives a higher bump to the click multiplier.

I then added a 4th button that when pressed will give the player a 2x to their multiplier for 30 sec (ex current click multiplier is 5 after button press it is now 10 after 30 sec it returns to 5)

The issue is that if the player clicks the 2x button and then buys a 1x click multiplier upgrade they do not keep the one they purchased during the 2x button coroutine. (ex current click multiplier is 1 click the 2x button click multiplier is now 2 then buy a 1x upgrade so the click multiplier is now 3. After the 30 sec the multiplier should return to 2 but instead returns to 1 as if they never purchased the 1x upgrade)

Hopefully, this is a bit better at explaining my issue. I tried adding a temp var of my original multiplier and then using mathf.ABS to figure out the difference and then do something with that, but it's honestly starting to confuse the crap out of me so I'm asking here for advice lol My code for it so far is:

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class TwoX: MonoBehaviour
{
    [SerializeField] Button _TwoX;

void Start () {
        Button btn = TwoX.GetComponent<Button>();
        btn.onClick.AddListener(TaskOnClick);
    }

    void TaskOnClick(){
        StartCoroutine(test());
    }

   IEnumerator test()
    {
        GameManager.Multiplier = GameManager.Multiplier * 2;
        yield return new WaitForSeconds(10);
        GameManager.Multiplier = GameManager.Multiplier / 2;
    }

}

Solution

  • From your descriptions it sounds like GameManager.Multiplier is an int so the steps are indeed

    • initial value 1
    • * 2 => 2
    • + 1 => 3
    • / 2 => 1

    since int division doesn't know about decimals (if it was a float the result would be 1.5f).


    The trick I would use would be to not use * and / at all but rather + and -:

    private bool alreadyDoubled;
    
    IEnumerator test()
    {
        // avoid hat the routine is running multiple times if your player spams the button
        if(alreadyDoubled) yield break;
    
        // block other instances of this routine
        alreadyDoubled = true;
    
        // cache the original value!
        // the advantage of a Coroutine here is that you can simply keep
        // along a value within this Coroutines scope
        var addition = GameManager.Multiplier;
    
        // This basically equals doing * 2
        GameManager.Multiplier += addition; 
    
        yield return new WaitForSeconds(10);
    
        // This only removes the addition, regardless of what happened to the value in the meantime
        GameManager.Multiplier -= addition; 
    
        // allow the next instance of this routine to start
        alreaeyDoubled = false;
    }
    

    This time the steps will rather be

    • initial value 1
    • "* 2" -> actually + 1 -> 2
    • + 1 => 3
    • "/ 2" -> actually - 1 -> 2