Devlog #013

WHALIEN - Unexpected Guests

Push and Pull your way through this heartfelt adventure! Fin, the mechanical whale you call home, is plagued by mischievous Squiddies. As Ernest Hemingwhale you set out on a Fin-tastic journey to help your friend with his unexpected guests.

Throughout WHALIEN, there are lots of actions that are triggered when the player (or any other character/object) reaches a designated area. Such actions can be noticeable for the player - like triggering a scripted sequence or the camera zooming out - but some actions are also unnoticeable – like saving the game and setting a new checkpoint. Most frequently we need to trigger multiple actions at the beginning of a new level, such as [list] [*] saving the game [*] updating the latest checkpoint [*] loading/unloading other levels [*] starting a scripted action [*] displaying some dialogue [*] unlocking an ability and displaying the corresponding tutorial video [*] unlocking an achievement [*] etc. [/list] All of these actions are ideally executed at the same time, but there are cases where some of them need to be executed in a predetermined order. For example, we might want to first display a dialogue and afterwards unlock a new ability for the player. Having individual triggers for each of these functionalities would be very cumbersome, because having them all fire at the same time would require all triggers to be placed at the exact same location and have identical dimensions. In this setup, we would have to make some triggers ever so slightly smaller to have them be fired later and keep the predetermined order. [img]{STEAM_CLAN_IMAGE}/38104262/f403b38b8c00df57b92a884766fb334981cffb97.png[/img] (Some actions combined into one collider. This trigger displays a static mesh and unlocks an ability and an achievement on overlap.) [h2]Core[/h2] Our CommonCollider system allows us to trigger the execution of multiple actions with a single collider. The order in which these actions are executed can be defined by the designers. The CommonCollider system consists of two elements, the [b]CommonColliderComponent[/b] and the [b]IColliderSystemImplementable[/b]-interface. This feature allows us to keep our levels tidy and simplifies getting an overview of all actions triggered at a specific point. It also makes adding new actions to an existing trigger less cumbersome. [img]{STEAM_CLAN_IMAGE}/38104262/cfb5942a2b58fe064f25ab132c67abebc9370cac.png[/img] (Multiple functions combined into one collider. This trigger prepares the state of the game for the newly entered level.) [h3]CommonColliderComponent[/h3] The CommonColliderComponent is a BoxCollider that manages all actions attached to its owning actor. Whenever the Collider registers an overlap, it forwards the event to all IColliderSystemImplementable components attached to its owner. The order of execution of these actions can be customized in the editor. [h3]IColliderSystemImplementable[/h3] Each action usable in our CommonCollider system needs to be an ActorComponent implementing the IColliderSystemImplementable interface. It declares the virtual function [i]ExecuteFunctionality()[/i], which is called on [i]CommonColliderComponent::BeginOverlap()[/i] and [i]EndOverlap()[/i]. Each component must override the function to define the logic to be executed on begin or end overlap. [img]{STEAM_CLAN_IMAGE}/38104262/a19df91b86633f5fddca1c899dd793d86674100b.png[/img] [img]{STEAM_CLAN_IMAGE}/38104262/7941eacc953c272da7d37744bde22da9e0746036.png[/img] (Examples of classes implementing IColliderSystemImplementable: The logic of individual actions is usually simple because they only have to accomplish simple tasks.) [img]{STEAM_CLAN_IMAGE}/38104262/58112b9def1337509ee36e37ef4fd9fed4a47603.png[/img] (The ICommonColliderInterface definition: Interfaces in UE4 require a special setup to be recognized by the engine and usable in Blueprint.) [h2]Challenges[/h2] One UE4-specific challenge we had to overcome for our CommonColliders was that overlap events aren’t fired if they happen during or before [i]BeginPlay()[/i]. This can for example happen when the player spawns inside a CommonCollider. Firing the overlap events manually during [i]BeginPlay()[/i] doesn’t work either, because [i]GetAllOverlappingComponents()[/i] returns an empty array at that time. Once all actors have finished their [i]BeginPlay()[/i], [i]GetAllOverlappingActors()[/i] works as intended, so normally, we could use the C++ delegate [i]UWorld::OnWorldBeginPlay[/i] (which is fired once all actors have finished their [i]BeginPlay()[/i]). However, since we use LevelStreaming and some actors are only loaded in after [i]OnWorldBeginPlay[/i], this approach is not applicable for us. Therefore, we subscribe to our own delegate [i]OnLevelStreamed[/i], which is fired whenever a new level is streamed in and all contained actors have received their [i]BeginPlay()[/i]. Therefore [i]GetAllOverlappingComponents()[/i] works here. If you want to learn more about our LevelStreaming system, check out our [url=https://steamcommunity.com/games/1270680/announcements/detail/3133944822947535307]second devlog entry[/url]. [img]{STEAM_CLAN_IMAGE}/38104262/79a5ad128ceb716e3e36ca09d1890d587fe0c903.png[/img] (Code to subscribe to [i]OnLevelStreamed [/i]on [i]BeginPlay()[/i] and manually trigger the overlaps once the event is fired.) Since first creating the CommonCollider system, we’ve continuously integrated new functionalities. It has become a staple in our toolbox to keep our levels clean and structured. If you have any questions or ideas about what other actions we could add to our CommonColliders, feel free to reach out! - Andi, Ralf