UI Object & Class data, Mutual referencing is only way?

Normally UI, from there user control various datas like equipped things, items, etc.

So for make this, I usually make both (UI gameobject & class data) get referencing each other.

----(from UI side) (name : EachUIScript.cs)
public SomeClass ThisClass;

----(from class side) (name : SomeClass)
public EachUIScript UIScript;

and when UI object instantiated, I connect each other.

so make it happen that, for controlling & manipulating class data, when user control UI.

But Is this right way?
Am I missing something?

If you use events then you only need a one-way reference. For example:

Player has HP event triggered when HP changes. UI health bar references player to listen to HP event. Only one way reference from UI element to player object is required.

Same principle can be used for inventory etc…

1 Like

In the ideal system: your main classes don’t know anything about the UI. They provide all the hooks necessary for the UI to manipulate them, but if you nuke your entire UI code, you should not get any compiler errors. This way, you can replace the UI with other systems (a different UI for a console, keyboard/mouse, or touchscreen, a network-contrlled player maybe, or an AI-controlled character, to name a few).

So in this ideal system, it’s easy to see how, say, your UI can display your player’s health, or tell your player to jump: the UI does have a reference to PlayerObject, and can manipulate it as it sees fit. The remaining question is, what about when the PlayerObject needs to tell the UI something, like say you want the lifebar to flash because the player just got hit. Without PlayerObject having a reference to the UI, how do you send that message?

Delegates and events to the rescue! A delegate is basically a reference to a function itself, which can be invoked freely even if you don’t necessarily know what the function even is.

So basically you’ll have something like this:

public class PlayerObject : MonoBehaviour {
public event System.Action<float> ActionOnReceiveDamage;

....
void OnCollisionEnter(Collision c) {
if (blah blah have taken damage) {
ActionOnReceiveDamage?.Invoke(damageAmount);
}
}

To break this down:

  • System.Action is a kind of builtin delegate. You can define your own delegates fairly easily, but I often find it helpful to just use System.Action most of the time. I usually only define my own delegate if I need the delegate to return something, which Action doesn’t support.
  • The event keyword on it means that the action may have 0, 1, or more listeners. (Non-event actions may only have 1 listener, which sometimes is preferred, especially for delegates with return types.)
  • The ?.Invoke syntax means that if the event is null it won’t cause an exception.

Now on the UI side, you’ll do something like:

public class PlayerUI : MonoBehaviour {
public PlayerObject myPlayer; //assign this however you like

void Awake() {
myPlayer.ActionOnReceiveDamage += RespondToPlayerDamage; //note: NO parameters/parentheses in this line
}

private void RespondToPlayerDamage(float dmg) {
Debug.Log($"We've received {dmg} damage.");
}
}

Notes on this one:

  • The += on the line in Awake means the function is being added to the event’s listeners. You can use -= if you want to stop listening. If the delegate wasn’t an event, we’d just be using =
  • The RespondToPlayerDamage function must exactly match the method signature (e.g. return and parameter types) of the delegate. Action is always void Something(foo).

I sort of threw a lot of info at you here, let me know if there’s too much or if I skipped something. There’s definitely more to learn about delegates that couldn’t fit onto a forum post.

1 Like

Thx but… as you can see in this video,
https://vimeo.com/436458954

User normally manipulate equipment through UI.

At above video, user control and manage equipment’s decoration (which can be equipped to equipment’s empty slots)

through many decoration represented UI buttons.

So game should know now what button user pressed, and what decoration info (decoration class) that UI button had.

And when changing equipment’s decoration, first user click what decoration already equipped, and then click what decoration he want to change to.

Then game should know both info stored.

Can these also be implemented via event system?