Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

How do I set a variable for an element stored in an array from another script?

Discussion in 'Scripting' started by OneMoreRound, Apr 20, 2018.

  1. OneMoreRound

    OneMoreRound

    Joined:
    Jul 22, 2015
    Posts:
    46
    I have a simple scene where objects are spawned at 7 random locations.

    These spawn locations are pre-loaded into an array SpawnPoints within my game controller script, DuckShootManager. DuckShootManager is attached to an empty GameObject called GameManager.

    When an object is spawned, a call is made to BottleManager, which is attached to each bottle. That bottle is given a number location relating to its spawn position.

    A call is then made to the SpawnPointManager array and an inUse bool is set to true to say that position is now in use.

    In the game, when that object is hit a hit()function within the BottleManager is called. From here force is applied to knock the object off the shelf.

    My problem is:

    How do I now set the .inUse variable of that spawn location back to false?

    The BottleManager knows the location, it is stored in int location. But i get an Object reference not set error.



    DuckShootManager script

    Code (CSharp):
    1.  
    2. public class DuckShootManager : MonoBehaviour {
    3.  
    4.  
    5.     public Transform[] spawnPoints;
    6.     public GameObject[] bottles;
    7.  
    8.     public float spawnWait;
    9.     private float curSpawnTime;
    10.  
    11.     public SpawnPointManager[] spawnPointManager;
    12.  
    13.     private int bottlesDisplayed;
    14.  
    15. private void spawnBottle(){
    16.  
    17.         if (bottlesDisplayed < spawnPoints.Length) {
    18.          
    19.             int i = Random.Range (0, spawnPoints.Length);
    20.  
    21.             if (spawnPointManager [i].inUse == false) {
    22.                 Vector3 pos = new Vector3 (spawnPoints [i].position.x, spawnPoints [i].position.y, spawnPoints [i].position.z);
    23.                 Quaternion rot = new Quaternion (0, 0, 0, 0);
    24.  
    25.                 GameObject bottle = Instantiate (bottles [Random.Range (0, bottles.Length)], pos, rot) as GameObject;
    26.  
    27.                 BottleManager b = bottle.GetComponent<BottleManager> ();
    28.  
    29.                 b.location = i; // adds what location the bottle is at
    30.  
    31.                 spawnPointManager [i].inUse = true; // sets the spawn point as in use
    32.  
    33.                 bottlesDisplayed += 1;
    34.  
    35.  
    36.             } else spawnBottle();
    37.          
    38.  
    39.         }
    40.     }
    41.  
    42. }
    43.  
    44.  
    BottleManagerScript

    Code (CSharp):
    1. public class BottleManager : MonoBehaviour {
    2.  
    3.     private Rigidbody rb;
    4.     private Collider bottleCollider;
    5.  
    6.     public int location;
    7.  
    8.     private GameObject gameManager;
    9.     private DuckShootManager duckShootManager;
    10.  
    11.     public int scoreValue;
    12.  
    13.     // Use this for initialization
    14.     void Start () {
    15.  
    16.         rb = GetComponent<Rigidbody> ();
    17.         bottleCollider = GetComponent<CapsuleCollider> ();
    18.         duckShootManager = gameManager.GetComponent<DuckShootManager> ();
    19.  
    20.     }
    21.  
    22.     // Update is called once per frame
    23.     void Update () {
    24.      
    25.     }
    26.  
    27.     public void hit()
    28.     {
    29.         rb.AddForce (transform.forward * 100);
    30.         bottleCollider.enabled = false;
    31.  
    32.         duckShootManager.spawnPointManager [location].inUse = false;
    33.  
    34.     }
    35. }
    36.  
    SpawnPointManager script


    Code (CSharp):
    1. public class SpawnPointManager : MonoBehaviour {
    2.  
    3.  
    4.     public bool inUse;
    5.  
    6.     // Use this for initialization
    7.     void Start () {
    8.         inUse = false;
    9.     }
    10.  
    11.     // Update is called once per frame
    12.     void Update () {
    13.      
    14.     }
    15. }
    16.  
     
  2. whileBreak

    whileBreak

    Joined:
    Aug 28, 2014
    Posts:
    289
    If the bottles are being spawned then gameManager won't be set. On the duckShootManager, when you set the location after instantiating the bottles, you should also set the duckShootManager, I think.

    Code (CSharp):
    1.  b.location = i;
    2. b.duckShootManager = this;
    delete the assignment on the bottle
     
    OneMoreRound likes this.
  3. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,140
    Right now, gameManager and duckShootManager are both private variables and although you try to assign duckShootManager, gameManager doesn't appear to be set anywhere, thus you can't actually get a value to duckShootManager.

    So either use object pooling, make duckShootManager public and drag and drop.
    Use a singleton pattern to your duckShootManager and access it through the singleton.
    Make duckShootManager public and assign its value when it spawns. (@whileBreak shows this, but duckShootManager would still need to be public)

    Also, you'll want to remove the assignment in Start to avoid setting it back to null.

    There are other ways also, but those should be the easier methods I think if you are still learning.
     
    Last edited: Apr 20, 2018
    OneMoreRound and whileBreak like this.
  4. OneMoreRound

    OneMoreRound

    Joined:
    Jul 22, 2015
    Posts:
    46
    Thank you both for your replies.

    @whileBreak what does your snipped of code do? (primarily line 2 as I've not seen this before).

    @Brathnann thank you for the explanation - I'm looking into object pooling and I think I'm understanding how that would be a better solution. Am I right in saying that this is a much better way to tie game objects in with the game manager? (as a general principle)
     
  5. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    'this' refers to the object/script.
     
  6. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,140
    Object pooling generally is a better option, but like many things, it has it's place. Generally speaking any situation where you can reuse stuff (bullets, massive enemies, puzzle pieces) are good cases where object pooling may be better. It is better than instantiate/destroy and it's usually easier to hook up.