Can someone help me with this code?

So i have the following code:
using UnityEngine;
using System.Collections;

public class WinOrLose : MonoBehaviour {
public static int heroCount;
public static int enemyCount;

private bool isHero;
private bool isEnemy;

private LevelManager levelManager;
// Use this for initialization

void Awake()
{
    heroCount = 0;
    enemyCount = 0;
}
void Start() {
    isHero = (tag == "hero");
    isEnemy = (tag == "enemy");

    if (isHero)
    {
        heroCount++;
    }
    print("hero count is:" + heroCount);

    if (isEnemy)
    {
        enemyCount++;
    }
    print("enemy count is:" +enemyCount);

    levelManager = GameObject.FindObjectOfType<LevelManager>();
}

// Update is called once per frame
void Update () {
    if (enemyCount <= 0)
    {
        SimulateWin();
    }
    //hypthetical function SimulateLose() does not exist
   // else if (heroCount <= 0)
   //{
    //    SimulateLose();
    //}
}



void SimulateWin()
{
    levelManager.LoadNextLevel();
}

}

for unity and i created 2 empty game objects, tagged one as hero and one as enemy.

I applied the script to both which might be cause of the following problem:
When i print the heroCount and enemyCount it prints 2 heroCounts to the console, each saying 1 and 1 enemyCount saying 0 and 1 saying 1. I am not sure why is prints 2 heroCounts and 2 enemyCounts could someone tell me what is wrong here? (also why is one enemyCount 0 and one of them 1)?

Thanks in advance

Hi @CelloGuy,

I’ve just run your code at this end to get a bit of a better understanding. The only thing I don’t have is your level manager code, so I have just commented out the calls to that, and instead inserted another Print statement in the SimulateWin() method.

So… you have a bit of a mix going on here…

If you currently have “Collapse” selected on your console I would suggest unselecting it for the moment (indicated in me screenshot), that way you will see the individual messages and it will probably make more sense.

To answer your first question, why do you get these messages twice - that’s because you have dropped the same script which is doing the same thing on to two objects. Both are calling the same code, hence, twice.

Regarding the differences in the counts if you look at your logic in your Start() method you say, effectively, if something is true, increment the counter. But regardless of the logic you print the hero count, and then on the second logic statement you print the enemy count.

So you you will see something like this…

The horizontal (ish) red line indicates your two separate game objects. The first two Print() statements are coming from game object 1, the second two from game object 2.

As it happens, my first game object is a hero, thus, the count is set to 1. Its not an enemy so that count remains at 0. But both are printed. Then the same code runs again on your second game object. This time, the object is actually an enemy, so the hero count is not increment, but you still print the count. The enemy count is then incremented, and you print that out.

What happens when this is collapsed is this:

The numbers on the far right (2, 1, 1) are simply the counts of matches messages that have been sent to the console. You don’t actually have two heroes, you have just printed the same message twice.

Update

If I might offer a suggestion…

Your WinOrLose script (class) is really your game controller, I would consider renaming it as such, or similar. Naming objects as to what they actually are will make things easier going forwards.

The next thing then ideally would be perhaps that your GameController keeps a track of the number of heroes and enemies, but that code doesn’t need to be applied to each hero or enemy.

You could determine the number of enemies and/or heroes by using something like this (quickly grabbed from the interwebs):

enemyCount = GameObject.FindGameObjectsWithTag("Enemy").length // replace Enemy with hero for heroes etc

1 Like

is this fine? @Rob because i was just wondering if it would affect my code in any way?

also the other part is, i have just run this code again but this time deleted the enemy game object. It print enemy count is 0 but it doesnt move onto the next level which is what my intent is with the update function. What am i doing wrong?

Did you still have the game running when you deleted the enemy? If so, your static variable holding the count would have already = 1, thus not the 0 (zero) required to load the next level. You currently have no methods to handle the an enemy being killed/destroyed do you, if you did and then reduced your enemyCount by 1 eventually you would get to 0 (zero) and your logic should load the next level… here’s screenshot from mine… I stopped the game, deleted the enemy object, ran the game…

Note, 481 is just the number of times it printed the same message, because I took out the call to actually load the next level (no level manager etc)

1 Like

Ah, if i add in a print to the function it does work and it keeps on printing next level loaded however the next level is not loading. Thanks for the help!

Well it works when i make it levelManager.LoadLevel(“Win”)
So it is probably something to do with my code in LevelManager
could you take a look if you have time?
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;

public class LevelManager : MonoBehaviour
{
// exposing the float autoloadnextlevelafter, tells computer how long to wait until computer auto loads next level, put in 0 if you dont want auto
// load
public float autoLoadNextLevelAfter;
void Start()
{
// tells computer if auto load is 0 then dont load next level
if (autoLoadNextLevelAfter == 0)
{
Debug.Log(“Level auto load disabled”);
}
// otherwise load next level after the amount of time
else {
Invoke(“LoadNextLevel”, autoLoadNextLevelAfter);
}
}
// for loading levels
public void LoadLevel(string name)
{
Debug.Log(“New level load:” + name);
SceneManager.LoadScene(name);
}
// for quitting
public void QuitRequest()
{
Debug.Log(“Quit requested”);
Application.Quit();
}
// function loadnextlevel
public void LoadNextLevel()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
}
}

You’re welcome. I updated my initial response with a couple of additional suggestions (was writing it when you responded so just thought I’d let you know in case you’ve not seen it)…

It looks like at the moment you are just running some tests which is cool, if you separate out the scripts a bit so that they only do the one thing they need to do, you could then create a separate script which is just literally for play testing… something like…

// add a hero
…
// add 5 enemies
…

// shoot 2 enemies
…

// shoot last 3 enemies
…

or whatever story you want to test… but these would be responsible for calling the code which increments/decrements the number of heroes/enemies… your GameController should then be able to handle the win (or lose) scenario… you can do it all with Print() statements too, so you can see exactly what is going on as it happens…

Remember, some methods may get called a lot (like mine with the 481 repetitions) so you may need to turn Collapse back on :slight_smile:

1 Like

So, you have a few different ways of loading a new scene. The one you have tried above is obviously by name. Unity will use the first instance it finds where that name matches (care has to be taken when typing the names in)…

In the code you pasted, you are doing this;

public void LoadNextLevel()
{
    SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
}

Instead of using a name your are using the Index value and incrementing it, as you are retrieving the GetActiveScene().buildIndex value, I would probably start there… for example… comment out that line for now… and replace it with this:

public void LoadNextLevel()
{
    // SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
    Print("Current build index is: " + SceneManager.GetActiveScene().buildIndex);
}

Let’s say for argument’s sake that returns a “1” to the console, it would be fair to assume your previous line (the one we commented out) would say “load the scene with a build index of 2”… if that’s the case, go to File… Build Settings… and check how many scenes you actually have in that list. The Unity documentation doesn’t suggest whether the index is zero based or not, so I’m assuming not. If you code wants index 2 then you’d need to have at least 2 scenes in the list.

1 Like

the code is 0 index based. I have all my scenes and there is a scene in uild settings after the level im testing

So, assuming you are starting your game on your first scene you will be on index 0 yes? if so, what happens if you hard code your existing LoadNextLevel() method to load scene index 1 for example?

SceneManager.LoadScene(1);

Can you try the above and see if it successfully loads your scene as it did when you provided the name “Win” etc.

1 Like

im not entirely sure what you are suggesting?
Sorry

Sorry, what I meant was, if you replace this:

with this:

public void LoadNextLevel()
{
SceneManager.LoadScene(1);
}

Just as a quick test… does it successfully load the scene (with an index value of 1) just like it successfully loaded the scene when you tried it via a name (“Win”) etc.

1 Like

no it doesnt work @Rob

That’s interesting.

Ok, so now try moving the;

using UnityEngine.SceneManagement;

from your levelManager and putting it at the top of the WinOrLose script.

and then in your SimulateWin() method, comment out what is there at the moment (the reference to the levelManager method) and pop this in;

SceneManager.LoadScene(1);

Does that make another scene load? If not, can you change the

SceneManager.LoadScene(1);

to

SceneManager.LoadScene("Win");

which worked earlier and just confirm that that still works please.

1 Like

If i`m not wrong, they made some changes in unity that made those methods become obsolete from unity 4 to 5, You added “using UnityEngine.SceneManagement” to the top of the script? I had an error with that method when I updated unity.

Upgrading to Unity 5.3 notes

The methods that become obsolete were related to Application. (Application.LoadLevel), these aren’t being used from what I can see.

SceneManager is being used, the namespace for UnityEngine.SceneManagement was in a different script, hence the suggestion to bring it all into this one for testing purposes…
https://docs.unity3d.com/ScriptReference/SceneManagement.SceneManager.LoadScene.html

I’m wondering whether there may be something going on with the way that the method is being called via Invoke, but wanted to break it down into some smaller pieces first.

1 Like

Hmmm. i came back from sleeping, my autoLoadNextLevel function wasnt working
so i decided to uncolmment loadnextlevelafter
just for test sakes
and lo and behold my script starts working. I dont know what happened there but its fine with me :slight_smile:

1 Like

That seems odd as you weren’t calling that from the other code? Glad you have it sorted anyway, amazing what a bit of sleep can do! :slight_smile:

I think we had got to the point where if it needed anymore looking at I’d have personally needed to see all the code, as it was getting a bit hard to go through etc.

Glad you are all sorted. Can you mark the post as [Solved] - thanks in advance :slight_smile: