0
\$\begingroup\$

As I'm developing our game I have asked myself a couple times "When we have more than 1 player, how will I ensure events from player A do not crossover to player B?"

As an example, lets say player A clicks on a unit. This publishes an event with data on the click location, the type of object it is, and the player that clicked. This can be received by lets say a selection manager script that just keeps track of what is currently selected for that player.

The problem now, is that this event is received by every player. Every player will receive this event and try and select that object, and perform various tasks along the way.

Is there a method of programming in unity to ensure that an event is only subscribed to by classes that have the same player component referenced (only the appropriate players methods will be added to the invocation list of delegates under the player)? Or will I just need to create a check at the subscribers to these events to only accept the event data if it's the same player?

ie.

if ( RClickEventArgs.Player.GetInstanceID() == player.GetInstanceID()) {}

Edit: For clarity. Here is an example event.

public delegate void RightClickHandler(string clickType, RClickEventArgs e);
public static event RightClickHandler RightClickEvent;
private void RightClick()
{
    if(Input.GetMouseButtonDown(1))
    {
        if (userInput.isMouseOnScreen && !EventSystem.current.IsPointerOverGameObject())
        {
            GameObject hitObject = inputValidations.FindHitObject();
            Vector3 hitPoint = inputValidations.FindHitPoint();
            hitPoint.z = -1;

            if (hitObject && hitPoint != ResourceManager.InvalidPosition && hitObject.name != "Ground")
            {
                RightClickEvent("Object", new RClickEventArgs(hitObject, hitPoint, player));
            }
            else if (hitObject.name == "Ground")
            {
                RightClickEvent("Ground", new RClickEventArgs(hitPoint, player));
            }
        }
    }
}

When an object is clicked an event is published with relevant info on what was clicked. There are subscribers to this event using "MouseClickEvents += YourMethodNameHere;". This works as intended. However, since two players will have the same scripts as components this creates an issue where the 2nd player's scripts also add themselves to the invocation list of player 1's delegates, and vice versa (as far as I know, I don't know how to check what is in the invocation lists). So each player receives their own events, and the events of the other player.

If I have a fundamental misunderstanding of a concept here, please let me know.

\$\endgroup\$
1
\$\begingroup\$

I don't what your code architecture looks like, but you will have to make this check at some point.

The simplest way to do this, imho, is to be sure that the local player only receive his own events, so, be sure to make him register to only his event.

You say that, at click, you know who has clicked. Why don't you just send the event to this specific player. If the, let's say, click_event object contains a player object, you just have to use it to only warn the specific player.

click_event.player.OnClickEvent(click_event);

EDIT

After your edit, it's now clearer.

You will have to check the sender in your callback method. Note that you often want to actually "display" other players actions. In RTS you sometimes want to show who is selecting what or who is clicking on what, even if you don't want to call the action code, only the UI code.

So if OnRightClickEvent has subscribed to RightClickEvent you would have something like :

void OnRightClickEvent(GameObject hit_obj, Player player)
{ 
   // SHOW ACTION UI
   // ... like mouse movement and click on the hit_obj ...
   // ... show hit_obj UI FX ...

   // HANDLE CLICK CODE ONLY FOR THE GOOD PLAYER
   if ( player == local_player )
   {
       // ... do what you want to do ...
   }
 }
\$\endgroup\$
  • \$\begingroup\$ I am not quite understanding your answer, I edited the question to add more clarity. I can't send the event to a specific class/method, the event itself does not "know" about those classes, rather those methods subscribe themselves to the event. The event is published without caring who is subscribed, and any subscribers to that event are called. Issue is, I do not know how to to limit the subscribers based on their components and/or instances of those components. aka only allow methods in classes with xxx ID to add themselves to the delegates invocation list. \$\endgroup\$ – Douglas Gaskell Feb 25 '15 at 23:19
  • \$\begingroup\$ You can also make a bunch of delegates (bad idea), one for every players and players only register to their own. Then, according to the sender you throw the right delegate. Once again, this is a bad idea. \$\endgroup\$ – lvictorino Feb 26 '15 at 8:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.