{"id":312,"date":"2024-03-18T18:56:18","date_gmt":"2024-03-18T18:56:18","guid":{"rendered":"https:\/\/abdoubouam.com\/?p=312"},"modified":"2024-03-18T19:57:09","modified_gmt":"2024-03-18T19:57:09","slug":"devlog-week-13","status":"publish","type":"post","link":"https:\/\/abdoubouam.com\/index.php\/2024\/03\/18\/devlog-week-13\/","title":{"rendered":"Devlog Week 13"},"content":{"rendered":"\n<p>This week was spent mostly prototyping an interaction system. Here&#8217;s a full list of what I&#8217;d done<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1 &#8211; Narrative Design Course<\/h2>\n\n\n\n<p>I followed a few video lessons from <a href=\"https:\/\/flippednormals.com\/product\/unreal-engine-5-visual-novel-and-narrative-game-design-37230?dst=eEL1cuJv\">Unreal Engine 5 Visual Novel and Narrative Design<\/a> . It&#8217;s not exactly what I&#8217;m aiming for, but it shows enough of the basics and tools. I realized it is much more different than what I intended to do for dialog and script management so I stopped at about a third\/halfway through it and started making my own system instead.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2- Object Interaction<\/h2>\n\n\n\n<p>This is where most of my time this week went. I decided to just dive in and make the interaction system from scratch myself, that way it will suit my needs and workflow exactly the way I want it, and also I will practice programming. The course above (what I followed of it, at least) helped me know just enough to start experimenting, especially how to reference an actor from another. What I was missing was for a way to talk with any arbitrary object, without hard-coded references in my code, and for that I found out about <a href=\"https:\/\/docs.unrealengine.com\/4.26\/en-US\/ProgrammingAndScripting\/Blueprints\/UserGuide\/Types\/Interface\/\" data-type=\"link\" data-id=\"https:\/\/docs.unrealengine.com\/4.26\/en-US\/ProgrammingAndScripting\/Blueprints\/UserGuide\/Types\/Interface\/\">Interfaces<\/a> . I was familiar with the concept of C++ interfaces from a long time, so it wasn&#8217;t hard to start using them. Unreal offers an &#8220;Implements Interface&#8221; node, which can be used to check if an actor implements it in its blueprints, and that&#8217;s all I was missing.<\/p>\n\n\n\n<p>Here&#8217;s a demo of the finished system.<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"http:\/\/abdoubouam.com\/wp-content\/uploads\/object interaction.mp4\"><\/video><\/figure>\n\n\n\n<p>Here&#8217;s a &#8220;short&#8221; explanation of my system:<\/p>\n\n\n\n<p>I created a blueprint for the interactable objects. From there, I will implement the interaction interface used to send data to the Player Blueprint, where all the logic is handled. It has a static mesh component, a sphere collision to overlap with the player, and a camera component. It has variables, where external camera, dialog, and whether a camera is used at all or not, as well as some that control the interaction radius, camera offset, and object origin (eg. set origin to player&#8217;s head instead of torso, or focus on the screen of an arcade machine instead of its body).<br>Here&#8217;s an implementation of the interface function:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure data-wp-context=\"{&quot;uploadedSrc&quot;:&quot;https:\\\/\\\/abdoubouam.com\\\/wp-content\\\/uploads\\\/2024\\\/03\\\/Interactable-Object-Interface-Function.jpg&quot;,&quot;figureClassNames&quot;:&quot;aligncenter size-full&quot;,&quot;figureStyles&quot;:null,&quot;imgClassNames&quot;:&quot;wp-image-321&quot;,&quot;imgStyles&quot;:null,&quot;targetWidth&quot;:1202,&quot;targetHeight&quot;:691,&quot;scaleAttr&quot;:false,&quot;ariaLabel&quot;:&quot;Enlarge image&quot;,&quot;alt&quot;:&quot;&quot;}\" data-wp-interactive=\"core\/image\" class=\"aligncenter size-full wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1202\" height=\"691\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/Interactable-Object-Interface-Function.jpg\" alt=\"\" class=\"wp-image-321\" srcset=\"https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/Interactable-Object-Interface-Function.jpg 1202w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/Interactable-Object-Interface-Function-300x172.jpg 300w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/Interactable-Object-Interface-Function-1024x589.jpg 1024w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/Interactable-Object-Interface-Function-768x442.jpg 768w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/Interactable-Object-Interface-Function-1000x575.jpg 1000w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/Interactable-Object-Interface-Function-230x132.jpg 230w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/Interactable-Object-Interface-Function-350x201.jpg 350w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/Interactable-Object-Interface-Function-480x276.jpg 480w\" sizes=\"(max-width: 1202px) 100vw, 1202px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Enlarge image\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"context.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"context.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><figcaption class=\"wp-element-caption\">Interact Interface Function<\/figcaption><\/figure><\/div>\n\n\n<p>I made a construction script that changes the position and rotation of camera, focuses it on the object, add offsets, and set collision sphere radius.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><a href=\"https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/Interactable-Object-Construction-Script.jpg\" target=\"_blank\" rel=\"noreferrer noopener\"><img decoding=\"async\" src=\"https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/Interactable-Object-Construction-Script.jpg\" alt=\"\"\/><\/a><figcaption class=\"wp-element-caption\">Construction Script. Click to expand.<\/figcaption><\/figure><\/div>\n\n\n<p>In the Player Blueprint, there&#8217;s a tick event that executes the following :<\/p>\n\n\n\n<ol>\n<li>Check if there&#8217;s enough time has passed since last execution (>0.10 seconds for example), to save some resources. I&#8217;m not 100% sure of the impact of this, but it&#8217;s based on the assumption that &#8220;Get Overlapping Actors&#8221; is too expensive to run on every tick. Please note that this step is skipped in the screenshot below.<\/li>\n\n\n\n<li>Get a list of all actors the player is overlapping with, using a &#8220;Get Overlapping Actors&#8221; node (each interactable actor has a sphere collision). <\/li>\n\n\n\n<li>Use list of actors, and check for the first actor satisfies both conditions : 1- Has implemented an interaction interface. 2- The player is looking in its direction (I compared the camera angle vs what the angle would be if you looked straight at its origin, using a dot product).<\/li>\n\n\n\n<li>When an object satisfies both conditions, show the interact icon, and change its material to be highlighted, and also set the &#8220;Active Interaction Object&#8221; variable to reference it. Otherwise clear that variable and undo the highlight and hide the interact icon.<\/li>\n<\/ol>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/detect-interactable-objects.jpg\" target=\"_blank\" rel=\"noreferrer noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"2560\" height=\"371\" src=\"https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/detect-interactable-objects-scaled.jpg\" alt=\"The blueprint. Click on the image to expand.\" class=\"wp-image-316\" srcset=\"https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/detect-interactable-objects-scaled.jpg 2560w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/detect-interactable-objects-300x43.jpg 300w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/detect-interactable-objects-1024x148.jpg 1024w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/detect-interactable-objects-768x111.jpg 768w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/detect-interactable-objects-1536x222.jpg 1536w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/detect-interactable-objects-2048x296.jpg 2048w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/detect-interactable-objects-1000x145.jpg 1000w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/detect-interactable-objects-230x33.jpg 230w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/detect-interactable-objects-350x51.jpg 350w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/detect-interactable-objects-480x69.jpg 480w\" sizes=\"(max-width: 2560px) 100vw, 2560px\" \/><\/a><\/figure><\/div>\n\n\n<p><\/p>\n\n\n\n<p>In addition to that, there&#8217;s an &#8220;On Click&#8221; event that acts independently, triggered by the key &#8220;E&#8221;. It does the following :<\/p>\n\n\n\n<ol>\n<li>When the player presses the interact key, it checks first if the active interaction object is valid to proceed, otherwise do nothing.<\/li>\n\n\n\n<li>The code gets a list of variables from the active interaction object, such as dialog\/description lines, use camera, custom camera, internal camera, camera offsets&#8230;etc.<\/li>\n\n\n\n<li>If &#8220;use camera&#8221; is true, the active camera switches to the interactive object camera or external camera if specified.<\/li>\n\n\n\n<li>Show the text UI, and load each line of the dialog with a typewriter effect, one by one. Play a sound every nth letter (every 2nd or 4th tends to work well, depending on speed), and delay slightly longer if the current character is a period or comma (more punctuation will be handled later).<\/li>\n\n\n\n<li>When all the characters of a dialog line are loaded, pause for 1 or 2 seconds (To do : change this to wait for user confirmation instead). If there&#8217;s still another line of dialog, repeat the step but with that line instead. Repeat until all the lines are exhausted.<\/li>\n\n\n\n<li>Remove UIs, clear active interaction object, stop camera shake animation if still playing, and switch back to the player&#8217;s main camera.<\/li>\n<\/ol>\n\n\n\n<p><\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/Interaction-Event.jpg\" target=\"_blank\" rel=\"noreferrer noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"2560\" height=\"918\" src=\"https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/Interaction-Event-scaled.jpg\" alt=\"\" class=\"wp-image-320\" srcset=\"https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/Interaction-Event-scaled.jpg 2560w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/Interaction-Event-300x108.jpg 300w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/Interaction-Event-1024x367.jpg 1024w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/Interaction-Event-768x275.jpg 768w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/Interaction-Event-1536x551.jpg 1536w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/Interaction-Event-2048x735.jpg 2048w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/Interaction-Event-1000x359.jpg 1000w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/Interaction-Event-230x83.jpg 230w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/Interaction-Event-350x126.jpg 350w, https:\/\/abdoubouam.com\/wp-content\/uploads\/2024\/03\/Interaction-Event-480x172.jpg 480w\" sizes=\"(max-width: 2560px) 100vw, 2560px\" \/><\/a><figcaption class=\"wp-element-caption\">Interaction logic. Click to expand.<\/figcaption><\/figure><\/div>\n\n\n<p>That&#8217;s pretty much what I did this week. I was a little bit worried I won&#8217;t like programming with nodes in UE5, considering I like low-level languages with text, but it felt very easy to get into and the logic behind things made sense. But it&#8217;s just another way of writing code, the implementation is really good.<\/p>\n\n\n\n<p>Don&#8217;t hesitate to ask if you have any questions, and I&#8217;ll hopefully see you next week<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This week was spent mostly prototyping an interaction system. Here&#8217;s a full list of what I&#8217;d done 1 &#8211; Narrative Design Course I followed a few video lessons from Unreal Engine 5 Visual Novel and Narrative Design . It&#8217;s not exactly what I&#8217;m aiming for, but it shows enough of the basics and tools. I realized it is much more different than what I [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":326,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"_links":{"self":[{"href":"https:\/\/abdoubouam.com\/index.php\/wp-json\/wp\/v2\/posts\/312"}],"collection":[{"href":"https:\/\/abdoubouam.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/abdoubouam.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/abdoubouam.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/abdoubouam.com\/index.php\/wp-json\/wp\/v2\/comments?post=312"}],"version-history":[{"count":12,"href":"https:\/\/abdoubouam.com\/index.php\/wp-json\/wp\/v2\/posts\/312\/revisions"}],"predecessor-version":[{"id":335,"href":"https:\/\/abdoubouam.com\/index.php\/wp-json\/wp\/v2\/posts\/312\/revisions\/335"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/abdoubouam.com\/index.php\/wp-json\/wp\/v2\/media\/326"}],"wp:attachment":[{"href":"https:\/\/abdoubouam.com\/index.php\/wp-json\/wp\/v2\/media?parent=312"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/abdoubouam.com\/index.php\/wp-json\/wp\/v2\/categories?post=312"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/abdoubouam.com\/index.php\/wp-json\/wp\/v2\/tags?post=312"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}