C# Unity:use of dynamic for a message/event system

Viewed 311

I was trying to create a system so that I could have a multitude of Game Objects call a method in a singular Game Object which would serve as a game controller. The object would take in either a String or a Int value to distinct what exactly the event was, and then using that: run a specific section of code which could, or could not require arguments of different types. I was wondering if using dynamic as the argument type for any auxiliary arguments would be a good idea or not. And if not then what I should do instead to get the same effect. some example code which would in theory use my method:

public void Message(String msg, dynamic arg0, dynamic arg1,
                    dynamic arg2, dynamic arg3){
    switch(msg){
        case "point score":
            // arg0 is number of points scored
            scorboard.addpoint(arg0);
            ResetMatch();
        break;
        etc...
    }
}

I could also change from using dynamic arguments to using a dynamic list. I am also aware that this system is not necessary however I feel it would add a lot of freedom and if there is a similar enough system that could accomplish the same result please do tell. Thank you

2 Answers

Oh god no don't do it like that... C# is an object oriented language, which means you don't need to use massive switch/if-else statements to handle stuff like this - you can encapsulate it in objects

public void Handle(ICommand command){
    var context = new Context(some data from this controller);
    command.Execute(context);
}

public interface ICommand {
    Result Exectute(Context context);
}

public class AddToScoreboardCommand : ICommand {

    private readonly int _points;

    public AddToScoreboardCommand(int points){
        _points = points;
    }

    Result Execute(Context context){
        context.Scoreboard.Add(_points);
    }
}

Then your components can do:

var command = new AddToScoreboardCommand(pointsToAdd);
YourController.Handle(command);

Then to add a new command you just need to create a new ICommand object - you don't need to go edit your big switch statement, or worry about which arguments it needs

I agree with Milney, but I'll take a different approach to explaining why this is not a good idea and what would be a good alternative.

C# is indeed an object oriented language, which means that objects are often passing information between each other. This replaces the more primitive messaging system you are describing.

Generally, we want to have a class for each thing we want to do, and that class should only do that thing. This principle is called Single Responsibility.

So lets say that one subsystem of your game is the point scoring system. We could write a class like this: Lets assume you have a player class defined.

public class ScoreKeeper : MonoBehavior
    {
        public int player1Score = 0;
        public int player2Score = 0;

        public Player p1;
        public Player p2;

        public void PointsScored(Player p, int amount)
        {
            if (p == p1)//if the player who scored (p) is the same object as player 1 (p1)
            {
                player1Score += amount;
            }
            else
            {
                player2Score += amount;
            }

        }
    }

This is a component that you can add to your main gameObject (I usually call mine GameMaster of something). If your game had other subsystems, you could also create another class and add it to the game master.

So to use the example class I wrote, lets say player 1 scores 3 points, you would call the PointsScored method with arguments of player1 and 3. Of course, depending how you setup your project, you may have to find the ScoreKeeper object first.

The main difference between this approach and your messaging approach is that this allows you to write classes that perform specific tasks, and then call those specific tasks. Another idea we often talk about in OOP is encapsulation, which is basically the idea that each object should only have access to the information it needs and nothing else. So our score keeping class doens't know anything about the power upgrades class of the experience tracker class.

Related