Best practice for getting references to gameobjects?

Hi,

I have currently a hybrid game, where most of the game is written in dots, but the ui is still using the old monobehaviours.

The problem i have with this is that sometimes i have quite some heavy logic inside the monobehaviours which is “timing” dependent. If i would move this code to systems it would make ordering much easier.

Now the problem is that i need to have references to UI elements for example.

Currently iam using Gameobject.find in OnStartRunning(), but this is not the way to go for me tbh…

on top of my head i would saythat i have a single authoring tool, which creates entites and i attach the specific ui class element to it. Then i can use getsingleton to get the reference …

any other solutions?

I typically have a MonoBehaviour that has public entry points for the systems to call into, and then have a ConvertToEntity with ConvertAndInjectGameObject on the same GameObject. While this does invoke runtime conversion, it is cheap enough for the handful of GameObjects that need runtime conversion (the main camera being another one).

If you prefer to do couple things in the other direction, you could also have your UI components fetch the system reference from the default world and subscribe to events on the system during Awake(). Then you could invoke those events from the system.

4 Likes

This works so well, thank you! :slight_smile:

For others:

  1. ) Create monobehaviour
  2. ) Add the stuff you want to reference as a public field
  3. ) assign values via drag and drop in the unity inspector
  4. ) add convert to entity script with inject mode
  5. ) add the following script somewhere so you have it on your entity manager:
 public static T GetClassSingleton<T>(this EntityManager entityManager)
    {
      var entity = entityManager
        .CreateEntityQuery(typeof(T))
        .GetSingletonEntity();

      return entityManager.GetComponentObject<T>(entity);
    }
  1. Win:
var gameObjectManager = EntityManager.GetClassSingleton<GameObjectManager>();

      _ingameGroup = gameObjectManager.IngameUiGroup;
4 Likes

Another question:

is there a way to delay the system creation?

I do the lookup in OnStart(), but the lookup object doesnt exist at that point, since the object conversion happens sometimes later, so i resort to OnStartRunning().

its not a huge problem but i feels better to do the lookup a single time instead when the systems start running

Yes, there is, but I would highly discourage taking that route. If you decide in the future to have multiple scenes, you will still run into the problem. Systems be default have a longer lifecycle than your GameObjectManager, and so you should query for it every OnUpdate(). That shouldn’t be a performance issue.

My game structure is complete, no new scenes are coming.

I would really like to delay the system creation until my “manager” object got instantiated and converted correctly.

Can you give me a short rundown how i would do this?

It involves disabling the automatic world generation (or perhaps just the system in question) and then setting it up manually yourself. I’m the wrong person to walk you through this though as I believe it to be bad practice. Is it really that big of a deal to query for the hybrid component in OnUpdate()?

Iam not using onUpdate for most of my game “state” logic. I use OnStartRunning and OnStopRunnign in combination with singleton entities, to trigger specific state transitions.

the problem is that my system is triggered in the “middle” of the game and when it first starts up,there happens to be a big lagg as all the gameobjects need to be converted to entities.

Yes i could run this system somehow earlier, but this would be a littl bit hacky and clunky.

If i delay the system creation, i can just have every “object setup” be done in OnStart(), which will happen in the beginning of the game (or in a loading screen for example)