0

So I am working on a game which has both single Player as well as multiplayer functionality in it. On one hand I have a bird script which should function differently on the basis as to whether it is a single player game or a mutli-player game. But I simply can't understand why my event listener is not working as such.

So for the Single Player game I have a script called GameController attached to a gameObject called GameController. In the Start function of it I am firing an event saying that it is a single player. Below is the relevant code:

public class GameController : MonoBehaviour
{

public static Action isSinglePlayer = delegate { };

 void Start()
    {
        isSinglePlayer?.Invoke();
    }
}

So in the Bird Pigeon class I have the listener and the relevant code is like this :

public class BirdPigeon : MonoBehaviour
{
    public void Awake()
    {
        PV = GetComponent<PhotonView>();
        BattleRandomController.BirdDirectionTransfer+=BirdDirectionMultiPlayer;
        GameController.isSinglePlayer += SinglePlayer;
        BattleRandomController.isMultiPlayer+=MultiPlayer;        
    }

 void Start()
    {     
       if (isMultiPlayerGame)
        {
            if (PV.IsMine)
                IndicatorForMe.SetActive(true);
            else
                IndicatorForMe.SetActive(false);
        }

     }

  public void SinglePlayer()
    {
        Debug.Log("isSinglePlayer function is executed................");
        isMultiPlayerGame = false;
        IndicatorForMe.SetActive(false);
    }
private void MultiPlayer()
    {
        Debug.Log("MultiPlayer function is executed");
        isMultiPlayerGame = true;
        IndicatorForMe.SetActive(true);
    }
}

But when I run the code the Debug.log statement "isSinglePlayer function is executed................" doesn't get executed at all.

Similarly for the multiplayer game scene I have a gameObject called Battle Random controller attached to game object of the same name and in the Start function of that I am firing an event to indicate it is a multiplayer and still the above listener for that which is Multiplayer, the debug.log statement doesnt get executed only i.e.,"MultiPlayer function is executed"

The Relevant code for the multiplayer scene is as follows:

public class BattleRandomController : MonoBehaviour
{
 public static Action isMultiPlayer=delegate{};
 void Start()
    {
       isMultiPlayer?.Invoke();
     }
}

Earlier I had fired the event in the Awake and was listening in the Start of the bird pigeon class which somewhere I read was wrong. Now there is a listener ready in the awake function of the BirdPigeon class but I can't understand as to why the listener is not functioning .

6
  • 1
    You're assiging your Action to an empty delegate {} which is what get's executed. If you want it to be BirdPidgeon.SinglePlayer() then you need A) an instance of BirdPidgeon and B) assing the SinglePlayer method of the instance to the Action property but that would be an awful code. Commented Jun 7, 2022 at 8:56
  • @PabloRecalde would you mind explaining that with a code or be a little more elaborate on what you told Commented Jun 7, 2022 at 9:06
  • What I mean is that you're not liking those two pieces of code anyhow. Commented Jun 7, 2022 at 9:07
  • public static Action isMultiPlayer=delegate{} this is an empty anonymous method, so no matter how many times you call it, it will do nothing. delegate {} is an empty anonymous method. Commented Jun 7, 2022 at 9:08
  • @PabloRecalde I have tried this same signature for my other events such as Game Over and getting Playfab friends and it has worked Commented Jun 7, 2022 at 9:38

2 Answers 2

1

The correct way to declare an event would be like

public event EventHandler MyEvent;

and raise it like

MyEvent?.Invoke(this, EventArgs.Empty)

You could use an arbitrary delegate in place of EventHandler or EventHandler<T>, but the most code I have seen uses EventHandler for events.

Note that you are using a static event, and there are several issues with such events. It may make thread safety more difficult, and can easily create memory leaks if you are not very through with unsubscribing. The singleton pattern might be an improvement, but I would recommend such singletons to only be global within some "context", and not for the entire application, that can make it easier to cleanly dispose of that context.

There is also the issue of timing, if you subscribe after raising the event you will obviously not get it. Easiest way to confirm this is by debugging. Add a breakpoint where you raise the event, and check that it is not null, that should also allow you to see if any breakpoints inside your event handler is hit.

Also, using events to determine the type of game seem fragile to me. You should ideally have some abstraction layer to isolate any multiplayer specific parts.

Sign up to request clarification or add additional context in comments.

7 Comments

I mean even my way of using Action , which is nothing but an event which is void , is nothing wrong. Even yours is correct, no doubt about that. For some other places such as GameOver, passing Playfab friend , coillisions it works fine with Actions , but here I can't understand whats the issue all about.
@chethanv77777 could be that you raise the event before subscribing to it. I would recommend some debugging to see what is going on.
@chethanv77777 also, there are some rules with regards to multicast delegates. I don't have them memorized, but I know using the event keyword works fine. I would not use your syntax without reading the language specification to confirm that it does what you intend it to do.
"you are using a static event...and can easily create memory leaks" - its a problem regardless of instance vs static but anything that is a CLR host can easily destroy statics, something that Unity does anyway. Using EventHandlers and straight-up delegates can lead to memory leaks because of their heavy-weight references as explained here and here respectively so they're generally a hot potato. They're not recommended for use in gaming for this reason.
"....you are using a static event...It may make thread safety more difficult..." - pretty sure that applies to anything that doesn't have any form of thread-safety in the form of locking around it. So I don't know if you know Unity but Unity MonoBehaviours run in Unity's Main Thread - think the main GUI thread in desktop apps such as WinForms/WPF. "There is also the issue of timing" - as above, N/A in this discussion. When it could be a problem as in Unity's built-in async I/O, Unity does a good job of performing thread marshalling.
|
-1

maybe you should try to replace your action by this :

public class GameController : MonoBehaviour
{

public event Action isSinglePlayer;

 void Start()
    {
        isSinglePlayer?.Invoke();
    }
}

1 Comment

I tried but it didnt work

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.