0
\$\begingroup\$

I'm in the middle of writing a platformer game in Unity using C#. I have my character, if he presses the kick button his state switches to kicking. During this "kicking" state the character doesn't actually do anything, he only publicly exposes the kicking information such as kickForce etc.

The enemies however have a check in their update functions for the players isKicking value, if he is and the enemy lies within the range for being kicked by the player then the enemy has forces applied to itself and such. All this works fine but I've been thinking about future implementation of different enemy types, if I want to implement other types of enemies that do not behave the same this same script will not work.

To me this is inintutive, part of me thinks that the kicking behavior should be in the player class, he should retrieve all enemies within the area of kicking and run them through some sort of KickObject method. However this is my very issue, I am unsure of what the cleanest and most straightforward (and easily extendable) way of doing this is. I have this problem in general when it comes to implementing the structure of the game, i don't know the best answer and I feel that often when I am planning things they get much more complicated than I had originally planned for down the line and the structure i had in place starts to fall apart.

Any advice on this matter would be greatly appreciated.

TL:DR - For kicking enemies, should the behaviour be applied by the player or is the method of every enemy having its own "be kicked" code the better way to do this. General game development code structure questions.

\$\endgroup\$
3
  • \$\begingroup\$ You could have enemies listen for a playerKickes event and on each enemy's code ads a response for that. All of them then can listen for the event but they can react differently with different code. \$\endgroup\$
    – rlam12
    Commented Jun 28, 2016 at 22:00
  • \$\begingroup\$ You should read about C# Delegates and Events - The basic idea is that your player decides when a method that's part of the enemies will be run. And the cool part is that player doesn't know what that method is. But still IMO that not the best approach here. \$\endgroup\$
    – Nikaas
    Commented Jun 29, 2016 at 21:33
  • 1
    \$\begingroup\$ Don't forget also that you can attempt to define a common interface used by all appropriate enemies. You could do so either with an interface or by using a base class. \$\endgroup\$
    – zcabjro
    Commented Jun 30, 2016 at 7:50

2 Answers 2

2
\$\begingroup\$

Why not use colliders and tags. When an enemy trigger/collider detects a player trigger/collider tagged say "Player kick" (child game object of the player) then that enemy executes his reaction with OnTriggerEnter(2D)/OnCollisionEnter(2D). Player just needs to enable and then disable its kick game object when kick is pressed.

The most important thing is that each object should only be responsible for his own actions/behavior. Player should only care to kick and nothing else. Enemies should only execute the consequences of being kicked.

\$\endgroup\$
0
\$\begingroup\$

The way I would handle this sort of scenario is to use some form of event messaging system. Each entity in your game world(and possibly the game world itself) should have the ability to send and receive messages.

A simple way to set this up would be to have a MessageTypeEnum that signals which type of message is being sent and then some way of sending the rest of the event data(i.e. use of dynamic to store a struct of data that the receiving entity can convert back to its original type, or through use of inheritance and extending a base message class with derived types for each message etc.).

You can then have a simple EventManager object that other entities can use to register for event types. When an event comes in to the manager it can then be dispatched off to the receiver method for each registered entity.

The main advantages of the above is that it is easily extendable and the sender object doesn't really care who the message is intended for. It just fires and forgets. This results in far less coupling in the code. It also allows for each entity to react differently if needs be to each message type.

For instance an EnemyDied message might result in the player handling it by adding some value to a score and the game world might handle it by removing the enemy from its update list.

\$\endgroup\$
6
  • \$\begingroup\$ I like this answer, But if for example, the kick can only affect a single enemy, you would run into problems, strictly out of an academic interest, how would you solve that using an event driven approach? you could argue that a kicked enemy can dispatch a "gotKicked" event with the kickID (to make sure it's not used again), but wouldn't that expose a race condition of sorts? \$\endgroup\$
    – Patrick
    Commented Jun 30, 2016 at 9:59
  • \$\begingroup\$ Good question. I would have a thread safe method on the derived kick event class to set the event as a one-off i.e. the first entity to receive it uses it up. and after that any other entity who receives the event cannot do anything with it. Of course this could be extended further to ensure that for instance the entity who tries to process the event first is within hitting distance of the players kick etc. \$\endgroup\$ Commented Jun 30, 2016 at 10:28
  • \$\begingroup\$ I'm new to coding and game-dev but I still think this approach is not the best when very small and variable number of all recipients will actually be interested in the event. I think that 1. "sender" should determine the "recipients" (tighter coupling) or 2 "recipients" on their own decide if they are interested in "listening" based on certain conditions (redundant checks). Actually thinking about it: events can work if receivers have a way to additionally check and determine if the just received event is truly intended for them. \$\endgroup\$
    – Nikaas
    Commented Jun 30, 2016 at 14:39
  • \$\begingroup\$ @Nikaas I think you missed the part where I mentioned the event manager where entities register for the event types they are interested in. This covers option 2. Tight coupling is never a good thing. \$\endgroup\$ Commented Jun 30, 2016 at 14:57
  • \$\begingroup\$ I mean if player kicks and each and every enemy is interested in being kicked but only 3 enemies fall into its kick? Each time different amount and instances of "enemy" are withing range. \$\endgroup\$
    – Nikaas
    Commented Jun 30, 2016 at 15:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .