Hi, in honor to the good old LucasArts adventure games like “Monkey Island” or “ZakMcKracken”, the first chapter of my “Ingoverse” will be a point-and-click scene like those classics above, but still in 3D. I got about 60 interactable objects in the scene and 15 action-buttons to interact with them. Already makes a total of 900 possibilities. Most of them just result in a text above the player’s head, but some interact with other objects, depending on their actual state. Like “Use DVD with DVD player → has player got DVD? → Is DVD player on’ → is TV switched on?”…
Since every object has to react different from the others, I created a cascade of branches checking all those 15 possibilities one after the other, what results in huge blueprint code only for one object.
There must be a better way to handle this, maybe using arrays, structures and such. I already watched some inverntory-tutorials, the one from Titanic Games I’ll choose when the player is back to “real 3D”, but all of those didn’t really match to my game. Maybe someone here can point me to the right direction or maybe my code is just fine as it is and I have to blow up my Level Bueprint further.
Here’s a video describing what I’m talking about. I create the game in my native language to get the best out of my fantasy, but I’ll add an english version as soon as chapter one is done.
Hi Morhol, the game has a nice look
I never had to handle with this kind of problem, but here are some ideas (maybe they dont help at all)
You got states, like TV is on/off or DVD is/isnt in inventory. I would save those states global in the Gameinstance.
global, because every interactable object is a Blueprint Actor, that has events, which handle the 15 action-Buttons (maybe 14, because “go-to” is more a navigation thing…). So the events can check for the states in the Gameinstance and react specific on those states.
This way you can reuse (copy-paste) events inevery Blueprint Actor like “talk-to”, that clearly isnt usable for objects…
To let the DVD-Player react with the DVD, you can also work with a state (“Object in hand”)and string of the object and maybe have an event in the DVD-Player BP Actor with a switch that reacts on different object-strings (or better IDs).
As said, just some ideas. Maybe you can also take a look at Blueprint Interfaces.
You create one or more places that contain booleans for states of the game that need to be known by more than one object. Where you put those booleans depends a bit on the design of your game. If you only had one level (room) as described above, GameInstance would work fine for all of them. It is global and easy enough to find when you need to check a boolean state variable (bIsLightOn, bIsDvdPlayerPossessed etc). If you have more than one level then you might want to put the boolean state variables that do NOT carry over from level to level in GameMode and then each level can have its own unique version of GameMode. The boolean state variables that DO carry over from level to level (like inventory) can be in GameInstance or in the Character
The Character’s job is to execute the"Move To" command and then, having moved to an object, which is then the object “in focus”, interact with that object. This is where the BluePrintInterface comes into play. You make a standard way of interacting with any object, for example you create an interface called “Interact” and send with that interaction an input that indicates the type of interaction based on one of the 14 buttons (other than Move To) that was pressed. This means the input to “Interact” would be the object you interacted with (an object that would implement the interface) and a message variable
Each button, when selected, would provide the contents for the message variable as an output so that the interface could pass it to the object being interacted with.
Each object then implements that interface by reading the message, checking boolean state variables stored by itself, those stored in GameInstance and/or those stored in GameMode or the Character and then decide what to do (including changing any state variables that it owns that are stored in those locations).
The main benefit of this approach is that you don’t have to centrally figure out with a giant “if” structure which commands to call, the basic flow is (loosely in pseudocode):
Character::MoveTo Command determines which object is “in focus”
Button::Message variable provides a message as to which interaction button was pressed
Character calls InFocusObject->Interact(Message) to send the message to the Object In Focus. This identical call would be made to any in-focused object, all of the inputs are variables (InFocusObject, Message) so one line of code (in the blueprint sense of the word “line”) does it all for any object. As written, the code doesn’t “know” which object is in focus until the program is actually running.
Each object receives the message, checks boolean state variables and decides what to do including perhaps doing nothing.
If all that happens is a message needs to be flashed over the character, you can have a similar “message” strategy where the object being interacted with fires a “display message” event at the character and sends the message to display.
Thanks for your suggestions so far! I’ll take a deeper look into Blueprint Interfaces to be able to implement the written above, that should lead me to the proper way handling this. Future plan is that this appartment shall be the player’s home, to which he always returns after completing chapters. After having solved all puzzles to open the main door, pixel-mode will switch off and you return to the original 3D including usual third person movement. So I guess I’ll store most of the variables in GameInstance, and only the inventory-object related ones in my character. Opening the door will lead you to another level/gamemode as well as using the notebook, that will contain another level/(mini-)game.
I finally got it! One the one hand I build a MasterObject containing all needed variables like “CanTurnOn?” or “LookAtText” and create my 60 individual children from that. On the other hand I found a simple way to determine which action-button (Open, Close, Push, …) had been pressed. I already got a string-variable containing this action-verb to display it in the infoline on screen. So I use a “SwitchonString” in my MasterObject to add the actions.