Modular Interactive System
What is it?
I started developing this system during my junior year. Our team required a system to handle the interactive objects and the corresponding event in the game. After several iterations, I designed this system which separated the interactive objects into two major categories, the trigger and the receiver.
The trigger defines the way of the player's "interaction". For example, entering an area, toggle a lever, press a button or focusing on an interactable object.
After the player interacts with a trigger, it will call the assigned receivers to activate the corresponding events.
The receiver defines what event should happen after the player "interact" with something. The one I used the most is the "Transform Modifying receiver". It will change the assigned object's transform when the related trigger is triggered. Other than that, I also made the custom event receiver to let the user can implement their desired event via blueprint.
If you are interested in this demo, the link of the executable is here.
You can also find its source code via my GitHub.
The base class of the trigger is called "Triggers". It defines the basic framework and variables for all the triggers.
When the player satisfies a trigger's interactive condition (e.g. moving into an area), it will call the "CallReceivers" function immediately or after the delay time to activate the receiver in its "Receivers" array.
At the same time, it will also call the "SelfReact" function to begin some events for feedback. An example can be making the lever rotate.
The bool variable "IsTriggerOnce" is used to specify whether the trigger can be launched once or several times.
I implemented three kinds of triggers in this demo project. The "Overlap trigger" will be triggered when the player enters its range. Both "Focus trigger" and "Non-focus trigger" require the player to press the interaction key (key "E" in this project) to launch them. The difference is that the "Focus trigger" also needs the player to focus on it (using line trace to detect which object that player is focusing on) while the "Non-focus trigger" can only be launched when the player is in its range while they pressing the interaction key.
To give the player feedback on whether they are in the range, I utilized the depth stencil value with the custom material to draw the object's outline.
If the trigger is a "Focus trigger", its outline will be displayed when the player is focusing on it. The related property is "ShouldPopSelfOutLine" in this project.
On the other hand, for the "Non-focus trigger", having the bool "ShouldPopOutLine" be true will display the corresponding objects' outline when the player is in its effective range.
Generally, I used "Non-focus trigger" for the third-person game and used "Focus trigger" for the first-person game.
The base class of the receiver is called "Receivers". It defines the basic framework and variables for all the receivers.
When the receiver receives the call from the trigger, it will call the "Activate" function to determine when to start the event. When the event should start, it will then call the "ReactMaster" to begin the event and play the SFX if there is any. The function that defines what event should happen is called "React". It is a virtual function and will be implemented differently by each child receiver for different kinds of events.
I spent a lot of time iterating the "Transform Modifier receiver" to make it more user-friendly. In the end, I implemented four buttons in the detail panel to record each interactive object's transform data. Instead of manually typing the transform data, the user now only needs to press the "Set Origin" button to record the objects' initial transform and modify the objects' transform to the desired status and then press the "Set Delta" button to record the change value. They can also use the "Check Origin" and "Check Destination" buttons to review the start and end status of the objects.
The "Custom Event receiver" has a "BlueprintImplementableEvent" function called "CustomReactEvent". It will let the user be able to define their desired event via blueprint without making a new child class.
The biggest advantage of this interactive system is its flexibility. The user can design and make their trigger or receiver as long as they are derived from the based class. Besides the ones I implemented in this demo project, I also created some complicated triggers and receivers like the conditional trigger(require other triggers be triggered to activate it), receiver to play cutscene, receiver to change the skylight...etc.
However, this system will increase the number of the object in the game since it will require at least two objects (one trigger and one receiver) for a single interaction event. I will develop a manager class and make the current trigger and receiver class become the component of it in the future.