Yeah, I’ve seen that. It’s bad advice. You usually do not want things to be static. Static variables belong to their class, NOT to instances of the class. For example, when you make the enemy health static, you’re saying that all enemies have one health pool that they share, and whenever you damage one, you damage all of them. The better way to interact with other scripts’ variables is to get a reference to the other script. You can do that through the inspector, through events, or with certain methods.
Let’s say you have one script you want to interact with, Enemy:
public class Enemy : MonoBehaviour
{
public float health; // This is a public variable, which means other classes/scripts can access it
}
Note that nothing is static here. Health is instance variable, which means each instance of enemy has its own health.
This enemy script is very simple, but you could add Start and Update methods to make it more interesting; I’m leaving it simple for the example. There are a few ways you can interact with this script.
public class EnemySpawner : MonoBehaviour
{
public Enemy otherScript; // This is a variable of type Enemy. You can assign it in the inspector
private void Update()
{
Debug.Log("Enemy health: " + otherScript.health); // Here we are accessing the other script's variable through the reference above
}
}
This is the most common way, much better than static variables. In the editor, you can drag the object with the Enemy script into the inspector of the EnemySpawner script to populate the “otherScript” variable. If you don’t do that step, otherScript will never be assigned and you will get NullReferenceExceptions.
Here’s another way:
public class EnemyWeapon : MonoBehaviour
{
private Enemy otherScript; // This is a private reference. It cannot be assigned through the inspector, and other classes can't see this variable
private void Start()
{
otherScript = GetComponent<Enemy>(); // Gets an 'Enemy' script attach to the same GameObject as this script
}
private void Update()
{
Debug.Log("Enemy health: " + otherScript.health); // We can still use the private reference above!
}
}
This one only works if the two scripts are attached to the same object, but it can come in handy. In particular, GetComponent can be called on a game object, so if you have an object and need to get a script attached to it, GetComponent is the way to go. I cannot overstate how useful GetComponent is. In practice, this is probably the method I use the most to get references to other scripts and interact with them.
Here’s a small example of interacting with another script, using GetComponent, through the physics system:
public class Trap : MonoBehaviour
{
public float damage = 10f; // Assigned through the inspector, but with a default of 10
private void OnTriggerEnter(Collider other) // OnTriggerEnter is a message that Unity will call; it's a part of the physics system. The Trap object needs a collider set to be a trigger for this to work
{
Enemy otherScript = other.GetComponent<Enemy>(); // We use the collider that entered our trigger to find the enemy script with GetComponent
if(otherScript != null) // If the other object didn't have an Enemy script, GetComponent returns null
{
otherScript.health -= damage; // We use the damage variable of this script to remove health from the other script
}
}
}
Hope these examples help, good luck on your journey!