{"id":927,"date":"2023-02-18T17:09:17","date_gmt":"2023-02-18T08:09:17","guid":{"rendered":"https:\/\/heyyocg.link\/?p=927"},"modified":"2024-11-13T01:09:38","modified_gmt":"2024-11-12T16:09:38","slug":"niagara-pbd-wanwan","status":"publish","type":"post","link":"https:\/\/heyyocg.link\/en\/niagara-pbd-wanwan\/","title":{"rendered":"Let&#8217;s Create Mario&#8217;s Chain Chomp in Niagara \u2013 Real-Time Chain Simulation Using the PBD Method"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p>Note: I wrote this article with UE 4.27 data, so it might have some changes in the latest UE version.<\/p>\n\n\n\n<p>In this article, I\u2019ll explain how to create Mario&#8217;s Chain Chomp!<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-rich is-provider-twitter wp-block-embed-twitter\"><div class=\"wp-block-embed__wrapper\">\nhttps:\/\/twitter.com\/yo_hanashima\/status\/1467857097715232768?s=20\n<\/div><\/figure>\n\n\n\n<p>That being said, the main focus here is how the movement of the chain connected to the Chain Chomp is created in Niagara.<\/p>\n\n\n\n<p>The chain\u2019s movement is simulated in real time using the <strong>Position Based Dynamics<\/strong> (PBD) method, through the <strong>Simulation Stage<\/strong> feature in Niagara.<\/p>\n\n\n\n<p>I have previously written an explanation about the <strong>Simulation Stage<\/strong>, so please refer to that article for more details.<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-wp-embed is-provider-heyyo-cg wp-block-embed-heyyo-cg\"><div class=\"wp-block-embed__wrapper\">\n<blockquote class=\"wp-embedded-content\" data-secret=\"jyFIhnewd1\"><a href=\"https:\/\/heyyocg.link\/en\/ue4-26-niagara-adavanced-simulation-stage-basic\/\">Niagara Advanced Guide &#8211; Basics of the Simulation Stage<\/a><\/blockquote><iframe class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" style=\"position: absolute; clip: rect(1px, 1px, 1px, 1px);\" title=\"&#8220;Niagara Advanced Guide &#8211; Basics of the Simulation Stage&#8221; &#8212; HeyYo CG\" src=\"https:\/\/heyyocg.link\/en\/ue4-26-niagara-adavanced-simulation-stage-basic\/embed\/#?secret=Y3NkMYgej8#?secret=jyFIhnewd1\" data-secret=\"jyFIhnewd1\" width=\"500\" height=\"282\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe>\n<\/div><\/figure>\n\n\n\n<p>Additionally, the chain simulation itself is based on an Epic sample that I have slightly modified. I\u2019ve written an explanation about that sample before as well.<\/p>\n\n\n\n<p>In this article, I will focus on explaining the specific modifications I made to the sample, so I recommend reading the following article first before continuing with this one.<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-wp-embed is-provider-heyyo-cg wp-block-embed-heyyo-cg\"><div class=\"wp-block-embed__wrapper\">\n<blockquote class=\"wp-embedded-content\" data-secret=\"4w1OeqSG6c\"><a href=\"https:\/\/heyyocg.link\/en\/ue4-27-niagara-advanced-position-based-dynamics-rigid-constraint-chain\/\">Niagara Advanced Guide &#8211; Chain Simulation with PBD<\/a><\/blockquote><iframe class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" style=\"position: absolute; clip: rect(1px, 1px, 1px, 1px);\" title=\"&#8220;Niagara Advanced Guide &#8211; Chain Simulation with PBD&#8221; &#8212; HeyYo CG\" src=\"https:\/\/heyyocg.link\/en\/ue4-27-niagara-advanced-position-based-dynamics-rigid-constraint-chain\/embed\/#?secret=Zlwe6XNscs#?secret=4w1OeqSG6c\" data-secret=\"4w1OeqSG6c\" width=\"500\" height=\"282\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe>\n<\/div><\/figure>\n\n\n\n<p>I apologize for the number of preparatory articles, but the content of this article will be broken down into three main sections:<\/p>\n\n\n\n<ol>\n<li>Modifying the chain simulation sample to enable collision detection<\/li>\n\n\n\n<li>Setting up the Chain Chomp&#8217;s chain simulation<\/li>\n\n\n\n<li>(Bonus) Controlling the movement of the Chain Chomp<\/li>\n<\/ol>\n\n\n\n<p>The data is also available in the link below. If you want to see the actual working data, please check it out.<\/p>\n\n\n\n<p> <a href=\"https:\/\/heyyohanashima.gumroad.com\/l\/noiblu\">Chain Simulation in Niagara &#8211; Create Mario&#8217;s Chain Chomp<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Modifying the Sample to Enable Collision Detection<\/h2>\n\n\n\n<p>First, copy the <strong>Chain_SimulationStages<\/strong> Niagara System from the sample and disable the unnecessary modules.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img fetchpriority=\"high\" decoding=\"async\" width=\"272\" height=\"759\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-011120.png\" alt=\"\" class=\"wp-image-716\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-011120.png 272w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-011120-108x300.png 108w\" sizes=\"(max-width: 272px) 100vw, 272px\" \/><\/figure>\n\n\n\n<p>The <strong>Curl Noise Force<\/strong> and <strong>Wind Force<\/strong> are used to move the chain with external forces, but since we are working on a simple case where we want to detect collisions, we will disable them.<\/p>\n\n\n\n<p>The <strong>Find Kinetic and Potential Energy<\/strong> and <strong>Colorize Chain Based on Kinetic Energy<\/strong> modules are used to visualize areas with stronger forces, but these can also be disabled for our purposes.<\/p>\n\n\n\n<p>Next, the starting point of the chain is set to sway, so we will disable that motion.<\/p>\n\n\n\n<p>Set the <strong>Chain Origin Offset<\/strong> in <strong>Update Chain Segments After Forces<\/strong> to (0, 0, 0).<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"674\" height=\"72\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-014251.png\" alt=\"\" class=\"wp-image-717\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-014251.png 674w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-014251-300x32.png 300w\" sizes=\"(max-width: 674px) 100vw, 674px\" \/><\/figure>\n\n\n\n<p>With these settings, the chain will only hang down due to gravity and will no longer move.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"298\" height=\"508\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-012044.png\" alt=\"\" class=\"wp-image-718\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-012044.png 298w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-012044-176x300.png 176w\" sizes=\"(max-width: 298px) 100vw, 298px\" \/><\/figure>\n\n\n\n<p>Next, let\u2019s use a Blueprint to make the starting point of the chain movable via keyboard input.<\/p>\n\n\n\n<p>First, create a <strong>StartPoint<\/strong> Vector user parameter and set it in the <strong>Chain Origin<\/strong> in <strong>Configure Chain<\/strong>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"673\" height=\"287\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-012111.png\" alt=\"\" class=\"wp-image-719\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-012111.png 673w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-012111-300x128.png 300w\" sizes=\"(max-width: 673px) 100vw, 673px\" \/><\/figure>\n\n\n\n<p>Then, create a suitable actor blueprint, add Niagara and a sphere, and assign the modified Niagara System to the Niagara component.<\/p>\n\n\n\n<p>Set up the Blueprint nodes to move the sphere left and right using keyboard inputs.<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"604\" data-id=\"720\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-015018-1024x604.png\" alt=\"\" class=\"wp-image-720\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-015018-1024x604.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-015018-300x177.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-015018-768x453.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-015018-816x481.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-015018.png 1239w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"887\" height=\"676\" data-id=\"721\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-015041.png\" alt=\"\" class=\"wp-image-721\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-015041.png 887w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-015041-300x229.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-015041-768x585.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-015041-816x622.png 816w\" sizes=\"(max-width: 887px) 100vw, 887px\" \/><\/figure>\n<\/figure>\n\n\n\n<p>Finally, in the <strong>Construction Script<\/strong> and <strong>Event Graph<\/strong>&#8216;s <strong>Tick<\/strong>, send the sphere&#8217;s world location to the <strong>StartPoint<\/strong> parameter in the Niagara system.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"925\" height=\"429\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-012132.png\" alt=\"\" class=\"wp-image-748\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-012132.png 925w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-012132-300x139.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-012132-768x356.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-012132-816x378.png 816w\" sizes=\"(max-width: 925px) 100vw, 925px\" \/><\/figure>\n\n\n\n<p>Now, the starting point of the chain can be moved with the keyboard, and the chain will move naturally along with it.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"327\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/FeatureSample_4_27-Unreal-Editor-2021-12-22-01-33-16.gif\" alt=\"\" class=\"wp-image-722\"\/><\/figure>\n\n\n\n<p>Now, let&#8217;s set up collision detection. This is done by simply adding the standard <strong>Collision<\/strong> module from Niagara.<\/p>\n\n\n\n<p>When you add it, you might get an error at first, but pressing the <strong>Fix Now<\/strong> button and moving the module above <strong>Solve Forces and Velocity<\/strong> should solve the problem.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"283\" height=\"284\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-015804.png\" alt=\"\" class=\"wp-image-723\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-015804.png 283w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-015804-150x150.png 150w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-015804-88x88.png 88w\" sizes=\"(max-width: 283px) 100vw, 283px\" \/><\/figure>\n\n\n\n<p>Keep in mind that since we are using the <strong>Simulation Stage<\/strong>, we must use GPU simulation.<\/p>\n\n\n\n<p>For GPU simulation, there are three types of collision detection methods:<\/p>\n\n\n\n<ul>\n<li><strong>GPU Depth Buffer<\/strong>: Collision detection based on depth values from the camera.<\/li>\n\n\n\n<li><strong>GPU Distance Fields<\/strong>: Collision detection based on global distance fields.<\/li>\n\n\n\n<li><strong>Analytical Planes<\/strong>: Collision detection using pre-configured infinite planes (up to two).<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"435\" height=\"105\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/1232.png\" alt=\"\" class=\"wp-image-724\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/1232.png 435w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/1232-300x72.png 300w\" sizes=\"(max-width: 435px) 100vw, 435px\" \/><\/figure>\n\n\n\n<p>At this point, neither <strong>GPU Depth Buffer<\/strong> nor <strong>GPU Distance Fields<\/strong> seem reliable for use in a real game environment.<\/p>\n\n\n\n<p>Here\u2019s a brief explanation of each method:<\/p>\n\n\n\n<p><strong>GPU Depth Buffer<\/strong>: In its default setup, the chain will fly off. This is likely because the collision detection is affecting the Mesh Particles themselves, but this needs further investigation.<\/p>\n\n\n\n<p>By unchecking <strong>Kill Occluded Particles<\/strong>, you can avoid the chain flying off, but the behavior when moving the chain becomes unnatural.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"327\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/FeatureSample_4_27-Unreal-Editor-2021-12-22-02-18-44.gif\" alt=\"\" class=\"wp-image-727\"\/><\/figure>\n\n\n\n<p><strong>GPU Distance Fields<\/strong>: This method is slightly better, but the collision is not accurate, and there are instances where the chain unexpectedly flies off.<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-3 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"327\" data-id=\"728\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/FeatureSample_4_27-Unreal-Editor-2021-12-22-01-31-04.gif\" alt=\"\" class=\"wp-image-728\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"327\" data-id=\"729\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/FeatureSample_4_27-Unreal-Editor-2021-12-22-01-31-04_1.gif\" alt=\"\" class=\"wp-image-729\"\/><\/figure>\n<\/figure>\n\n\n\n<p>This issue seems to be related to the Global DistanceField\u2019s accuracy, so accurate collision detection may not be possible unless the precision of the Global DistanceField is improved.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"555\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/ScreenShot00001-1024x555.png\" alt=\"\" class=\"wp-image-730\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/ScreenShot00001-1024x555.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/ScreenShot00001-300x163.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/ScreenShot00001-768x416.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/ScreenShot00001-1536x832.png 1536w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/ScreenShot00001-816x442.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/ScreenShot00001.png 1920w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Global DistanceField Preview<\/figcaption><\/figure>\n\n\n\n<p><strong>Analytical Planes<\/strong>: This method allows for highly accurate collision detection, and the chain doesn\u2019t suddenly fly off. It is a good option if you only need to detect collisions with a floor, for example.<\/p>\n\n\n\n<p>In the Chain Chomp example, I am using <strong>Analytical Planes<\/strong> to detect collisions only with the floor.<\/p>\n\n\n\n<p>\u203b When it comes to Collision, it still needs further research. It might be improved if you implement collision detection within a simulation stage.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Setting Up the Chain Chomp\u2019s Chain Simulation<\/h2>\n\n\n\n<p>Now we\u2019ll move on to setting up the Chain Chomp itself!<\/p>\n\n\n\n<p>There\u2019s not much to do here. Compared to the previous steps, we just need to fix both the start and end points of the chain.<\/p>\n\n\n\n<p>The overall structure looks like this. In addition to the parts we disabled earlier, we will also disable <strong>Constrain Chain Max Length<\/strong>. This is because, in this setup, we are fixing both ends and controlling the movement via Blueprint, so depending on the timing, the chain might exceed the pre-set maximum length.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"273\" height=\"760\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-031212.png\" alt=\"\" class=\"wp-image-737\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-031212.png 273w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-031212-108x300.png 108w\" sizes=\"(max-width: 273px) 100vw, 273px\" \/><\/figure>\n\n\n\n<p>We also need to apply the modifications made to prevent not only the start point but also the end point from being affected by the simulation.<\/p>\n\n\n\n<p>First, create the user parameters <strong>ChainEnd<\/strong> and <strong>ChainStart<\/strong>. These will be used to set the fixed positions later (more on the scale settings below).<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"232\" height=\"118\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-025239.png\" alt=\"\" class=\"wp-image-732\"\/><\/figure>\n\n\n\n<p>As with the previous section, set <strong>ChainStart<\/strong> to the <strong>Chain Origin<\/strong> in <strong>Configure Chain<\/strong>.<\/p>\n\n\n\n<p>Next, slightly modify the contents of the <strong>Initialize Chain Constraint<\/strong> scratchpad.<\/p>\n\n\n\n<p>Originally, only the <strong>ChainStartPoint<\/strong> had an <strong>InverseMass<\/strong> of 0, so change the <strong>ChainEndPoint<\/strong> to also have an <strong>InverseMass<\/strong> of 0. <strong>InverseMass<\/strong> is used later to disable velocity.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"410\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-024912-1024x410.png\" alt=\"\" class=\"wp-image-733\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-024912-1024x410.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-024912-300x120.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-024912-768x308.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-024912-816x327.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-024912.png 1391w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, modify the contents of <strong>Update Chain Segments After Forces<\/strong>.<\/p>\n\n\n\n<p>Here, we set the position of the particle we want to fix to an arbitrary location. Only the <strong>ChainStartPoint<\/strong> was originally fixed by applying an offset to the Chain Origin, but now we remove the offset and just set the <strong>ChainStartPoint<\/strong> to be Chain Origin input as well as the ChainEndPoint to be Chain End input.<\/p>\n\n\n\n<p>Then fixing its position with set the previously created <strong>ChainStart<\/strong> and <strong>ChainEnd<\/strong> parameter for those inputs.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"402\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-025103-1024x402.png\" alt=\"\" class=\"wp-image-735\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-025103-1024x402.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-025103-300x118.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-025103-768x301.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-025103-816x320.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-025103.png 1509w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"401\" height=\"92\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-031121.png\" alt=\"\" class=\"wp-image-736\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-031121.png 401w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-031121-300x69.png 300w\" sizes=\"(max-width: 401px) 100vw, 401px\" \/><\/figure>\n\n\n\n<p>Finally, make minor adjustments to <strong>Solve Chain Constraint<\/strong> to finalize the fixed position at the end point.<\/p>\n\n\n\n<p>To the flag given to the <code>CurrentPinned<\/code> in the <code>Calculate Link Constraint<\/code>, simply add the <code>ChainEndPoint<\/code>. This will exclude both the start and end points from the simulation calculations.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"573\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-025346-1024x573.png\" alt=\"\" class=\"wp-image-738\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-025346-1024x573.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-025346-300x168.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-025346-768x430.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-025346-816x456.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-025346.png 1153w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Now, for collision detection, as mentioned earlier, we set <strong>Analytical Planes<\/strong> and configure <strong>Analytical Collision Plane Position 1<\/strong> to (0, 0, 20) in world space, which aligns with the floor.<\/p>\n\n\n\n<p>Other values such as <strong>Radius<\/strong>, <strong>Bounce<\/strong>, and <strong>Friction<\/strong> can be set arbitrarily, so don\u2019t worry too much about them.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"649\" height=\"623\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-025210.png\" alt=\"\" class=\"wp-image-739\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-025210.png 649w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-025210-300x288.png 300w\" sizes=\"(max-width: 649px) 100vw, 649px\" \/><\/figure>\n\n\n\n<p>Lastly, I will explain the <strong>Scale<\/strong> parameter.<\/p>\n\n\n\n<p>To make the chain\u2019s size adjustable, we added a <strong>Scale<\/strong> parameter. There are two places where this scale must be applied:<\/p>\n\n\n\n<ol>\n<li>Multiply it with the mesh particle size.<\/li>\n\n\n\n<li>Apply it to the <strong>Chain Segment Length<\/strong> in <strong>Configure Chain<\/strong> to maintain the correct length, as improper scaling here will cause issues in the simulation.<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"639\" height=\"493\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-032307.png\" alt=\"\" class=\"wp-image-740\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-032307.png 639w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-032307-300x231.png 300w\" sizes=\"(max-width: 639px) 100vw, 639px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"637\" height=\"272\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-032328.png\" alt=\"\" class=\"wp-image-741\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-032328.png 637w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-032328-300x128.png 300w\" sizes=\"(max-width: 637px) 100vw, 637px\" \/><\/figure>\n\n\n\n<p>With that, the Niagara setup is complete.<\/p>\n\n\n\n<p>Next, let\u2019s proceed with setting values for <strong>ChainStart<\/strong> and <strong>ChainEnd<\/strong> in the Blueprint.<\/p>\n\n\n\n<p>The fixed positions are set as shown in the image below. <strong>ChainEnd<\/strong> remains fixed, but <strong>ChainStart<\/strong> will be updated every frame based on the movement of the Chain Chomp.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"555\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/ScreenShot00002-1024x555.png\" alt=\"\" class=\"wp-image-752\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/ScreenShot00002-1024x555.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/ScreenShot00002-300x163.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/ScreenShot00002-768x416.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/ScreenShot00002-1536x832.png 1536w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/ScreenShot00002-816x442.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/ScreenShot00002.png 1920w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>In the <strong>Construction Script<\/strong>, assign the <strong>World Position<\/strong> of the <strong>Pile Attach<\/strong> to <strong>ChainEnd<\/strong>, and the <strong>World Position<\/strong> of the <strong>Wan Wan Attachment<\/strong> to <strong>ChainStart<\/strong>.<\/p>\n\n\n\n<p>\u203b By the way, Wan Wan is the Japanese name of Chain Chomp.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1015\" height=\"534\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-032731.png\" alt=\"\" class=\"wp-image-744\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-032731.png 1015w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-032731-300x158.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-032731-768x404.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-032731-816x429.png 816w\" sizes=\"(max-width: 1015px) 100vw, 1015px\" \/><\/figure>\n\n\n\n<p><strong>Pile Attach<\/strong> is placed at an appropriate world position and assigned to the relevant Blueprint variable.<\/p>\n\n\n\n<p><strong>Wan Wan Attachment<\/strong> is a hidden sphere child of the Chain Chomp&#8217;s static mesh.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"653\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-034112-1024x653.png\" alt=\"\" class=\"wp-image-751\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-034112-1024x653.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-034112-300x191.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-034112-768x490.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-034112-816x520.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-034112.png 1474w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Finally, in <strong>Event Tick<\/strong>, update <strong>ChainStart<\/strong> with the world position of <strong>Wan Wan Attachment<\/strong>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"260\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-034247-1024x260.png\" alt=\"\" class=\"wp-image-745\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-034247-1024x260.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-034247-300x76.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-034247-768x195.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-034247-816x208.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-034247.png 1423w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>That\u2019s the setup for the Chain Chomp\u2019s chain simulation!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">(Bonus) Controlling the Movement of the Chain Chomp<\/h2>\n\n\n\n<p>The explanation for the <strong>PBD-based chain simulation<\/strong> in this article is complete. However, as a bonus, I will quickly explain how the movement of the Chain Chomp is controlled in Blueprint.<\/p>\n\n\n\n<p>First, we define the Chain Chomp\u2019s states. There are five states, which are set as <strong>Enumerators<\/strong>:<\/p>\n\n\n\n<ul>\n<li><strong>Follow<\/strong>: The Chain Chomp chases the player in the red zone.<\/li>\n\n\n\n<li><strong>Berserk<\/strong>: The Chain Chomp chases the player in the blue zone but is stopped by the chain.<\/li>\n\n\n\n<li><strong>Lose<\/strong>: When the player exits the blue zone, the Chain Chomp loses interest and turns back to the starting position.<\/li>\n\n\n\n<li><strong>Back<\/strong>: The Chain Chomp returns to its starting position.<\/li>\n\n\n\n<li><strong>Stay<\/strong>: The Chain Chomp stays at the starting position.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"340\" height=\"223\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-234229.png\" alt=\"\" class=\"wp-image-755\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-234229.png 340w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-234229-300x197.png 300w\" sizes=\"(max-width: 340px) 100vw, 340px\" \/><\/figure>\n\n\n\n<p>Each state\u2019s transition is evaluated every frame based on the player\u2019s and Chain Chomp\u2019s position, as well as the chain\u2019s length. These transitions are handled by a <strong>State Manager<\/strong> function. (Details omitted for brevity.)<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"736\" height=\"675\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-234453.png\" alt=\"\" class=\"wp-image-756\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-234453.png 736w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-234453-300x275.png 300w\" sizes=\"(max-width: 736px) 100vw, 736px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"381\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-234420-1024x381.png\" alt=\"\" class=\"wp-image-757\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-234420-1024x381.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-234420-300x112.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-234420-768x286.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-234420-816x303.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-22-234420.png 1377w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">State Manager Logic<\/figcaption><\/figure>\n\n\n\n<p>Each state corresponds to specific actions that are implemented as functions. These functions are executed based on the current state.<\/p>\n\n\n\n<p>While I won\u2019t go into details on each function, here are some tips for controlling the movement:<\/p>\n\n\n\n<ul>\n<li><strong>Natural Chase Movement<\/strong>: Use <strong>Lerp<\/strong> to make the Chain Chomp move faster when further away from the target, and slower as it gets closer.<\/li>\n\n\n\n<li><strong>Bouncing Movement<\/strong>: Use <strong>AddWorldOffset<\/strong> with upward movement to simulate a bouncing effect.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"724\" height=\"339\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-23-000005.png\" alt=\"\" class=\"wp-image-758\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-23-000005.png 724w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-23-000005-300x140.png 300w\" sizes=\"(max-width: 724px) 100vw, 724px\" \/><\/figure>\n\n\n\n<ul>\n<li><strong>Disabling Inertia<\/strong>: <\/li>\n<\/ul>\n\n\n\n<p>Since the Chain Chomp has collision enabled and is using physics behavior, I found that it wouldn&#8217;t stop properly when reaching the maximum chain length at first.<\/p>\n\n\n\n<p>To fix this, I decided to simply remove the physical velocity. By setting <strong>Set Physics Linear Velocity<\/strong> to 0, you can override the velocity calculated by the physics engine, causing the object to stop immediately.<\/p>\n\n\n\n<p>If you also want to disable rotation, just set <strong>Set Physics Angular Velocity in Radians<\/strong> to 0, and that will do the trick.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"348\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-23-000421-1024x348.png\" alt=\"\" class=\"wp-image-759\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-23-000421-1024x348.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-23-000421-300x102.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-23-000421-768x261.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-23-000421-816x278.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/2021-12-23-000421.png 1293w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Since I wanted to keep the inertia in the vertical direction, I set the other values to 0.<\/figcaption><\/figure>\n\n\n\n<p>That wraps up the explanation!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>When I saw the chain simulation sample in Niagara by function, I thought, &#8220;I want to make it interactive with collision!&#8221; and started brainstorming for a good subject. For some reason, the idea of &#8220;Mario&#8217;s Chain Chomp&#8221; popped into my head.<\/p>\n\n\n\n<p>However, the collision didn\u2019t work as well as I expected, and it doesn\u2019t seem like it will be easy to improve. So, practical interactive PBD simulations will need a bit more thinking and refinement.<\/p>\n\n\n\n<p>Even so, I think it&#8217;s really convenient to easily create relatively natural chain behaviors like this, and PBD methods have various potential uses beyond just chains, so I\u2019m looking forward to exploring this further!<\/p>\n\n\n\n<p>By the way, I modeled the Chain Chomp in Houdini! It turned out surprisingly cute \ud83d\ude42<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"555\" src=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/ScreenShot00003-1024x555.png\" alt=\"\" class=\"wp-image-760\" srcset=\"https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/ScreenShot00003-1024x555.png 1024w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/ScreenShot00003-300x163.png 300w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/ScreenShot00003-768x416.png 768w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/ScreenShot00003-1536x832.png 1536w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/ScreenShot00003-816x442.png 816w, https:\/\/heyyocg.link\/wp-content\/uploads\/2021\/12\/ScreenShot00003.png 1920w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Note: I wrote this article with UE 4.27 data, so it might have some changes in the latest UE version. In this article, I\u2019ll explain how to create Mario&#8217;s Chain Chomp! That being said, the main focus here is how the movement of the chain connected to the Chain Chomp is created in Niagara. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":712,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_lmt_disableupdate":"no","_lmt_disable":"","_mi_skip_tracking":false,"footnotes":"","_locale":"en_US","_original_post":"http:\/\/heyyocg.link\/?p=706"},"categories":[17,31],"tags":[32,15,30],"modified_by":"yohanashima","_links":{"self":[{"href":"https:\/\/heyyocg.link\/wp-json\/wp\/v2\/posts\/927"}],"collection":[{"href":"https:\/\/heyyocg.link\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/heyyocg.link\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/heyyocg.link\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/heyyocg.link\/wp-json\/wp\/v2\/comments?post=927"}],"version-history":[{"count":8,"href":"https:\/\/heyyocg.link\/wp-json\/wp\/v2\/posts\/927\/revisions"}],"predecessor-version":[{"id":1480,"href":"https:\/\/heyyocg.link\/wp-json\/wp\/v2\/posts\/927\/revisions\/1480"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/heyyocg.link\/wp-json\/wp\/v2\/media\/712"}],"wp:attachment":[{"href":"https:\/\/heyyocg.link\/wp-json\/wp\/v2\/media?parent=927"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/heyyocg.link\/wp-json\/wp\/v2\/categories?post=927"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/heyyocg.link\/wp-json\/wp\/v2\/tags?post=927"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}