What is a good way to manage connections in projects?

Hi,

I usually write a lot of classes which find an object (e.g. FindWithTag), access a script (GetComponent) and modify public variables / use public methods. I do this for communication between enemies player, as well as for reading ‘global’ properties like game speed, gravity and other global forces.

Is this considered good style?
Do you have distinctly better ways of managing this type of standard interactions (perhaps using inheritance, or writing your own events)? Or is what I am doing pretty standard in Unity?

Thank you!

As far as i’m aware, all Find methods are somewhat slow and you don’t really want to use them past the Awake time of the scene.

What i’m doing is having a list (or array, depending) of all objects of specific class, attached as a static variable to the class itself. This then allows me to access any object in that list from any place in the code.

Something like this in c#:

public class Light : MonoBehaviour {
    public static List<Light> list = new List<Light>(); // Static list of references to all Light class MonoBehaviours
    ...
    public void Awake() { // when the engine finds Light attached to a game object ...
          list.Add(this); // it adds this Light to static list
          ...
    }
    public static void DoSomething() { // a function that does something with the light
         ...
    }
}

public class Main : MonoBehaviour {
    public void Update() {
         foreach (Light l in Light.list) {
                l.DoSomething();
         }
    }
}

Hi uniMaxi,

I think your idea works very well when you have many objects behaving in exactly the same way. However, if you wanted to speak to a specific instance, you would have to find the object in your list with a particular tag (or object name) anyway, right? If, for instance, you had a simple game with many shooters, each shooting at all others, this would be perfect for a public static shooter list. If, however, the player also belongs to that list (because it has the same mechanics, with the addition of a movement script or something) and there is even the slightest form of individual treatment (for example that is more likely that someone shoots at the player), you would need to find the player instance among the instances of the shooter list, using tag or name or something. So it seems to me that static lists work only in limited cases of very similar mass behaviour and they are not ideal for individual treatment / exceptions to that behaviour. Would you agree?

Also, I remember having some issues updating the values in the inspector for static public fields. But maybe it was just me / maybe this is fixed.

The inspector isn’t designed to handle static things - it only really handles member variables.

Anyway, you can use the exact same concept (self-registering components) but with a Dictionary instead of a List (populating the dictionary key with whatever is relevant - GO name, tag…). I like avoiding strings whenever possible, so I’d probably make an enum like ActorType { Player, FriendlyNpc, UnfriendlyNpc, NeutralNpc } and use that as the key.

If you wanted to use the tag string for example it could be

Dictionary<string,List>;

The library suggestion works decently well for individual tags. Though i’m not sure why you’d want individual treatment if mechanics are the same. If the differences lie in the movement script, then all the individual treatment should happen through movement script anyway (which can have it’s own self-constructing data structure).

The inspector thing is a more interesting issue. Static accessors don’t work too well if you want to change them on the fly in the inspector.
I am getting around this particular issue by having a singleton class that stores everything i want to be able to change in the inspector. That way, there is one instance of a class that’s directly associated with the type through a static reference, and then all the variables can be accessed through that instance. Works like this:

public class SingletonWithInspectorVars : MonoBehaviour {
	public bool SHOW_PATHING = true; // boolean to show/hide some stuff
	public float PATH_HEIGHT = 0; // parameter to change on the fly through inspector
        public Mob playerCharacter; // player char to change on the fly through inspector

	private static SingletonWithInspectorVars i; // static instance reference ...
	public void Awake() {
		i = this; // ... initialised
	}
}

public class USP_SomethingDoer {
	public void DoSomething {
		SingletonWithInspectorVars.i.playerCharacter.DoSomething(); // calls nonstatic playerCharacter through static instance reference
	}
}

This is a barebone singleton implenetation. In practice, you’ll need to make sure singleton instance and player characters are never null.