G
G
Georgy Pelageikin2015-08-09 17:50:28
C++ / C#
Georgy Pelageikin, 2015-08-09 17:50:28

How to enforce strict order of event subscription?

I am developing a game in Unity. The logic is quite voluminous, so it turned out to be very convenient to use events (events). And while unrelated events should be performed - for example, the start of the move and fixing the camera on the player, everything is fine: in the corresponding scripts, we subscribe to the event, everything is beautiful and convenient.
And here is another situation: the player clicks on the part of the ship, you must first call the method that finds out which part the player clicked on, and only after thatseveral scripts should show information about this part. Naturally, if called in the reverse order, an error will be thrown. Problem: scripts subscribe in Awake() or OnEnable() - when the scene is loaded. And you never know whose OnEnable() will be called first. What are the options for solving the problem? I see the following:
1) Do two different events - one for processing a click, the second for the rest, called at the end of the first. In some cases, I did just that.
2) Subscribe all methods in one place. Those. in the first script, in addition to its method, sign the rest - you get an ugly sheet, the OOP is horrified. I've only used this once and I'm trying to get away from it completely. Here, enjoy:

spoiler
using System.Collections;
using UnityEngine;

public class EventController_script : MonoBehaviour       //Только методы, которые должны подписываться в строгом порядке
{
  public EventContainer_class events;
  public Trajectory_script trajectoryScript;
  public TrajectoryGUI_script trajectoryGUIScript;
  public PlayerMov_script playerMovScript;
  public DateGUI_script dateGUIScript;
  public CamMov_script camMovScript;

  void OnEnable()
  {
    events = GetComponent<EventContainer_class>();

    EventContainer_class.OnTrajectoryCall_event += events.CallOnTrajectoryCleanEvent;
    EventContainer_class.OnTrajectoryCall_event += trajectoryScript.CalculateTrajectory;
    EventContainer_class.OnTrajectoryCall_event += trajectoryGUIScript.DrawTrajectory;

    EventContainer_class.OnTrajectoryClean_event += trajectoryGUIScript.CleanTrajectory;

    EventContainer_class.OnTurnStart_event += WorldState_class.StartTurn;
    EventContainer_class.OnTurnStart_event += dateGUIScript.UpdateDateBar;
    EventContainer_class.OnTurnStart_event += events.CallOnTrajectoryCleanEvent;
    EventContainer_class.OnTurnStart_event += events.CallOnCamReturnEvent;

    EventContainer_class.OnTurnEnd_event += WorldState_class.StopTurn;

    EventContainer_class.OnLand_event += WorldState_class.StopTurn;
    EventContainer_class.OnLand_event += SceneSwitch_class.Land;

    EventContainer_class.OnJump_event += WorldState_class.StopTurn;
    EventContainer_class.OnJump_event += SceneSwitch_class.Jump;
  }

  void OnDisable()
  {
    events = GetComponent<EventContainer_class>();

    EventContainer_class.OnTrajectoryCall_event -= events.CallOnTrajectoryCleanEvent;
    EventContainer_class.OnTrajectoryCall_event -= trajectoryScript.CalculateTrajectory;
    EventContainer_class.OnTrajectoryCall_event -= trajectoryGUIScript.DrawTrajectory;

    EventContainer_class.OnTrajectoryClean_event -= trajectoryGUIScript.CleanTrajectory;

    EventContainer_class.OnTurnStart_event -= WorldState_class.StartTurn;
    EventContainer_class.OnTurnStart_event -= dateGUIScript.UpdateDateBar;
    EventContainer_class.OnTurnStart_event -= events.CallOnTrajectoryCleanEvent;
    EventContainer_class.OnTurnStart_event -= events.CallOnCamReturnEvent;

    EventContainer_class.OnTurnEnd_event -= WorldState_class.StopTurn;

    EventContainer_class.OnLand_event -= WorldState_class.StopTurn;
    EventContainer_class.OnLand_event -= SceneSwitch_class.Land;

    EventContainer_class.OnJump_event -= WorldState_class.StopTurn;
    EventContainer_class.OnJump_event -= SceneSwitch_class.Jump;
  }
}

And this method works only for those methods that must be signed once and exist in a single instance. In general, this is not a solution.
3) What are your options?
Still I have such question arose: where to declare events? So far, I have a separate singleton class for this, which suits me in principle, but it’s interesting how such things are done in normal projects.
PS correction. OnEnable(), Awake() and others are called in the order of the game object hierarchy - the parent method is called first. Tested - it seems really so. But here are the subscribers - are they exactly called in the subscription order? Although I read in some article that yes, but nonetheless. And what if the objects are not in each other's hierarchy or their hierarchy is not known in advance?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
E
Espleth, 2015-08-09
@ArXen42

The player clicks the mouse. A raycast or something like that is sent. This raycast hits the Collider. We take GetComponent<ShipPart>(or whatever it is called) from our Collider and call our event with the received ShipPart. I don't understand what is the problem?

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question