To make buttons I have done some complex Blueprints with a lot of logic to achieve some nice effects and playability. In this Youtube video you can see the result:
To make them I made a structure of inheritance similar than the one I have made with lamps, so I have the same lamp features into my buttons: noise, sparks, light, etc. I will not go step by step because my button's Blueprints are very complex but I will explain the general ideas about "Blueprint Interfaces" that let me make the buttons interaction.
WHY I NEED BLUEPRINT INTERFACES?
Now I have a new problem: any button on my game can interactuate with any other object or objects. For example: a button can switch on or off a group of lights in a room, trigger an event like spin one time a rotating door, etc.
Doors and lights are very different objects, and inside both of them could exists a lot of subtypes of doors and lights. Then I need some kind of mechanism to let a button recognize any object in the game and launch its logic.
In the other side we will have a button that the player can push with the game character. A button can be an object that can vary from a simple button to a switch with different meshes, effects, lights, etc. So we need also a mechanism to let the game recognize a button and makes the player character push it when we press the action button on our keyboard, controller, etc.
Here is where a "Blueprint Interface" can help us.
A "Blueprint Interface" its a special type of Blueprint that can't be instantiated and can't have any logic inside, but it must have at least one function declaration. We can define any function that we will need with its data input and outputs.
Then we can apply this "Blueprint Interface" on any other "Blueprint" and this one will have the methods of its interface, then we have to specify the logic to apply for each interface function in this "Blueprint". This lets us make a different behaviour on each "Blueprint" for the same function.
For example: I will make a switch interface that let me execute a function in a game object called "BPI_BooleanSwitchable" to switch on or off a light, a machine, an engine, etc. Inside this interface we have a function called "Switch".
I can use this interface for doors and lights and then a button can cast any of these object into "BPI_BooleanSwitchable" and launch its "Switch" function when the player pushes the button.
HOW I ACTIVATE A BUTTON (or something) IN THE GAME?
First of all I added a new collider to my character to detect interactive objects called "InteractableCollider":
When a object that has the interface BPI_Interactable is inside in the collider then can be activated. So when the player press the action button on his controller and if there is a object inside the interactable collider it tries to cast it into a BPI_Interactable object and launch its logic.
This is the detail of the bject logic of my character Blueprint:
The BPI_Interactable is a Blueprint interface that has the method "Interactuate" to activate a button, take an object or whatever I need to do. If it is a button will trigger other objects logics. Then I use the BPI_Interactable interface to create buttons like my BP_Base_Button.
FROM A BUTTON HOW I ACTIVATE OTHER OBJECTS LOGICS?
Then I need objects that responds to the button but not to the player. For example a machine that starts to work when we activates it. Every button has an array of objects that can be triggered, to recognize them every object will has a BPI_Triggerable interface.
This interface has one method that is useful to activate its objects: the Launch method. When the player push the button then the button cast its activable objects into BPI_Triggerable and then every object executes its own logic.
Here I show the button BP_Base_Button logic. To keep it easy to understand I hide all logic about make sounds, lights, etc and I'm only showing the important part of the button logic:
As you can see at the end I execute a "Launch" function inside the BPI_Triggerable object.
This is a good point to make more complex buttons.
WHAT ABOUT THE SWITCH BUTTON?
The switch button is useful for things that can have two states, for example will be things like lamps or other buttons that can be active or not, doors that can be open or closed, etc. To achieve it I made a BPI_BolleanSwitchable interface wich have the "switch" function.
My switch button is an evolution of my BP_Base_Button blueprint called BP_Base_Switch. It will override the LaunchObjectLogic function thanks to inheritance and instead of BPI_Triggerable objects it will launch BPI_BooleanSwitchable objects. But this is a special button that will host the state of the things that will be active or not so first we need to modify our BP_Base_Button again.
I added a "Update" function that will be useful to make modifications when the button is pressed. On the BP_Base_Button this function will remain void because I don't need to do anything at this point and will be useful only to be overriden by child Blueprints.
This image shows the important parts of the button logic:
As you can see between the start and the end of this process I call the "Update" function because if I want to made modifications on the button data its mandatory to make them before we try to launch the objects logics.
Now I made the BP_Base_Switch and in this Blueprint I configured the inheritance to have the BP_Base_Button as father Blueprint and this means that I already has all the logic that we saw before and the BPI_Interactable interface aplied.
Then I have overriden the Update and LaunchObjectLogic functions:
The important thing in the Update method is that I changed the boolean state of the switch and in the LaunchObjectLogic instead of the BPI_Triggerable we are caasting to BPI_BooleanSwitchable. Also I sent the switch state to the object throug the Switch function.
To try to make all this a bit more clear take a look on this schema. Its a reprensentation of this mechanism of interaction and buttons: