0

I'm trying to make my Unity mobile game Difficulty options button selections (Easy/Medium/Hard) function to change the spawn rate for enemy ai. For example, clicking on Medium should trigger spawn 2x as much ai across all levels/scenes.

I have the buttons working according to Console but the difficulty Button script is not communicating with the Spawn script properly since selecting a difficulty level is not influencing spawn rate.

Does anyone see what I'm missing? Have spent lots of time on this but no luck.

Difficulty Button Script:

public class DifficultyButton : MonoBehaviour
{
    private Button button;

    private RandomSpawn randomSpawn;
    
    public int difficulty;

    
    
    // Start is called before the first frame update
    void Start()
    {
        button = GetComponent<Button>(); 
        button.onClick.AddListener(SetDifficulty); 
        randomSpawn = GameObject.Find("Random Spawn").GetComponent<RandomSpawn>(); 
    }

    //click on diff buttons n Console will show they were clicked
    void SetDifficulty() 
    {
        Debug.Log(gameObject.name + " was clicked");
        
    }
}

Spawn Script:

public class RandomSpawn : MonoBehaviour
{
   
    public GameObject prefab1, prefab2, prefab3, prefab4;
   
    public float spawnRate = 2f;
   
    private float nextSpawn = 0f;
   
    private int whatToSpawn;
   
 
    public bool isGameActive;
    public void StartGame(int difficulty)
    {
        isGameActive = true;
        spawnRate /= difficulty;
    }
 
    void Update()
    {
        if (Time.time > nextSpawn) { //if time has come
            whatToSpawn = Random.Range(1, 6); // define random value between 1 and 4 (5 is exclusive)
            Debug.Log(whatToSpawn); //display its value in console
           
           
            switch (whatToSpawn) {
                case 1:
                    Instantiate(prefab1, transform.position, Quaternion.identity);
                    break;
                case 2:
                    Instantiate(prefab2, transform.position, Quaternion.identity);
                    break;
                case 3:
                    Instantiate(prefab3, transform.position, Quaternion.identity);
                    break;
                case 4:
                    Instantiate(prefab4, transform.position, Quaternion.identity);
                    break;
               
            }
         
            nextSpawn = Time.time + spawnRate;
        }
    }
}

Here's a pic of my difficulty button setup on Hard in the Inspector

enter image description here

derHugo
  • 83,094
  • 9
  • 75
  • 115
xaltx
  • 15
  • 4
  • I might be missing it, but where are you setting the difficulty? From the onClick delegate function you are just printing the message, not incrementing anything related to difficulty neither locally nor in the RandomSpawn script. You need to pass the difficulty clicked to the other script. – TEEBQNE Apr 08 '21 at 04:43
  • @TEEBQNE, thx for the speedy reply! I'm setting Difficulty in the Inspector. The Difficulty Button script triggers a Difficulty field, which I'm putting as 1 for easy, 2 for medium & 3 for hard. This is "supposed to" link up to the Spawn Script line that calls spawnRate /= diffculty so that, for example, a Medium difficulty selection triggers spawn every .5 seconds whereas Hard would be every.33 sec. Right now seems like I'm missing something to get these scripts to communicate w/one another – xaltx Apr 08 '21 at 04:58
  • When you say difficulty field do you mean the `public int difficulty` in your script? – TEEBQNE Apr 08 '21 at 05:09
  • @TEEBQNE, yes that's right. – xaltx Apr 08 '21 at 05:28

1 Answers1

0

I assume your issue is that the buttons are linked to your onClick, but then the onClick is not doing anything. As far as I can tell, the onClick you are setting up just has the Debug.Log, so I will try to help fix that.

public class DifficultyButton : MonoBehaviour
{
private Button button;

private RandomSpawn randomSpawn;

public int difficulty;



// Start is called before the first frame update
void Start()
{
    button = GetComponent<Button>(); 
    randomSpawn = GameObject.Find("Random Spawn").GetComponent<RandomSpawn>();
    button.onClick.AddListener(delegate{randomSpawn.UpdateSpawnRate(difficulty);});  
}
}

Random Spawn Class

public class RandomSpawn : MonoBehaviour
{

public GameObject prefab1, prefab2, prefab3, prefab4;

public float maxSpawnRate = 2f;

private float nextSpawn = 0f;

private int whatToSpawn;
private float spawnRate = 2f;


public bool isGameActive;
public void StartGame(int difficulty)
{
    isGameActive = true;
    UpdateSpawnRate(difficulty);
}

void Update()
{
    if (Time.time > nextSpawn) { //if time has come
        whatToSpawn = Random.Range(1, 6); // define random value between 1 and 4 (5 is exclusive)
        Debug.Log(whatToSpawn); //display its value in console
       
       
        switch (whatToSpawn) {
            case 1:
                Instantiate(prefab1, transform.position, Quaternion.identity);
                break;
            case 2:
                Instantiate(prefab2, transform.position, Quaternion.identity);
                break;
            case 3:
                Instantiate(prefab3, transform.position, Quaternion.identity);
                break;
            case 4:
                Instantiate(prefab4, transform.position, Quaternion.identity);
                break;
           
        }
     
        nextSpawn = Time.time + spawnRate;
    }
}

public void UpdateSpawnRate(int difficulty)
{
    spawnRate = maxSpawnRate / difficulty;
}
}

I am not sure if your buttons appear before the game, then you select the difficulty then click another button which calls StartGame(). Either way what I am doing now is directly setting your button onClick of the difficulty buttons to the delegate function UpdateSpawnRate() which will update your current spawnRate. I also changed the public variable of spawnRate to maxSpawnRate in case you change the difficulty multiple times or play multiple rounds. Having the max allows the now temporary spawnRate to relatively change based on the maxSpawnRate and difficulty variable.

Let me know if this code works, I type of solutions as a general direction to follow, not the exact answer. If you need more guidance on how to implement it or something in the code does not work, let me know in the comments.

TEEBQNE
  • 6,104
  • 3
  • 20
  • 37
  • Thx again for the great input! Everything looks good except the last line of the Button script: button.onClick.AddListener(randomSpawn.UpdateSpawnRate(difficulty)); --this call is triggering in my script editor, the error " argument type void is not assignable to parameter type unityengine.events.unityction – xaltx Apr 08 '21 at 05:47
  • @xaltx Sorry forgot that it needs to be wrapped in delegate{} try the updated code – TEEBQNE Apr 08 '21 at 06:05
  • FYI I actually don't need the StartGame call---maybe keeping it is causing an issue. I had thought to have the Diff buttons trigger game start but now use a different button with a totally different script for that so the StartGame reference is leftover. Like you deduced in your last comment, buttons appear in Options menu prior to game start then you exit to main game screen & begin game from there – xaltx Apr 08 '21 at 06:07
  • @xaltx With the updated edit of the delegate{} to the onClick listener do the buttons work as expected now? – TEEBQNE Apr 08 '21 at 06:22
  • Unfortunately, not yet. I tried upping the Hard Difficulty to 20 in the Inspector to see if I could get a more dramatic result but spawn rate appears the same still no matter what Difficulty selected. Let me know if there's a Debug, etc to determine what I'm doing wrong. and many thanks again in advance--truly appreciate your time – xaltx Apr 08 '21 at 06:31
  • @xaltx I just copied the code I wrote and the objects are spawning faster when I click on the faster buttons. If you want to add a debug, try adding one to the function `UpdateSpawnRate()` in the script `RandomSpawn`. The spawnRate should decrease as the difficulty increases. Add the line `Debug.Log(spawnRate + " " + difficulty);` to the function to see if it is properly working. Something you can try is copying the code written here directly into your scripts. If that does not work, it is something to do with your editor setup. – TEEBQNE Apr 08 '21 at 06:49
  • @xaltx The one difference is I am not calling your StartGame function. I do not see that being the issue though but you can try not calling it. – TEEBQNE Apr 08 '21 at 06:54
  • @TEEBQNE--ok, checking it out now. will report back in a few – xaltx Apr 08 '21 at 06:56
  • really glad it worked for you--still no change over here. i copied your edited code directly in. the console isn't showing anything weird with the new debug log entry. checking editor setup now – xaltx Apr 08 '21 at 07:25
  • just added to original post a screenshot of my Inspector setup on Hard. Since the click functions are called out in the script, I don't think there are any Onclick additions that need to be made in the Inspector, right? – xaltx Apr 08 '21 at 07:42
  • @xaltx Nope that all looks right. If the spawner and the buttons exist at compile time (Meaning before you run the game), you could remove the code for adding the onClick and do it in the inspector. It might be easier to track. Just click the + button on the bottom of the onClick list, then drag in the Spawner object that is in your scene. After that select the script component RandomSpawn from the drop-down list and after that select the function UpdateSpawnRate. The inspector will then give you a box to fill in the difficulty number. – TEEBQNE Apr 08 '21 at 14:55
  • @xaltx But you tried the Debug.log and that was printing the correct information right? I tried all of this myself and it seems to be working. There must be something else with your setup that makes it not work. – TEEBQNE Apr 08 '21 at 14:55
  • many thx for the workaround!!! switching to onClick in the Inspector made everything work, but only in my Options (select Difficulty) scene 1 (I was able to verify that diff selections did change spawn rate, but of course don't want enemies to be spawning there)----once I exit to play game screen, press play & enter scene 2/level 1, the difficulty selection does not carryover into that scene or subsequent scenes/levels. My play game script is simple--hopefully it's not interfering with our Difficulty/Spawn code mods : SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1); – xaltx Apr 08 '21 at 23:06
  • You will need to save data. By default, data is not persistent through Unity scenes. Check out [this](https://stackoverflow.com/questions/32306704/how-to-pass-data-between-scenes-in-unity) post. I am not sure which one fits your needs best, but some of the easiest are using a static object, using PlayerPrefs or DontDestroyOnLoad. – TEEBQNE Apr 08 '21 at 23:09
  • If you need more help pertaining to keeping data persistent I would open a new question with your attempt and what is not working. Generally, the comment section is not supposed to be used this much. As your original question is answered and if my answer solved it, I would select it as the answer and upvote it. That way if someone else has a similar issue they can know this resolved it. Again, if you are still having trouble I am happy to help in a new post that has a different more relevant question now. – TEEBQNE Apr 08 '21 at 23:29
  • Thank you very much! Upvoted (since I'm brand new to Stack, it's not showing yet). just added playerprefs so will make new post. you are awesome TEEBQNE! – xaltx Apr 08 '21 at 23:46
  • Just saw the new post. You can also select an answer as the one that solved your problem. You can do that by clicking the empty checkmark to the left of the solution I provided. – TEEBQNE Apr 09 '21 at 00:10