I have been reading on the forums, and i see there are 2 ways of doing it…:
the one i think many recommend is using the GetComponent correct?
need help trying to implement it, i am confused on the naming, so here is my 2 script names below…
///this has the variable i want to pass to Ant_Eat script
public class Smash : MonoBehaviour
{
bool Smashed_Ant = false;
void Start()
{
}
void Update()
{
}
}
///this is the script i want to have the bool character appear
public class Smash : MonoBehaviour
{
GameObject Ant_Smashed = GameObject.Find("Smash");
void Start()
{
Smash smash = Ant_Smashed.GetComponent<Smash>();
}
void Update()
{
}
}
again, trying to understand but let me know, the other trick was to put the bool variable as a static, which i believe jlb said not to do, i want to learn the right way and good habits
You want to use Find very sparingly. Probably don’t use it in this case. In most cases, you will do the following:
public class Bool_Script_To_Access : MonoBehaviour
{
public bool Smashed_Ant = false;
}
public class Script_To_Do_Stuff : MonoBehaviour
{
public GameObject ant;
private Bool_Script_To_Access bool_script;
private void Start()
{
bool_script = ant.GetComponent<Bool_Script_To_Access>();
}
private void Update()
{
bool_script.Smashed_Ant = true;
}
}
This is assuming that the two scripts are attached to two separate game objects. Now, in the inspector, select the game object which is attached to Script_To_Do_Stuff. Then, drag the game object which is attached to Bool_Script_To_Access to where it says “ant.” Done. This will work for most cases you’ll have. If you need more general reference to a game object it gets more difficult, and you might want to look into singleton approach.
Edit: You might check out the first 15 minutes or so of Persistence: Saving and Loading Data - Unity Learn
where he creates a GameControl which stores variables that can be accessed from any script. It is a great video.
public class Smash : MonoBehaviour
{
public bool Smashed_Ant = false;
void FixedUpdate ()
{
void_Smashed_Ant(); // this will change the bool Smashed_Ant to true;
}
}
the script that needs to access is below, so the above script has a touch function, and when the user touches the ant, he smashed it, so with the bool variable now changed from false to true, i want the below script to see it and stop a timer below, or in this example, just use the log to register it smashed.
public class Ant_Eat : MonoBehaviour
{
public GameObject Ant;
void Start()
{
Ant = GameObject.FindGameObjectWithTag("Ant");
}
void Update()
{
if (Ant.GetComponent<Smash>().Smashed_Ant == true)
{
Debug.Log("Ant Smashed");
}
}
}
I haven’t watched the video, but I will say using GetComponent every single frame is a very bad idea – very expensive. The 2 ways I told you both work great, however.
The object reference error is because you have to drag the ant game object to the field “ant” in the other script in the inspector. I mention that above.
ok let me just give the objective of what i want maybe this will help.
if the ant collides with an object, then start a timer… if its smashed even when its collided or not, stop or reset a timer back to 10 seconds. i have a timer that goes off when the ant collider hits another object collider, which then has a count down timer… if the ant is smashed before the timer is 0, then reset timer to 10 seconds…
so far, i just have it where the ant object is destroyed… and it has a script called smash on it… and the other object has the “Ant_Eat” script…
You need to either Get the value or Set the value. When the bug is squished you would invoke a method or call a method on the bug to update its state. It’s possible to have the object monitor a variable but that is not ideal for performance. Rather think about it this way, the input script checks if you clicked on a bug. Once you click on a bug you call the method on a bug script that resides on the bug called ‘Clicked()’. I think your question is more along the line of logic than process.
You should very rarely (only if you absolutely have to) use GetComponent in Update. Notice how I cache the GetComponent in a variable in Start above. Otherwise, it could lead to garbage that needs to be collected. Good Luck
thank you for taking the time, however i am getting this error message:
UnassignedReferenceException: The variable ant of Ant_Eat has not been assigned.
You probably need to assign the ant variable of the Ant_Eat script in the inspector.
UnityEngine.GameObject.GetComponent[Smash] () (at C:/buildslave/unity/build/Runtime/Export/GameObject.bindings.cs:28)
Ant_Eat.Start () (at Assets/Scripts/Ant_Eat.cs:27)
at this part of the code:
public GameObject ant;
private Smash smash;
// Use this for initialization
void Start()
{
smash = ant.GetComponent<Smash>(); /* <- right here is where its saying the error message is raised*/
}
not sure why. I dragged my ant prefab to the public Gameobject on my unity, but this error still shows up.
That’s the thing – use the ant in the scene and not the prefab. It’s a pain to get your instantiated objects to play well with your game objects that are always in the scene, because of the way Unity works. Sometimes you have to get creative, depending on what you want to do. If it’s not in the scene before you hit play, then you may want to “find” it at Start(). I would use “find” sparingly though, as I said before, and try to only use it at Start() or Awake().
The GameControl method works pretty well for me, because the player is always in the scene. I try to design everything so that the ant needs to access player information and rarely the other way around, if that makes sense. Because, there may be many ants, but in my case, there is only one player. Then, I store player information in the GameControl. If you need even more access, then a more advanced singleton would perhaps be better.
For an unrelated example, just to give you an idea of how to manage many ants in a scene, in the game I’m making right now, I use “tags” often. I’ll have a collider on the ant. Then in OnColliderEnter(), if (collider.gameObject.tag == “player”), then he gets squashed. That keeps things simple, and then each individual ant has their own squashed boolean variable, so every ant in the scene is not affected – only the one that was collided with. That’s just one way to handle things, but I hope you get the idea.
Thanks for the extremely detailed answers, Tarball! I was able to get script referencing to work after about 3 hours because of this.
Some key lessons I learnt:
Public variables show up in the Inspector under the script. (I believe serialize field private variables do too, but haven’t experimented on that).
When you are just trying to read or reference a variable in the initial script, the only thing that needs to change is whether it is public (or serialized private).
In your accessing script:
Since you are going to be referring to the script to be accessed through a game object, you must create a public Gameobject. What this does is it creates a variable on the inspector that allows for a Gamobject to be dropped in.
You drag and drop (from the hierarchy) the gameobject (with the script to be accessed attached to it) through the inspector into that Gameobject variable space.
I’ve found that you can create a static Instance of an object if you are referencing a script in multiple other scripts. Be aware that this will only work if there is only a single instance of the script.
So here is the script that you want to get variables from:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectPooler : MonoBehaviour
{
public static ObjectPooler Instance;
private void Awake()
{
Instance = this;
}
// Rest of your code goes here
}
You can then reference the script in other scripts like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Example : MonoBehaviour
{
ObjectPooler objectPooler;
void Start()
{
objecetPooler = ObjectPooler.Instance;
}
//Rest of your code below
}