Is it OK to use public accessers for unique gameobjects (C#) ?

Let’s say I have several game objects that are unique in my game, and that will always be present. For example the main character.

Its behaviour is implemented in a C# script, deriving from MonoBehaviour. Imagine now that it has some components like particle systems, line renderers or whatever attached to it as gameobject childs.

One way of accessing the main character’s particle systems from another script is to do something like

GameObject.Find("My character").GetComponentsInChildren<ParticleSystem>()

It works, but I would like to know if it is a better solution to have (static if needed in some cases) public accessers or properties to do this kind of access. For example, storing the particle systems in an array in the Start() method of the main character and provide access to it by a property.

Without a doubt you should do one of two things:

  1. Look once (‘Find’ & ‘GetComponent’) and store for the rest of the objects life in private variable.
  2. Drag the references by hand before run time to public variables.

Calling ‘Find’ and ‘GetComponent’ every time you need it from scratch can hinder you performance.
Not to mention calling these every frame which can kill your performance like you wouldn’t believe it.

GuyTidhar is completely right, if you can capture the reference of an object and hold that reference, you win. The big thing to remember here and you totally control this, if you destroy anything, the reference(s) are going to be toast and require you to update any references, otherwise you may end up with null reference exceptions all over the place.

private GameObject playerChar;
private List<ParticleSystem> playerPartSys;
private LineRenderer playerLineRenderer;

void Start()
{
  playerChar = GameObject.Find("My Character");

  if(playerChar)
  {
    playerPartSys = new List<ParticleSystem>(playerChar.GetComponentsInChildren<ParticleSystem>());

    playerLineRenderer = playerChar.GetComponent<LineRenderer>();
  }
}

void Update()
{
  // Do stuff with vars
}

How often do you use them?

If it’s for something that happens at most every few frames (explosion, scoring, spawn enemy…) it can be easier to just do a 1-line gameObject-Find. Much easier to track down errors. I have some non-trivial stuff that runs just fine on an iPad which is full of GameObject.Finds (but not in Update.)

If you feel weird about being sloppy, look up “premature optimization.” Common rules are not to speed up code if it runs fast enough already and focus on speeding up the parts that run the most (ex: once per enemy per frame, code in loops.)