Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

[Solved] Calling function from different script somehow doesnt update intended variable.

Discussion in 'Scripting' started by Deleted User, Oct 20, 2019.

  1. Deleted User

    Deleted User

    Guest

    I'm really hoping someone can help me with this. I've been stuck for way too long.

    I have two scripts.

    Script Enemy_Wavespawner keeps track of how many enemies there are on the map by using int enemyCount. Basically it adds 1 to enemyCount whenever an enemy spawns, and it should subtract 1 from enemyCount whenever an enemy dies. I've included some debugs, will get back to that later.
    Code (CSharp):
    1. public class Enemy_WaveSpawner : MonoBehaviour
    2. {
    3.  
    4.     int enemyCount;
    5.  
    6.     void Start()
    7.     {
    8.         enemyCount = 0;
    9.     }
    10.  
    11.     void Update(){
    12.         if (Input.GetKeyDown(KeyCode.Tab))
    13.         {
    14.             Debug.Log(enemyCount);                              // DebugA
    15.         }
    16.  
    17.     IEnumerator enemySpawner()
    18.     {
    19.         // Enemy is spawned using instantiate.
    20.         enemyCount += 1;
    21.     }
    22.  
    23.     public void enemyCounter()
    24.     {
    25.         Debug.Log(enemyCount);                                   // DebugB
    26.         enemyCount -= 1;
    27.         Debug.Log(enemyCount);                                   // DebugC
    28.     }
    29. }

    Script Enemy_Health is attached to the enemy. When the enemy's health reaches zero or below it calls enemyCounter.
    Code (CSharp):
    1. public class Enemy_Health : MonoBehaviour
    2.  
    3.     public GameObject waveSpawnerObject;
    4.     Enemy_WaveSpawner spawnScript;
    5.  
    6.     float health;
    7.  
    8.     void Start()
    9.     {
    10.         health = 10;
    11.         spawnScript = waveSpawnerObject.GetComponent<Enemy_WaveSpawner>();
    12.     }
    13.  
    14.     public void ChangeHealth(int i)
    15.     {
    16.         // Code for receiving damage from player here.
    17.  
    18.         if (health <= 0)
    19.         {
    20.             spawnScript.enemyCounter();
    21.             Destroy(gameObject);
    22.         }
    23.     }


    At start of game, one enemy spawns and DebugA shows 1, as expected.

    The enemy dies, and enemyCounter is called.
    DebugB shows -18.
    DebugC then shows -19.
    Now, when calling Debug A it still shows 1.
    When I manually call enemyCounter from within its script Debug A does go down to 0.

    Now, when I quit the game, start again and repeat this process DebugB will show -19 and DebugC -20.
    So its storing a variable somewhere but I have no idea where.

    I'm pretty new to coding in general and I have no clue what's wrong.
     
    Last edited by a moderator: Oct 21, 2019
  2. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    Not related to the problem here, but instead of '+=1' you can just write '++'. Same for the subtract version.
    That said, the only weird thing i see in your code right now, is how your Update() function in the above script does not have a body {}. Neither do (both of) your classes. Is that a just a typo / copypaste mistake?
    If not i'd be surprised that it even compiled. If that's just a mistake in the forum example:

    Is it consistantly going down by one each time you play? Or did you just test it twice and it may have been a coincident that it was -18 once and -19 the second time? As you are initializing the enemyCounter to 0, it should start there every time. Do you reference the correct spawner script in your health script?

    And you said "Now when calling Debug A it still shows 1" - how did you test that? Debug A, according to your comments, is in Update(). You cannot, or should not, manually call that. It should get printed once per frame, every frame. Is that what you meant? But i guess there is either something missing, something wrong with the formatting, or something majorly wrong with the code there anyways, since the example is missing the whole {} brackets of the function. So that's enough questions for now until we cleared that :)
     
  3. Deleted User

    Deleted User

    Guest

    Thanks for your reply! I apologise if my copypaste wasn't clear. I emitted a lot of code that wasn't necessary to illustrate the problem and accidentally omitted the brackets as well I guess. The missing brackets are present in the actual scripts.

    It is consistently going down in number every time I play the game within Unity. If I kill multiple enemies in the same play its goes down 1 with each enemy death. If I press stop, and start again it picks up where it left off. The only way to reset it to 0 is to restart Unity itself, and then it will go down from there. So it is running the enemyCount -= 1, but it is not storing it in the variable enemyCount I declared at the top, but rather creating some sort of ghostvariable that shouldnt exist somehow?

    Debug A is called when I press the Tab Key using if(Input.GetKeyDown(Keycode.Tab)) and is only there for my own debugging purposes. The script in general seems fine. No errors or even notifications whatsoever.

    Similarly, when I say manually call enemyCounter I do it using Input.GetKeyDown.
     
    Last edited by a moderator: Oct 21, 2019
  4. bobisgod234

    bobisgod234

    Joined:
    Nov 15, 2016
    Posts:
    1,042
    Are you sure you don't have 2 or more instances of Enemy_WaveSpawner in the scene? You can enter "t:Enemy_WaveSpawner" into the hierarchy search to list all the instances of Enemy_WaveSpawner.
     
  5. Deleted User

    Deleted User

    Guest

    I checked, I only have the one GameObject with that one script. No duplicates.
    Of course, every enemy spawns with the Enemy_Health script attached to it.
     
  6. Deleted User

    Deleted User

    Guest

    I think I may have finally found the issue but I don't know how to fix it.

    The GameObject WaveSpawner is present in the scene with the script Enemy_Wavespawner attached to it. I also have a prefab of this object in my assets folder. It spawns enemies using a prefab of the enemy GameObject .

    The Enemy prefab has the WaveSpawner prefab linked as its waveSpawnerObject. So I think it's trying to change the variable on the wavespawner prefab, but not on the WaveSpawner object that is in the scene.

    Is that possible? If so, how would I go about solving this? I can't drag and drop the WaveSpawner object from the hierarchy into the slot in my enemy prefab.
     
    Last edited by a moderator: Oct 21, 2019
  7. bobisgod234

    bobisgod234

    Joined:
    Nov 15, 2016
    Posts:
    1,042
    You can reference prefabs, and the scripts attached to prefabs, from instances in the scene in play mode. They work much like an instance would.

    You need your enemies to reference the instantiated WaveSpawner. You can use FindObjectOfType, or set up your WaveSpawner as a singleton.
     
  8. Deleted User

    Deleted User

    Guest

    Solved.

    Instead of declaring a public GameObject and dragging/dropping the prefab in, it now uses FindGameObjectWithTag in Start function to find the correct instance of WaveSpawner.

    I'm still confused how the previous setup managed to store a variable that never existed in the scene, but at least it's fixed. Thanks for thinking along.