Using GameMode for "global"events

Hello!

I’m quite new to Unreal and I’ve been really excited about it so far. I have some very basic understanding about blueprints, c++ and games in general. My question is the following:

I was thinking about using GameMode to store some sort of event emitter that I can use to notify relevant entities in my level (not necessarily actors) that something happened.

A good example would be my quest system: I designed my quest objectives as simple UObjects as there’s no need for them to be actors, but I wanted each quest objective to subscribe to their topic of interest, for example an enemy killed or an item added to inventory. The flow would be:

  • I create an event emitter in GameMode
  • Quest initializes
  • objetive subscribes to enemy killed event
  • Enemy dies → notify my event emitter
  • Quest objective updates

Would that be a good approach? Or would there be a more recommended place to emit that sort of events? One of the reasons I’m tempted to use GameMode is that I believe have access to it even from non-actor classes.

Hi.

It could be done, well, anything can be done anywhere, especially when the scope of your game is small. However it wouldn’t be the ideal place, here is why with some items:

  1. Being able to access it anywhere doesn’t mean much and the act itself is dangerous on Blueprinting. You will get the game mode anywhere, you will cast it anywhere and the moment your game has Game Modes of different class, your objects will carry the references of your gamemode to other gamemodes and suddenly, you will have all your blueprints loaded all the time on all game modes. You can still access anything by holding a reference to one object.

  2. GameMode’s intended use is to handle Player Spawning, rounds etc. However a quest system is relevant only for a player. Again, if your game would be single player, that could get a pass, but on a multiplayer game, you would have a mess in your hands.

  3. The ideal place would be to have it on your Player State if you have a minor interest in going the multiplayer way. While the quest themselves might be UObject, they also can be instanced (Multiple people can be on the same quest at the same time).

  • Player accepts quest
  • A quest and quest objective instances get created on the PlayerState
  • Quest objectives hook to relevant Player events (EnemyKilled, ConversationCompleted, ArrivedToLocation)
  • Objectives dispatch OnCompleted event to Quest.
  • Quest gets completed and rewards the player.

And to avoid being able to complete the same quest over and over, you can hold the completed quest ID’s in your Player State. It also makes it easier for you to be able to save an individual player’s state rather than saving the GameMode once or its properties selectively.

Thanks for the response @Naocan !

My game will be single player, but I would still like to do things in the recommended way. Your recommendation above makes sense to me, but there are just a few things that are not clear (as I haven’t used PlayerState before). Is there a way for me to have access to player state inside the quest objectives, or is your suggestion to pass it to them as they are instantiated when player accepts the quest?

It would be the latter, you can either keep a reference to the PlayerState in your Quest class, or have it a Function/Event that receives the PlayerState as a parameter and you can directly hook-up your events that way. Regardless of the method, PlayerState being passed to it via a function will always be more elegant, given you won’t have to use rerouted accessors like “GetGameMode” and/or trying to figure out what PlayerState (via Index) the quest is responsible for.

To access the PlayerState, you can use the following: GetPlayerController()->GetPlayerState() (They do exist in BP’s too) or you can GetGameState()->GetPlayetStates() (Not 100% sure about this one). Earlier will be better since you can access the PlayerController much easier via pawn using GetController()->CastToPlayerController().

Agreed. I will try that! I’ve been a (non-game) developer for quite a while and learned all sorts of good practices but I’m struggling a little bit to adjust them to the Unreal way of doing things, so I appreciate the help!