{"id":159,"date":"2024-02-14T17:55:58","date_gmt":"2024-02-14T17:55:58","guid":{"rendered":"https:\/\/andrewdalaimo.nuacomputerscience.co.uk\/blog\/?p=159"},"modified":"2024-02-14T17:56:14","modified_gmt":"2024-02-14T17:56:14","slug":"ggj-2024-ui-handler-devlog_016","status":"publish","type":"post","link":"https:\/\/andrewdalaimo.nuacomputerscience.co.uk\/blog\/2024\/02\/14\/ggj-2024-ui-handler-devlog_016\/","title":{"rendered":"GGJ 2024 UI Handler | DevLog_016"},"content":{"rendered":"\n<p>Recently in the Global Games Jam, I had the opportunity to work with several other disciplines to make a very unique game in a short amount of time. The game was heavily reliant on a &#8220;spam&#8221; mechanic of ads on the player screen reminiscent of early 2000&#8217;s windows interface.<\/p>\n\n\n\n<p>In Unreal Engine 5, the way that this data was handled would have to be built in a way that reminded us of the annoyance of old technology. UI elements are made with Widget Blueprints in UE5. These can be spawned and placed in flat layers in the game world, or directly in front of the player&#8217;s screen. Example would be a HUD or &#8220;fake&#8221; computer screen in the world that the player could interact with. In our game, we would have a mixture of both. A computer screen that simulated that of an older interface, that would generate and handle many different UI elements on top of it that the player could interact with.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-twentytwentyone-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"809\" src=\"https:\/\/andrewdalaimo.nuacomputerscience.co.uk\/blog\/wp-content\/uploads\/2024\/02\/GGJ_2024Screen-1024x809.png\" alt=\"\" class=\"wp-image-162\" srcset=\"https:\/\/andrewdalaimo.nuacomputerscience.co.uk\/blog\/wp-content\/uploads\/2024\/02\/GGJ_2024Screen-1024x809.png 1024w, https:\/\/andrewdalaimo.nuacomputerscience.co.uk\/blog\/wp-content\/uploads\/2024\/02\/GGJ_2024Screen-300x237.png 300w, https:\/\/andrewdalaimo.nuacomputerscience.co.uk\/blog\/wp-content\/uploads\/2024\/02\/GGJ_2024Screen-768x607.png 768w, https:\/\/andrewdalaimo.nuacomputerscience.co.uk\/blog\/wp-content\/uploads\/2024\/02\/GGJ_2024Screen.png 1225w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Handling this many Widget blueprints could get unruly, especially because of the different types we needed to spawn on the screen (A popup ad, a timed ad, and a CAPTCHA system).<\/p>\n\n\n\n<p>Handling each would require storing them efficiently and ordered so that they could be spawned correctly as the design team saw fit. Because the team member was comfortable with Data Tables, I created a custom data structure to help organize all of these in one spot for them, easily accessible and with helper functions to make them appear on screen correctly.<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:10px\"><code>UENUM(BlueprintType)\r\nenum class EAdvertType : uint8 {\r\n\tPOPUP = 0 UMETA(DisplayName = \"Popup\"),\r\n\tTIMED = 1 UMETA(DisplayName = \"Timed\"),\r\n\tINTERACTIVE = 2 UMETA(DisplayName = \"Interactive\")\r\n};\r\nUSTRUCT(BlueprintType)\r\nstruct FAdvertData : public FTableRowBase\r\n{\r\n\tGENERATED_USTRUCT_BODY()\r\n\tpublic:\r\n\t\tUPROPERTY(EditAnywhere, BlueprintReadWrite, Category = \"Advert Properties\")\r\n\t\t\tEAdvertType Type;\r\n\r\n\t\tUPROPERTY(EditAnywhere, BlueprintReadWrite, Category = \"Advert Properties\")\r\n\t\t\tTArray&lt;TSubclassOf&lt;UUserWidget>> UIWidgets;\r\n};<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:10px\"><code>\/\/ Grab Popup and add to viewport\r\nUUserWidget* AUIHandler::ShowPopupUIWidget(TSubclassOf&lt;UUserWidget> Widget)\r\n{\r\n\tif (Widget != NULL)\r\n\t{\r\n\t\tUUserWidget* Popup = CreateWidget&lt;UUserWidget>(GameInstanceRef, *Widget);\r\n\t\tPopup->AddToViewport();\r\n\t\treturn Popup;\r\n\t}\r\n\treturn NULL;\r\n}\n\/\/ When Timed Advert is added to viewport, create timer to destroy \r\nUUserWidget* AUIHandler::ShowTimedAdvertUIWidget(TSubclassOf&lt;UUserWidget> Widget)\r\n{\r\n\tif (Widget != NULL)\r\n\t{\r\n\t\tTimedAdvert = CreateWidget&lt;UUserWidget>(GameInstanceRef, *Widget);\r\n\t\tif (TimedAdvert != NULL) \r\n\t\t{\r\n\t\t\tTimedAdvert->AddToViewport();\r\n\t\t\tAdvertTimerDelegate.BindUFunction(this, \"ExitTimedAdvertUIWidget\");\r\n\t\t\tGetWorld()->GetTimerManager().SetTimer(AdvertTimer, AdvertTimerDelegate, 7.0f, false);\r\n\t\t}\r\n\t}\r\n\treturn TimedAdvert;\r\n}<\/code><\/pre>\n\n\n\n<p>The above code can be used in Blueprint to take whichever widget the designer sees fit, using it&#8217;s subclass to create a temporary Widget, which then adds it to the viewport (either destroying it on a timer for the Timed ads, or just waiting for user input for Popups and Captcha Ads).<\/p>\n\n\n\n<p>This simple tool means that the designer could add as many different ads (widget blueprints) into the data structure, then pull them out when necessary not having to deal with any of the backend functionality of creating references for them, or handling how the user should interact with them.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Recently in the Global Games Jam, I had the opportunity to work with several other disciplines to make a very unique game in a short amount of time. The game was heavily reliant on a &#8220;spam&#8221; mechanic of ads on the player screen reminiscent of early 2000&#8217;s windows interface. In Unreal Engine 5, the way&hellip; <a class=\"more-link\" href=\"https:\/\/andrewdalaimo.nuacomputerscience.co.uk\/blog\/2024\/02\/14\/ggj-2024-ui-handler-devlog_016\/\">Continue reading <span class=\"screen-reader-text\">GGJ 2024 UI Handler | DevLog_016<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[],"class_list":["post-159","post","type-post","status-publish","format-standard","hentry","category-devlog","entry"],"_links":{"self":[{"href":"https:\/\/andrewdalaimo.nuacomputerscience.co.uk\/blog\/wp-json\/wp\/v2\/posts\/159","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/andrewdalaimo.nuacomputerscience.co.uk\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/andrewdalaimo.nuacomputerscience.co.uk\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/andrewdalaimo.nuacomputerscience.co.uk\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/andrewdalaimo.nuacomputerscience.co.uk\/blog\/wp-json\/wp\/v2\/comments?post=159"}],"version-history":[{"count":3,"href":"https:\/\/andrewdalaimo.nuacomputerscience.co.uk\/blog\/wp-json\/wp\/v2\/posts\/159\/revisions"}],"predecessor-version":[{"id":163,"href":"https:\/\/andrewdalaimo.nuacomputerscience.co.uk\/blog\/wp-json\/wp\/v2\/posts\/159\/revisions\/163"}],"wp:attachment":[{"href":"https:\/\/andrewdalaimo.nuacomputerscience.co.uk\/blog\/wp-json\/wp\/v2\/media?parent=159"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/andrewdalaimo.nuacomputerscience.co.uk\/blog\/wp-json\/wp\/v2\/categories?post=159"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/andrewdalaimo.nuacomputerscience.co.uk\/blog\/wp-json\/wp\/v2\/tags?post=159"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}