17

I've searched around and I just can't get this to work. I think I just don't know the proper syntax, or just doesn't quite grasp the context.

I have a BombDrop script that holds a public int. I got this to work with public static, but Someone said that that is a really bad programming habit and that I should learn encapsulation. Here is what I wrote:

BombDrop script:

 <!-- language: c# -->

 public class BombDrop : MonoBehaviour {

 public GameObject BombPrefab;

 //Bombs that the player can drop
 public int maxBombs = 1;


 // Update is called once per frame
 void Update () {

 if (Input.GetKeyDown(KeyCode.Space)){

         if(maxBombs > 0){
         DropBomb();

         //telling in console current bombs
         Debug.Log("maxBombs = " + maxBombs);
         }
   }


 }    

 void DropBomb(){

     // remove one bomb from the current maxBombs
     maxBombs -= 1;

     // spawn bomb prefab
     Vector2 pos = transform.position;
     pos.x = Mathf.Round(pos.x);
     pos.y = Mathf.Round(pos.y);
     Instantiate(BombPrefab, pos, Quaternion.identity);

 }
}

So I want the Bomb script that's attached to the prefabgameobject Bombprefab to access the maxBombs integer in BombDrop, so that when the bomb is destroyed it adds + one to maxBombs in BombDrop.

And this is the Bomb script that needs the reference.

 public class Bomb : MonoBehaviour {
 // Time after which the bomb explodes
 float time = 3.0f;

 // Explosion Prefab
 public GameObject explosion;

 BoxCollider2D collider;

 private BombDrop BombDropScript;




 void Awake (){

     BombDropScript = GetComponent<BombDrop> ();
 }

 void Start () {

     collider = gameObject.GetComponent<BoxCollider2D> ();

     // Call the Explode function after a few seconds
     Invoke("Explode", time);

 }

 void OnTriggerExit2D(Collider2D other){

     collider.isTrigger = false;
 }

 void Explode() {
     // Remove Bomb from game
     Destroy(gameObject);

     // When bomb is destroyed add 1 to the max 
     // number of bombs you can drop simultaneously .
     BombDropScript.maxBombs += 1;

     // Spawn Explosion
     Instantiate(explosion,
                 transform.position,
                 Quaternion.identity);

In the documentation it says that it should be something like

BombDropScript = otherGameObject.GetComponent<BombDrop>();

But that doesn't work. Maybe I just don't understand the syntax here. Is it suppose to say otherGameObject? Cause that doesn't do anything. I still get the error : "Object reference not set do an instance of an object" on my BombDropScript.maxBombs down in the explode()

apxcode
  • 7,696
  • 7
  • 30
  • 41
DoubleCode
  • 185
  • 1
  • 1
  • 7

3 Answers3

27

You need to find the GameObject that contains the script Component that you plan to get a reference to. Make sure the GameObject is already in the scene, or Find will return null.

 GameObject g = GameObject.Find("GameObject Name");

Then you can grab the script:

 BombDrop bScript = g.GetComponent<BombDrop>();

Then you can access the variables and functions of the Script.

 bScript.foo();

I just realized that I answered a very similar question the other day, check here: Don't know how to get enemy's health


I'll expand a bit on your question since I already answered it.

What your code is doing is saying "Look within my GameObject for a BombDropScript, most of the time the script won't be attached to the same GameObject.

Also use a setter and getter for maxBombs.

public class BombDrop : MonoBehaviour
{
    public void setMaxBombs(int amount)
    {
        maxBombs += amount;
    }

    public int getMaxBombs()
    {
        return maxBombs;
    }
}
Community
  • 1
  • 1
apxcode
  • 7,696
  • 7
  • 30
  • 41
  • This sounds about right but one question. The bombPrefab is a prefab I don't want to stay in the scene. because upon destroy it changes my maxBombs count. And If I have a bomb in the scene already it messes the counter up. Isn't there a way to access the prefabs script without it being in the scene? – DoubleCode Oct 24 '14 at 17:55
  • There are ways of having a class object alive without it being in the scene. For example, static class, regular C# class that is not a MonoBehaviour, etc. However, your code does imply that `BombDrop` needs to be in the scene because of the `Update` code that creates Bombs. Also I just realized you can write your code so much simpler. I will update my answer. – apxcode Oct 24 '14 at 18:01
  • Yes my player has the BombDrop script that instantiates the bombPrefab. So the prefab is not in the scene before instantiated. But maybe the target works once it is instantiated? So it finds it 's target anyway? Ok, that would be of great help : ) My code is just what I could put togheter from own bad logic hehe. – DoubleCode Oct 24 '14 at 18:05
  • And one thing! I plan on having more than one player, so the bomb kinda need to know who has created it. So it doesn't reset the counter of the other players. But that's for later. First I just needed the reference : ) – DoubleCode Oct 24 '14 at 18:08
  • Actually, I take that back. The way you set it up, you do need to call the `BombDrop`. I didn't think of other Players! So, yes use my code and you will be fine. Make sure you add a setter and a getter to `maxBombs`, public variables are dangerous. – apxcode Oct 24 '14 at 18:08
  • Oki : ) And you think that will work without the bombPrefab being in the scene from start? It will know the tag once it instantiate? – DoubleCode Oct 24 '14 at 18:12
  • Correct, the prefab should not be in the scene, just make sure that `BombDrop` is always in the scene. – apxcode Oct 24 '14 at 18:13
  • 1
    Thank you: ) I'll take a look on the set and get logic from documentation. – DoubleCode Oct 24 '14 at 18:15
2

use it in start instead of awake and dont use Destroy(gameObject); you are destroying your game Object then you want something from it

void Start () {
     BombDropScript =gameObject.GetComponent<BombDrop> ();
     collider = gameObject.GetComponent<BoxCollider2D> ();

     // Call the Explode function after a few seconds
     Invoke("Explode", time);

 }

void Explode() {
//..
  //..
//at last
Destroy(gameObject);
 }

if you want to access a script in another gameObject you should assign the game object via inspector and access it like that

 public gameObject another;
void Start () {
     BombDropScript =another.GetComponent<BombDrop> ();
}
Milad Qasemi
  • 3,011
  • 3
  • 13
  • 17
  • Hmm, no still doesn't work. Maybe it's something with the explode method? – DoubleCode Oct 24 '14 at 16:13
  • dont use Destroy(gameObject); you are destroying your game Object then you want something from it – Milad Qasemi Oct 24 '14 at 16:14
  • Ah I see, so it destroys it before it is called? But how can I make it change the variable after it is destroyed then. If I set it over the destroy in Explode() it never destroys. – DoubleCode Oct 24 '14 at 16:18
  • just make it the last thing that it does like this void `Explode() { //.. //.. //at last Destroy(gameObject); }` – Milad Qasemi Oct 24 '14 at 16:20
  • hmm. I Have now Explode(){ BombDropScript.maxBombs before the Destroy(gameObject} But Ingame now it never destroys, it never disappear. And I still get the Null reference on my BombDropScript.maxBombs I suspect that it still doesn't find the maxBombs from BombDrop script and therefore just stops. But it did work with public static. – DoubleCode Oct 24 '14 at 16:24
  • No, I tried debugging seeing if it got the reference. It didn't so the problem is that it doesn't see the maxBombs from BombDrop still. hmm – DoubleCode Oct 24 '14 at 16:32
  • No BombDrop is attached to the player, another gameobject. And the Bomb script is attached to the bombPrefab – DoubleCode Oct 24 '14 at 16:33
  • when you use `obja.GetComponent ();` it means that a `BombDrop` is attached to `obja` and i want to grab it – Milad Qasemi Oct 24 '14 at 16:35
  • I can't quite understand what you mean though. The thing I want is to grab the maxBombs from the BombDrop script on another gameobject. what is the syntax? that's my problem I think. I tried this.getComponent, gameObject.getComponent, otherGameObject.getComponent. nothing works yet. As you see in my code up above. what should it say instead of BombDropScript = GetComponent (); ? – DoubleCode Oct 24 '14 at 16:40
  • i edited my answer to show you how to access a script in another gameobject – Milad Qasemi Oct 24 '14 at 16:45
  • assign another via inspector `public gameObject another; void Start () { BombDropScript =another.GetComponent (); }` – Milad Qasemi Oct 24 '14 at 17:06
0

Can Use this :

entBombDropScript.maxBombs += 1;

Before :

Destroy(gameObject);

I just want to say that you can increase the maxBombs value before Destroying the game object. it is necessary because, if you destroy game object first and then increases the value so at that time the reference of your script BombDropScript will be gone and you can not modify the value's in it.

Omdevsinh Gohil
  • 145
  • 1
  • 4