tag:blogger.com,1999:blog-348558957198280902024-03-18T08:33:41.511+05:30Unreal PossibilitiesRohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.comBlogger77125tag:blogger.com,1999:blog-34855895719828090.post-46002856548041483702023-07-21T16:55:00.062+05:302023-10-13T11:53:22.845+05:30Tower Defense Starter Kit Tutorial: How to create new Towers<p><span style="font-family: helvetica; font-size: medium;">[<i>This tutorial is based on v2.30 edition of the toolkit, but should work for later versions as well. For previous versions of the toolkit, <span><span><span>you can follow this tutorial: <a href="https://docs.google.com/document/d/1Et1PXlQ8xJ6n0q5Ok8BiYYpJ5BwwLdIvSC3cbuqmOPM/edit?usp=sharing">https://docs.google.com/document/d/1Et1PXlQ8xJ6n0q5Ok8BiYYpJ5BwwLdIvSC3cbuqmOPM/edit?usp=sharing</a>.</span></span></span></i></span></p><p><span style="font-family: helvetica; font-size: medium;"><span><span><span><i>If you're unsure about what version of the toolkit you're using, you can find this information under Edit >> Project Settings >> Description >> Project Version.</i>]<br /></span></span></span></span></p><p><span style="font-family: helvetica; font-size: medium;"><span><span>1. First <b>create a new child blueprint based on BP_Tower_Parent</b>.</span></span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica; font-size: medium;"><span><span><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiu9Y85xRErEf2MRGg3_M6wYclbQClVpGuZisxy8Vgflwp3NdLu48nIHV4ox-p6UDrCOH47gsiVDnJvu-lR1C1Hun89VO-rZcdulF97ZAWJ6GhD4cZaJWfZq53haZgx8cwYgtQ_lBiSqq6IWbhl4tvgIjY5s_vHdoRU2ux-piEhuTafMTjn0-5pZQcHdIs/s1920/newtowerchild.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiu9Y85xRErEf2MRGg3_M6wYclbQClVpGuZisxy8Vgflwp3NdLu48nIHV4ox-p6UDrCOH47gsiVDnJvu-lR1C1Hun89VO-rZcdulF97ZAWJ6GhD4cZaJWfZq53haZgx8cwYgtQ_lBiSqq6IWbhl4tvgIjY5s_vHdoRU2ux-piEhuTafMTjn0-5pZQcHdIs/s320/newtowerchild.png" width="320" /></a></span></span></span></div><p><span style="font-family: helvetica; font-size: medium;"><span><span>2. Open the newly created Tower blueprint, and <b>set a new custom static mesh for your Tower</b>.</span></span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica; font-size: medium;"><span></span></span></div><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica; font-size: medium;"><span><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCzdemVD6C8iKG_vaAXHRbYX8jA3tSc7pUk-eZ1RHTrNXvhrJHcbntP6asyBSdWngYfxUZnwQjaBhTj-lDcPGFws6G8FxUYy2BijCH8bZ9ABFt_zrJ8XYJ5dNXAqlYZaHaML8N36rUM3VVT8mri7VEan43cXau0w1I4-bJFbeHXtR7pJn0BOz-oSEbAOA/s1920/newtowermesh.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCzdemVD6C8iKG_vaAXHRbYX8jA3tSc7pUk-eZ1RHTrNXvhrJHcbntP6asyBSdWngYfxUZnwQjaBhTj-lDcPGFws6G8FxUYy2BijCH8bZ9ABFt_zrJ8XYJ5dNXAqlYZaHaML8N36rUM3VVT8mri7VEan43cXau0w1I4-bJFbeHXtR7pJn0BOz-oSEbAOA/s320/newtowermesh.png" width="320" /></a></span></span></div><p><span style="font-family: helvetica; font-size: medium;"><span><span><b>Optionally, you can also set a custom static mesh for the Turret component</b> if the gun is separate from your base Tower mesh.<br /></span></span></span></p><p><span style="font-family: helvetica; font-size: medium;"><span><span>3. </span></span></span><span style="font-family: helvetica; font-size: medium;"><span><span>Head over to the Weapons folder and create a child blueprint based on <b>BPC_WeaponSystem</b>.</span></span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica; font-size: medium;"><span><span><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMkLTjYScsLWefFSvB_GVEoo0okadTHUdX1XiwQd5sY7yD_mdLzikfnykqy8q5w1thF_W39vFKmkwjuIiVUOZvaKFrV8RdPLDbyf3xhmQOHJoGG0VrSmcqgyDyQAhHpMxlWknbfk6sQz2eakH7X2ui84YllzzzaltpKf_vRSKX55xqpPBjc4VQ59rcBFE/s1920/newweaponcomp.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMkLTjYScsLWefFSvB_GVEoo0okadTHUdX1XiwQd5sY7yD_mdLzikfnykqy8q5w1thF_W39vFKmkwjuIiVUOZvaKFrV8RdPLDbyf3xhmQOHJoGG0VrSmcqgyDyQAhHpMxlWknbfk6sQz2eakH7X2ui84YllzzzaltpKf_vRSKX55xqpPBjc4VQ59rcBFE/s320/newweaponcomp.png" width="320" /></a></span></span></span></div><p><span style="font-family: helvetica; font-size: medium;"><span><span>As
the name suggests, this component handles the firing systems for the
Tower. As an optional step, you can then move this new component to
Towers >> WeaponSystems folder since that's where you can find all the default tower weapon system components that comes with the toolkit.</span></span></span><span style="font-family: helvetica; font-size: medium;"><span><span> </span></span></span></p><p><span style="font-family: helvetica; font-size: medium;"><span><span>4. Now what we do next depends on what kind of Tower you want to create. If the tower firing behavior involves locking on to and firing at a single target at a time (<i>eg: Machine Gun Tower</i>), then we want to override the <b>FireAtTarget </b>function within the new weapon system component we created in previous step. On the other hand, if you want to create a Tower that does AoE damage to all units in range (<i>eg: Shockwave Tower</i>), then we want to override the <b>FireAtTargets </b>function.</span></span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica; font-size: medium;"><span><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2zN5yonpd9SGMK4WfLnKcdZnq4F8nMRWI0cgtqRfyc5t7yyNh36cUFZjmSes2NBRIYpFEQ0ioBFxq8elReKJGA1Y8PFoUuSZNBt2Iw2bUtBof7Dfvah_e6fe62gGmkC_FdAvb47a4cjUsruNy7NiMBwMrSNzXw0GFyPvA2JBjzM0bpeA2VSwCs1mZYnQ/s1920/weaponfireoverridestart.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2zN5yonpd9SGMK4WfLnKcdZnq4F8nMRWI0cgtqRfyc5t7yyNh36cUFZjmSes2NBRIYpFEQ0ioBFxq8elReKJGA1Y8PFoUuSZNBt2Iw2bUtBof7Dfvah_e6fe62gGmkC_FdAvb47a4cjUsruNy7NiMBwMrSNzXw0GFyPvA2JBjzM0bpeA2VSwCs1mZYnQ/s320/weaponfireoverridestart.png" width="320" /></a></span></span></div><p><span style="font-family: helvetica; font-size: medium;"><span>For this tutorial, I'm going to go ahead and override the FireAtTarget function as shown below: <br /></span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica; font-size: medium;"><span><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9VAuXdW_8UvBykPDTTUTbi6QQhkMsXo8OSs7PcgRk4onLG4Y7da_4S6tUN6VyWVLnBD28eIsq3XolmDCy-iD0EVmd5Hefkcqx6iB0PedY2KlMJfvynPDfnH9fx2HzpCnLoDvFwYVkilVaGKG6fRNSV9Jf3-qw7JdowWm8qsAljO-zvoxhzG1sQNsn16c/s1920/firelpattargeteg.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9VAuXdW_8UvBykPDTTUTbi6QQhkMsXo8OSs7PcgRk4onLG4Y7da_4S6tUN6VyWVLnBD28eIsq3XolmDCy-iD0EVmd5Hefkcqx6iB0PedY2KlMJfvynPDfnH9fx2HzpCnLoDvFwYVkilVaGKG6fRNSV9Jf3-qw7JdowWm8qsAljO-zvoxhzG1sQNsn16c/s320/firelpattargeteg.png" width="320" /></a></span></span></div><p><span style="font-family: helvetica; font-size: medium;"><span><span>You can write your own custom firing logic here based on the kind of Tower you had in mind. <br /></span></span></span></p><p><span style="font-family: helvetica; font-size: medium;"><span><span>I'd also suggest checking out the FireAtTarget/Targets functions within the default weapon system components to study the firing solution implementations for other Towers. As starter examples</span></span></span><span style="font-family: helvetica; font-size: medium;"><span><span>, BPC_WeaponSystem_Hitscan and
BPC_WeaponSystem_SphericalAoEBlast components are quite straightforward
and easy to understand.</span></span></span></p><p><span style="font-family: helvetica; font-size: medium;"><span><span>5. With the firing logic taken care of, the next step is to set up the high level behavior of the weapon system. Like what kind of targeting model is being used to track targets, whether it can fire continuously, and the firing trajectory used to reach the intended target. The code for these are all implemented already, so we just need to specify the type so that the Tower knows what to do. For this, select Class Defaults from the top toolbar, then go to the Config section under the Details Panel, and set these three parameters as per your requirements.</span></span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica; font-size: medium;"><span><span><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVTT0gvUh4C-nXoYny0_lrNygisSlXyqJbaNkhCvMeTnt-Sxyx5TMebRbacoxBH176vvSKWGSLWpcE9aY16qXTxsLuaL7Q4mcM71sEaVeHpUo5LDLqPfcICwrKKuhW5Y5ajwVTcUQtfzBgpy5j7jGUqMxDZwlQHcbH90I_bJUBNY13WcCyB9mrIuKYMr4/s1920/weaponconfig.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVTT0gvUh4C-nXoYny0_lrNygisSlXyqJbaNkhCvMeTnt-Sxyx5TMebRbacoxBH176vvSKWGSLWpcE9aY16qXTxsLuaL7Q4mcM71sEaVeHpUo5LDLqPfcICwrKKuhW5Y5ajwVTcUQtfzBgpy5j7jGUqMxDZwlQHcbH90I_bJUBNY13WcCyB9mrIuKYMr4/s320/weaponconfig.png" width="320" /></a></span></span></span></div><p><span style="font-family: helvetica; font-size: medium;"><span><span>5. </span></span>Finally, <b>we are going to create child components based on the custom Weapon System component that we just created</b>, such that there is one child for each Tower that uses this weapon system. Say, for example, if a Machine Gun Tower and all its upgrades use the same weapon system, then we'd want to create a child weapon system component for each of its upgrade level as shown in the next screenshot:</span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-size: medium;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYs8zxIIfCu7Cv986tZk20jRdLizKa4VRD8OdHxvhGy2uXNyFj5t7bQfDortBX_EFb-jFg9ibf8NVmg80qUCbdHArs_HkiJy8YAHOE_iTiCDEC3axDY6lXeWuAFBxxDIJY7fLsaWdUEnqyT4bsioj4JQj8jceUAn8PQ3uTWWkIPTewrcSbDGJjGVbLjYU/s2560/mgweaponchild.png" style="font-family: helvetica; margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1440" data-original-width="2560" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYs8zxIIfCu7Cv986tZk20jRdLizKa4VRD8OdHxvhGy2uXNyFj5t7bQfDortBX_EFb-jFg9ibf8NVmg80qUCbdHArs_HkiJy8YAHOE_iTiCDEC3axDY6lXeWuAFBxxDIJY7fLsaWdUEnqyT4bsioj4JQj8jceUAn8PQ3uTWWkIPTewrcSbDGJjGVbLjYU/s320/mgweaponchild.png" width="320" /></a></span></div><p><span style="font-family: helvetica; font-size: medium;">Now we can go into each of these child components and <b>set up unique weapon stats on each of them through the variables listed under Stats >> Base category</b> as shown below:</span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-size: medium;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiNP0VbKQevrkFIqjgyGyvoGF1XNv9xqULUm-3W8LO1B7oMxPrNMVXAUY7HdBoV2YgCQE3VsWZZ4PiByOcfdRZzzm4VHlCvWCuwkwLwDdjMAjVJ8qG0IAv6eItLYTKL7KXZxAoS0TbTtQc6AxC_ZLa-pt3axkH67tZS_gUibIcgW_aAN7vIhg6-yzAY0E/s2560/weaponbasestats.png" style="font-family: helvetica; margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1440" data-original-width="2560" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiNP0VbKQevrkFIqjgyGyvoGF1XNv9xqULUm-3W8LO1B7oMxPrNMVXAUY7HdBoV2YgCQE3VsWZZ4PiByOcfdRZzzm4VHlCvWCuwkwLwDdjMAjVJ8qG0IAv6eItLYTKL7KXZxAoS0TbTtQc6AxC_ZLa-pt3axkH67tZS_gUibIcgW_aAN7vIhg6-yzAY0E/s320/weaponbasestats.png" width="320" /></a></span></div><p><span style="font-family: helvetica; font-size: medium;">6. <span><span><span>Next, open the enumeration <b>ETowerModels </b>and add a new entry for your new Tower.</span></span></span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica; font-size: medium;"><span><span><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQzXEbxY3E5b-9pMbH4RFjh85HbPZRxy5QY6qhMOV2udikGE-88-yyaVDzS0Zp45QKhFvvrn3nQQOC1k7JGEXXzGqD54MAAP_b0Hhto35uaQgyK30WH6ds7409Cjm6WXR_qgo0dCk4yg1Ocw9NcsnrbNJI96HYFTl7y4De5DFF1M7Tlx8kIeQ-ZKMTOIY/s1920/tuttowerenum.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQzXEbxY3E5b-9pMbH4RFjh85HbPZRxy5QY6qhMOV2udikGE-88-yyaVDzS0Zp45QKhFvvrn3nQQOC1k7JGEXXzGqD54MAAP_b0Hhto35uaQgyK30WH6ds7409Cjm6WXR_qgo0dCk4yg1Ocw9NcsnrbNJI96HYFTl7y4De5DFF1M7Tlx8kIeQ-ZKMTOIY/s320/tuttowerenum.png" width="320" /></a></span></span></span></div><p><span style="font-family: helvetica; font-size: medium;"><span><span>7. </span></span></span><span style="font-family: helvetica; font-size: medium;"><span><span>The stats for all Towers in the toolkit are set through data table entries. So we're going to open the data table <b>DT_TowerData </b>and add a new entry for our Tower here.</span></span></span></p><p><span style="font-family: helvetica; font-size: medium;"><span><span></span></span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica; font-size: medium;"><span><span><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFxE_RlxT5MdeDUcEPHVR2XJVo7EUs7ft5Y680TSI9XpYGEHItjY0EO21zDnK57YBmFeS0kUP00jdUnh_u7zCHXQHx0FA_VtZ9s4xKTKr2uNl0_IWcNcep6-nHqqn40eVA0vksNZwBrGng3ugyWGQqVJRUSszz2ff5v2IxEvO8P8O2u2j9m8BeYtzttJM/s2560/towerdtstats.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1440" data-original-width="2560" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFxE_RlxT5MdeDUcEPHVR2XJVo7EUs7ft5Y680TSI9XpYGEHItjY0EO21zDnK57YBmFeS0kUP00jdUnh_u7zCHXQHx0FA_VtZ9s4xKTKr2uNl0_IWcNcep6-nHqqn40eVA0vksNZwBrGng3ugyWGQqVJRUSszz2ff5v2IxEvO8P8O2u2j9m8BeYtzttJM/s320/towerdtstats.png" width="320" /></a></span></span></span></div><p></p><p><span style="font-family: helvetica; font-size: medium;"><span><span>Make sure to set the "WeaponSystem" parameter to match the weapon system component associated with the Tower. It will automatically handle spawning in the component when the Tower is constructed during gameplay. <br /></span></span></span></p><p><span style="font-family: helvetica; font-size: medium;">9. </span><span style="font-family: helvetica; font-size: medium;"><span><span>Finally select the <b>BP_TowerManager </b>actor from your level and the new Tower enum entry to its <b>BaseTowerModels </b>array from the details panel.</span></span></span></p><p><span style="font-family: helvetica; font-size: medium;"><span><span></span></span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica; font-size: medium;"><span><span><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUUy45qieWI-akijC1cfwAL8cAoew5pvkGn1iG2mx85GC5VjUpdlNRFHF-7yuIBcHbS8ciHG37sb95RRblLD_d3QrId0nLmadj4_-K3U2OtQoogUTtXju4NQhqe-wJrSU41WgDVaYGHZgA_UQjKNal_Sqv3mRl_TnMwmyYXyOYuqiG03L5JF4l-YNym-g/s1920/basetowermodelstut.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUUy45qieWI-akijC1cfwAL8cAoew5pvkGn1iG2mx85GC5VjUpdlNRFHF-7yuIBcHbS8ciHG37sb95RRblLD_d3QrId0nLmadj4_-K3U2OtQoogUTtXju4NQhqe-wJrSU41WgDVaYGHZgA_UQjKNal_Sqv3mRl_TnMwmyYXyOYuqiG03L5JF4l-YNym-g/s320/basetowermodelstut.png" width="320" /></a></span></span></span></div><p><span style="font-family: helvetica; font-size: medium;"><span><span><br /></span></span></span><span style="font-family: helvetica; font-size: medium;"><span><span>And
that's it. You have now created your very own Tower. All the UI changes
and stats will all be set directly from the data table. So you don't
have to worry about going around making those changes. If you have any
doubts regarding the workflow, just let me know in the comments, and I'd
be happy to help.</span></span></span></p><p></p>Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com0tag:blogger.com,1999:blog-34855895719828090.post-15059013799840063642023-07-08T17:26:00.006+05:302023-07-11T17:44:54.912+05:30Tower Defense Starter Kit: How to assign Hotkeys to Global Abilities<p><span style="font-family: helvetica;">The Tower Defense Starter Kit comes equipped with a host of Global Abilities that can be activated by the player during gameplay. As of the v2.27 edition, the toolkit contains the following abilities: Airstrike, Tower Guardians, Proximity Mine, and Regen Field.</span></p><p><span style="font-family: helvetica;">By default, using these abilities require first selecting the required ability through the Global Ability buttons displayed on the bottom left corner of the screen and then activating the selected ability by targeting an appropriate location on the map. This tutorial aims to provide you with the steps required to implement hotkey support for quickly selecting the global abilities.</span></p><p><span style="font-family: helvetica;">1. First open up the <b>Widget_GlobalAbilityButton </b>blueprint and add the following nodes:</span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6hHr3x5jZ-gL8HK6AZ2OMNe-3qNI5EGwmQU_qaxEqgP6uGEziU7TXyjyskr3kEXTAxCS0j3OSJV4eWDzGW8T6cIeKIfyhGClqGN14dy_kawdhwHLaoHLW6YS7DGF49SFeGDPcbIIsmP9goHTrnIF-Cn2OEsB554ND7x5VU06tVhDavQEaovG-o3xq70I/s1920/gahotkeygating.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6hHr3x5jZ-gL8HK6AZ2OMNe-3qNI5EGwmQU_qaxEqgP6uGEziU7TXyjyskr3kEXTAxCS0j3OSJV4eWDzGW8T6cIeKIfyhGClqGN14dy_kawdhwHLaoHLW6YS7DGF49SFeGDPcbIIsmP9goHTrnIF-Cn2OEsB554ND7x5VU06tVhDavQEaovG-o3xq70I/s320/gahotkeygating.png" width="320" /></a></span></div><p></p><p><span style="font-family: helvetica;">This event will help us directly control the ability button selection states without requiring the player to click on the button.</span></p><p><span style="font-family: helvetica;">2. Now head over to the <b>Widget_GlobalAbilities </b>blueprint and add the following function to it:</span></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiI4oMNjhyAIERqjmEIkP7yJDdcYBwmkHdtNF38I4IFYEzw465S_2EQf8hsu4i4SLdUP8FwTtytpg6ytvLZwjLkcNMxQLSB5yXCwSoA9BdVWdMxx_mSzCgDnzuncaw6ecFpy_XJiWRUpY7UsikgIIu-s1m-23erw6613_b9AklRgGYFPANpV0m6RA_l4yc/s1920/gacontainertobtnaccess.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiI4oMNjhyAIERqjmEIkP7yJDdcYBwmkHdtNF38I4IFYEzw465S_2EQf8hsu4i4SLdUP8FwTtytpg6ytvLZwjLkcNMxQLSB5yXCwSoA9BdVWdMxx_mSzCgDnzuncaw6ecFpy_XJiWRUpY7UsikgIIu-s1m-23erw6613_b9AklRgGYFPANpV0m6RA_l4yc/s320/gacontainertobtnaccess.png" width="320" /></a></div><br /><span style="font-family: helvetica;">This blueprint essentially acts as a container for displaying all the global abilities in the player's arsenal during gameplay. And the new function we're adding here will lets us access the ability buttons using indices associated with our ability hotkeys.</span><p></p><p><span style="font-family: helvetica;">3. Now that we've covered the changes to the UI part of the workflow, we'll need to add the logic to call these UI changes. So copy the event shown below into the <b>BP_PlayerController</b> blueprint.</span></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhI37VCVhYhnILZ3-AERz4qiK76pkGmWy5qoyNfZr1lg8WqZuWVo1w6xtVjQtmrYQVEb_Upc8231rdB5kFLCH2t7L-f68KZMMRRLYGasGA31abIteo0vFkMLwGmoR3k_8cNinNm99DIYcI0eAelu9_ZFG_MvQDfWB50YNaXzKRFwlxoL_9cxlF6EOcNfP0/s1920/playerconabilityslotsel.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhI37VCVhYhnILZ3-AERz4qiK76pkGmWy5qoyNfZr1lg8WqZuWVo1w6xtVjQtmrYQVEb_Upc8231rdB5kFLCH2t7L-f68KZMMRRLYGasGA31abIteo0vFkMLwGmoR3k_8cNinNm99DIYcI0eAelu9_ZFG_MvQDfWB50YNaXzKRFwlxoL_9cxlF6EOcNfP0/s320/playerconabilityslotsel.png" width="320" /></a></div><br /><span style="font-family: helvetica;">4. Before finally adding the input controls, we'll first add input mappings for our ability hotkeys through the Input section under Project Settings.</span><p></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYgm4cOc_OWEDiIbXDLxHqVNhJvSnCTRDtFgSsigPNKswzPGMHZo8c7-62txvWdB14KHt7Y4z6d_DjXMEtFDkBIOdbqfh934Z2KCKK8FLr39_n_OL58HvkZ7_Vvn0QOkcaZbp8-jWpCYTs3rECyTS28nS6cq4cFVTMFw0dZFS_dfihbP9fMb8qjPkaPgk/s1920/abilitykotkeymap.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYgm4cOc_OWEDiIbXDLxHqVNhJvSnCTRDtFgSsigPNKswzPGMHZo8c7-62txvWdB14KHt7Y4z6d_DjXMEtFDkBIOdbqfh934Z2KCKK8FLr39_n_OL58HvkZ7_Vvn0QOkcaZbp8-jWpCYTs3rECyTS28nS6cq4cFVTMFw0dZFS_dfihbP9fMb8qjPkaPgk/s320/abilitykotkeymap.png" width="320" /></a></div><br /><span style="font-family: helvetica;">5. And now for the final step, just add the input events for these hotkeys in the <b>BP_PlayerPawn </b>blueprint and have them call the event we added in player controller. Also make sure to start the indices for your abilities from 0 instead of 1 since we're essentially using it to access an array of widgets.<br /></span><p></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOkMKGhlvduAeHmWqVD1ac_j164_6koTLfR31vfMqqrXFtuI4wzA2ABKxl6u95P3A3yvB7_Vr5kGFiTstOnTG32R2AHqVwSJp5-VOtTzemORYBuGyTDosRCxYCvbE0PtCgvW7Bs5-VxJuMR4ChHb5qPnrxE2InSWpGhAHOu9m_gyqyDc5Iszq6JN2KS-Q/s1920/gahotkeyinputevents.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOkMKGhlvduAeHmWqVD1ac_j164_6koTLfR31vfMqqrXFtuI4wzA2ABKxl6u95P3A3yvB7_Vr5kGFiTstOnTG32R2AHqVwSJp5-VOtTzemORYBuGyTDosRCxYCvbE0PtCgvW7Bs5-VxJuMR4ChHb5qPnrxE2InSWpGhAHOu9m_gyqyDc5Iszq6JN2KS-Q/s320/gahotkeyinputevents.png" width="320" /></a></div><br /><span style="font-family: helvetica;"></span><p></p><p><span style="font-family: helvetica;">Alright, that's all there is to it. Now you should be able to select global abilities in your game directly through your assigned hotkeys. Pressing the same hotkey again should also stop the ability targeting process since we're using already existing code to handle that. So there is no need to write any additional code for that. And if you have any doubts regarding the workflow, feel free to reach out through the comments section.</span><br /></p>Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com0tag:blogger.com,1999:blog-34855895719828090.post-26129408633539596372022-08-19T14:21:00.002+05:302022-08-19T14:21:16.251+05:30Why I reverted back to Unreal's native damage framework in Tower Defense Starter Kit<p><span style="font-family: helvetica;">I've been using a custom Damage Interface to handle all damage events in the Tower Defense Starter Kit. This interface was added a few years ago to enable for support additional parameters like Critical hit damage and Critical chance to be passed on as part of the damage application process. But in the latest <a href="https://forums.unrealengine.com/t/tower-defense-starter-kit/57044/361" target="_blank">v2.22 update</a> for Tower Defense Starter Kit, I finally reverted back to the Unreal Engine's inbuilt damage system.<br /></span></p><p><span style="font-family: helvetica;">The primary reason for this change was driven by the fact that <b>Unreal's native damage framework provides us with an easy and straightforward solution to use Event Dispatchers for listening to and responding to damage events</b>.<br /></span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrtuEfilPSLKE_50L0Q1sF8ZKGu2gdJbj9-zyZsgGTtMLOZCOMma6OjStxFvaaHXYqo96HG0rowgOAa4uEz6CTmBua0xdbSrRJXsAgxxI0qYGZLOqQ1hgSTjV6VGn3wcBX9fOtK0MOk9_5lNLZFtfRm2gyJCHJ3iXjQUST2PsQu3EvTyN-zSwU-FJk/s1920/eddmg.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrtuEfilPSLKE_50L0Q1sF8ZKGu2gdJbj9-zyZsgGTtMLOZCOMma6OjStxFvaaHXYqo96HG0rowgOAa4uEz6CTmBua0xdbSrRJXsAgxxI0qYGZLOqQ1hgSTjV6VGn3wcBX9fOtK0MOk9_5lNLZFtfRm2gyJCHJ3iXjQUST2PsQu3EvTyN-zSwU-FJk/s320/eddmg.png" width="320" /></a></div><p></p><p><span style="font-family: helvetica;">While it is definitely possible to add in new damage event dispatchers to the toolkit, it comes with the drawback of requiring both the Tower and Wave AI classes to have their own unique event dispatchers. Which means, any object that wants to be registered as an observer will first need to do a cast operation to access the dispatcher. <b>If on the other hand, we were to use Unreal's native damage framework, there would be no need to add new dispatchers for each parent class nor would the cast operation be required in order to access the event dispatcher</b>.<br /></span></p><p><span style="font-family: helvetica;">So I started looking for ways to incorporate the critical hit data as well as any other future requirements like say elemental damage types into Unreal's native damage model. I figured that critical hits could be handled in one of two ways: either create a new actor component to handle all damage related calculations including critical hits, or create a global function in a blueprint function library to calculate critical damage. Since I was not keen on having an additional component in every single Wave AI and Tower actor just for this purpose, I decided to go ahead with the later option. So now I just <b>call the aforementioned global function to calculate the critical hit damage first before passing it on to the Apply Damage function</b> as shown below:</span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuMz-h5sA7q5E7tsggxyLjCYyQHlR5N8AJf-2sZLkGSyGBveOElWPAK7yJbUy2B3Mo_R1iR09WMiT7169_fufjr08HitXp5KyYECMT-v5H7BOHs8Y47MJa1ofnxdXpJdIp4DojBehVnCyHYDotRwduHuYcP38fArPZaxARtOHHJ0xRS_O5NGZURsKt/s1920/calccritdmg.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuMz-h5sA7q5E7tsggxyLjCYyQHlR5N8AJf-2sZLkGSyGBveOElWPAK7yJbUy2B3Mo_R1iR09WMiT7169_fufjr08HitXp5KyYECMT-v5H7BOHs8Y47MJa1ofnxdXpJdIp4DojBehVnCyHYDotRwduHuYcP38fArPZaxARtOHHJ0xRS_O5NGZURsKt/s320/calccritdmg.jpg" width="320" /></a></div><p></p><p><span style="font-family: helvetica;">As mentioned earlier, I want this to be scalable with my future plans for <a href="https://www.unrealengine.com/marketplace/en-US/product/tower-defense-starter-kit" target="_blank">Tower Defense Starter Kit</a>, including the idea of introducing Elemental Damage Types to the toolkit. After giving it some thought, I believe that it can be easily achieved through the use of Unreal's Damage Type classes, which can be passed through the Apply Damage function. So I'm really hoping to get around to fleshing out the damage framework once </span><span style="font-family: helvetica;">I wrap up work on the Hero system.</span></p>Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com0tag:blogger.com,1999:blog-34855895719828090.post-12559249469780047552022-08-09T10:53:00.002+05:302022-08-09T22:06:34.575+05:30Introducing Hero units to Tower Defense Starter Kit<p><span style="font-family: helvetica;">Heroes in <a href="https://www.unrealengine.com/marketplace/en-US/product/tower-defense-starter-kit" target="_blank">Tower Defense Starter Kit</a> are special units that can be controlled by the player and can be given orders to move around the map. This makes them more versatile than the Tower Guardians which are temporarily spawned reinforcement units that can only defend the area around their spawn location.</span></p><p><span style="font-family: helvetica;">The Hero unit was first added in the <a href="https://forums.unrealengine.com/t/tower-defense-starter-kit/57044/343" target="_blank">v2.20 update</a> for Tower Defense Starter Kit and has since received additional features including a <a href="https://forums.unrealengine.com/t/tower-defense-starter-kit/57044/358" target="_blank"><b>dedicated UI button for player interaction</b></a>, a <b>cooldown based respawning system</b>, and a <a href="https://forums.unrealengine.com/t/tower-defense-starter-kit/57044/361" target="_blank"><b>passive health regeneration</b></a> ability.</span></p><p><span style="font-family: helvetica;"></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6YxJPwzoAlaSJfrRBmGJ-kjpcWefsjWjF0q0RvuwbFqQl3cVjfuLam2lhHcBoNpjEtYMYcvU42eRkMCMwXwvI35VLXw0JV2RSVnudxV0RLo6EJWAucx-Hs6P3UWUcqltdtqlzhw48-iEtF7MnZN-Efoln7fJrtkK5OLZVqGrWy08OoICke-XG60l0/s800/hero1.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="450" data-original-width="800" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6YxJPwzoAlaSJfrRBmGJ-kjpcWefsjWjF0q0RvuwbFqQl3cVjfuLam2lhHcBoNpjEtYMYcvU42eRkMCMwXwvI35VLXw0JV2RSVnudxV0RLo6EJWAucx-Hs6P3UWUcqltdtqlzhw48-iEtF7MnZN-Efoln7fJrtkK5OLZVqGrWy08OoICke-XG60l0/s320/hero1.gif" width="320" /></a></span></div><span style="font-family: helvetica;"><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj026RT0pXuCWR-8AfqqbvxXMeD5xoht8Rbd9t1EY9itPo8YeqfvWjLjKOByHNwOu6sWemqsKPD8l0JRzFlWEG5fjDuHmpq8FL7u7Gk5nBt9N8BTkrnJnJlmZ_qXhO6D8-KlSeLR3YezHv9QzSwUs-elRnpwHs2lvsBF_1sAI5zdJWCgOGYcYld3CpJ/s600/hero2.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="338" data-original-width="600" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj026RT0pXuCWR-8AfqqbvxXMeD5xoht8Rbd9t1EY9itPo8YeqfvWjLjKOByHNwOu6sWemqsKPD8l0JRzFlWEG5fjDuHmpq8FL7u7Gk5nBt9N8BTkrnJnJlmZ_qXhO6D8-KlSeLR3YezHv9QzSwUs-elRnpwHs2lvsBF_1sAI5zdJWCgOGYcYld3CpJ/s320/hero2.gif" width="320" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5QB4nJ851cGBoQzB84ltM3bk9dmZRlmoM0IGwXyYw5b1dd07SPo9GhTHXafrTlx7bHeSKjrVhacvn64UuEPcd06ylH76SJPlhfZ3xtD8Og-8mjIJ-TnD69zkBZ4frmUYdoNH_Ki4RDav2SWiKEZ0dXOTbnepo5dFZrUpvy6E2aQEtdwzWfklGIqWD/s600/hero3.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="338" data-original-width="600" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5QB4nJ851cGBoQzB84ltM3bk9dmZRlmoM0IGwXyYw5b1dd07SPo9GhTHXafrTlx7bHeSKjrVhacvn64UuEPcd06ylH76SJPlhfZ3xtD8Og-8mjIJ-TnD69zkBZ4frmUYdoNH_Ki4RDav2SWiKEZ0dXOTbnepo5dFZrUpvy6E2aQEtdwzWfklGIqWD/s320/hero3.gif" width="320" /></a></div></span><p></p><p><span style="font-family: helvetica;">The 2.20 edition of Tower Defense Starter Kit also introduced a dedicated Hero Manager class that serves a purpose similar to that of the Tower Manager for Towers. <b>The Hero Manager is an actor class blueprint that can be added to your map and contains parameters for customizing the Hero class as well as their respawn times.</b></span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgamksYsOGv9ADqNituKWrGsIeeMp6lVUG1UH5uBz-jHm9aQM2LGuWfKWYOLbyIzZ2GWOAU1tOSnB6QPJhOwkhMcROC94-rFPNEDMR6cSsYfspEBugVAmbmYQ7mdF8rlGrAMMLI6vYPdDt2o87wffLPp-zr_BTxe7zSlW4_Si9UuvG_CCytsxvQ7X8Q/s1920/hmparacust.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgamksYsOGv9ADqNituKWrGsIeeMp6lVUG1UH5uBz-jHm9aQM2LGuWfKWYOLbyIzZ2GWOAU1tOSnB6QPJhOwkhMcROC94-rFPNEDMR6cSsYfspEBugVAmbmYQ7mdF8rlGrAMMLI6vYPdDt2o87wffLPp-zr_BTxe7zSlW4_Si9UuvG_CCytsxvQ7X8Q/s320/hmparacust.png" width="320" /></a></div><h4 style="text-align: left;"><span style="font-family: helvetica;">Creating your own custom Hero Unit</span></h4><p style="text-align: left;"><span style="font-family: helvetica;">1. Create a new child class from <b>BP_FriendlyAI_Hero</b>.</span></p><p style="text-align: left;"><span style="font-family: helvetica;"></span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvDpKbcmnyh6BMYYUeTSnwR-mTa2r-ih5tZvnW7z2LMoJBsiy7YtE2EWqFjpD-oeDxYVNwGh6kYA5gQdBy0DbL60BPsBlaqjxiwJS-4DNDLpbxZgtDKPWfycFW_MvqStf7xAg47OWWuHRIAUd-ySo0waKJ8BHYcI1KyIb2B66bNQj0VI2fi8BpeXYK/s1920/herochild.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvDpKbcmnyh6BMYYUeTSnwR-mTa2r-ih5tZvnW7z2LMoJBsiy7YtE2EWqFjpD-oeDxYVNwGh6kYA5gQdBy0DbL60BPsBlaqjxiwJS-4DNDLpbxZgtDKPWfycFW_MvqStf7xAg47OWWuHRIAUd-ySo0waKJ8BHYcI1KyIb2B66bNQj0VI2fi8BpeXYK/s320/herochild.png" width="320" /></a></div><p style="text-align: left;"><span style="font-family: helvetica;">2. Override the Config variables, character mesh and if required, the default behavior of the BP_FriendlyAI_Hero functions (<i>see screenshot below</i>) in your new child Hero blueprint.</span></p><p style="text-align: left;"></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg84M09Iu-ycIEHH0SIUgdl2hy7KAOqdwBjYrRDFndOtrHFSfEqdfkFbOuhDJR0tkBkuopTU1zFB27nS3DO8sVfdpulZYUmymiAh-HPOgawsPvUt3tW92tMvlPjs2PsTEOk6Vq7DUVYtHQIwX0uPgGYSejLZI-iQjwFLBx6NevPvtj8EpuaM-qc_Res/s1920/heroparent.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg84M09Iu-ycIEHH0SIUgdl2hy7KAOqdwBjYrRDFndOtrHFSfEqdfkFbOuhDJR0tkBkuopTU1zFB27nS3DO8sVfdpulZYUmymiAh-HPOgawsPvUt3tW92tMvlPjs2PsTEOk6Vq7DUVYtHQIwX0uPgGYSejLZI-iQjwFLBx6NevPvtj8EpuaM-qc_Res/s320/heroparent.png" width="320" /></a></div><span style="font-family: helvetica;"></span><p></p><p style="text-align: left;"><span style="font-family: helvetica;">3. Select the Hero Manager from your level and change the Hero class to the new Hero you just created through the drop down menu. You can also move the Hero Manager actor around to set a new spawn location for your Hero unit.</span></p><p style="text-align: left;"></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo8gJzedfgBjYAna4MT0wzavZf7og0lhBZeR2njK9mDAhV0l84JJ0gQkEiDRl2vvQjfb5mEd1YxfNKOGnA2bE2AG-6qy_E0FzmTwluWQ01vLJBtA1qHhZUXyMyzL__aRz2Em-DLnykVKxehmDXEtq3iexoQ35pH3qp0wQf9FXLu4f3DxRuhNWwX98W/s1920/setnewhero.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo8gJzedfgBjYAna4MT0wzavZf7og0lhBZeR2njK9mDAhV0l84JJ0gQkEiDRl2vvQjfb5mEd1YxfNKOGnA2bE2AG-6qy_E0FzmTwluWQ01vLJBtA1qHhZUXyMyzL__aRz2Em-DLnykVKxehmDXEtq3iexoQ35pH3qp0wQf9FXLu4f3DxRuhNWwX98W/s320/setnewhero.png" width="320" /></a></div><p><span style="font-family: helvetica;"></span></p><p><span style="font-family: helvetica;">Now you should have your very own Hero unit ready to fend off the enemy waves. Just click play and you should see the default Hero replaced with your new custom Hero unit.</span></p><p><span style="font-family: helvetica;"></span></p><p><span style="font-family: helvetica;"> </span></p><p><span style="font-family: helvetica;">And with that, we've come to the end of this post. I will be adding more features to flesh out Hero system like for example, the ability to gain experience through combat and level up over time. There are also plans to add a Hero selection panel to the pre mission loadout menu, similar to how loadout selection is handled right now for Towers and Global Abilities. More on that coming soon.</span></p>Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com0tag:blogger.com,1999:blog-34855895719828090.post-67974018673353397582022-07-21T12:39:00.001+05:302022-07-21T12:47:01.107+05:30Final major update for Prototype Menu System<p><span style="font-family: helvetica;">After a long hiatus, I'm finally back to working on my personal projects in Unreal Engine, starting off with a new update for the Prototype Menu System. The project now works natively in Unreal Engine 5.0 and also received a new Audio Options menu to edit and save audio settings. This was accomplished by using Sound Classes to group different sound assets and then applying volume changes to each of those classes as a whole.</span></p><p></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"><iframe allowfullscreen="" class="BLOG_video_class" height="266" src="https://www.youtube.com/embed/LYfJj7jgFyo" width="320" youtube-src-id="LYfJj7jgFyo"></iframe></span></div><span style="font-family: helvetica;"><br /></span><p></p><p><span style="font-family: helvetica;">With the new update, all sounds assets have been grouped into the following categories: <b>Master</b>, <b>Music</b>, <b>Voice</b>, and <b>SFX</b>. The Music, Voice, and SFX classes are child classes of the Master class and hence any volume change applied to the Master class gets applied across all the child classes as well.</span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGNGghP3elxNpNE-nYvkxLJ1q8GRophR8gOG08528qV6C6N5DO_tff7JrsERfOGR8Uw00W7iiEd56lASD0TdeIiOx2eLWgmEW1FbIxwfrlRAE68p2dSb77UCxp7ccF2BijDpOzaGSf8WqpTSTR6yYXHrD0spW6MT9MYRhLceUoSA3RP69-gfzWwZwj/s1920/soundclasses.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGNGghP3elxNpNE-nYvkxLJ1q8GRophR8gOG08528qV6C6N5DO_tff7JrsERfOGR8Uw00W7iiEd56lASD0TdeIiOx2eLWgmEW1FbIxwfrlRAE68p2dSb77UCxp7ccF2BijDpOzaGSf8WqpTSTR6yYXHrD0spW6MT9MYRhLceUoSA3RP69-gfzWwZwj/s320/soundclasses.png" width="320" /></a></div><p></p><p><span style="font-family: helvetica;">The new audio options menu has slider knobs to control volume for each of the aforementioned sound classes as shown below:</span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2v7PR-LlU7GJzlVP8sDU1jw02xDsgaXkxHIMKvZhMr0c2h8HZU4AxNir5JifSz-nWiO3CTOD2cMFPpeMocJN4ThOqA3mWG7pn9b_Ek2vlqrmBla82ZX1Zbbn6uAYDQTjPjbyVyA0und-yCnBoDN81kANaQKPONPvnuurF6IfiRaBVPd4wyG3xl4eL/s1920/volsliders.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2v7PR-LlU7GJzlVP8sDU1jw02xDsgaXkxHIMKvZhMr0c2h8HZU4AxNir5JifSz-nWiO3CTOD2cMFPpeMocJN4ThOqA3mWG7pn9b_Ek2vlqrmBla82ZX1Zbbn6uAYDQTjPjbyVyA0und-yCnBoDN81kANaQKPONPvnuurF6IfiRaBVPd4wyG3xl4eL/s320/volsliders.png" width="320" /></a></div><p></p><p><span style="font-family: helvetica;">Now in order to have these volume changes reflect on custom sound assets in your projects, you'll have to first assign your sound files to one of the aforementioned sound classes. Doing so is as easy as opening the asset from the Content Browser and then setting the Sound Class through the drop down menu as shown below:</span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh88cZTKYdLvPJPmMFY-02KES5ZygGM27Q7YeKp4KLfZ6ZxNDkHK2HjWt9hSfzpjtch8wYDI66ipZfLS7QABPswupK3nWi_dbCXAdEFOXpQqZiZkrfs9ww0rQfY1nbNs7AnHnY5d2uMuVIkBlyQZulq40lnF_8hNd7y9oVkdraksreOUyncsyRZJt3q/s1920/soundcueclass.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh88cZTKYdLvPJPmMFY-02KES5ZygGM27Q7YeKp4KLfZ6ZxNDkHK2HjWt9hSfzpjtch8wYDI66ipZfLS7QABPswupK3nWi_dbCXAdEFOXpQqZiZkrfs9ww0rQfY1nbNs7AnHnY5d2uMuVIkBlyQZulq40lnF_8hNd7y9oVkdraksreOUyncsyRZJt3q/s320/soundcueclass.png" width="320" /></a></div><p></p><p><span style="font-family: helvetica;">Alright, so that's a basic overview on the workings of the new audio control system. This will be final major update for the Prototype Menu System. It might receive a few minor updates (<i>eg: to add numerical value display for volume sliders</i>) in the future, but I think the project is now in a good place with regards to the core feature set that I wanted it to offer.</span></p><p><span style="font-family: helvetica;">The latest version of Prototype Menu System is now available on Github. So feel free to use it in your projects.You can grab the project files from here: <a href="https://github.com/RohitKotiveetil/UnrealEngine--PrototypeMenuSystem" target="_blank">https://github.com/RohitKotiveetil/UnrealEngine--PrototypeMenuSystem</a></span></p>Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com0tag:blogger.com,1999:blog-34855895719828090.post-69944751167076983922021-11-06T16:40:00.002+05:302021-11-06T16:42:13.139+05:30Unreal Engine Tips: How to create slanted Health Bars<p><span style="font-family: helvetica;">The UMG UI Designer in Unreal Engine comes equipped with a variety of tools that can be used to create UI elements for your projects. Among these tools is the Progress Bar widget, which is often used to create Health bars. Simply drag & drop the progress bar into the UI designer and you essentially have a basic Health bar already.<br /></span></p><span style="font-family: helvetica;">But what if we wanted to create a health bar that has a slanted design? Say, for example, something similar to the ones used in Borderlands 3.</span><p><span style="font-family: helvetica;">Fortunately, the same can be achieved in Unreal without writing a single line of code. Under the <b>Render Transform</b> section in the details panel for the Progress Bar widget, is a parameter named <b>Transform</b>. Expand it to reveal the <b>Shear </b>and <b>Angle </b>settings for the widget.</span></p><p><span style="font-family: helvetica;">The Shear controls how slanted the widget is, while the Angle determines its degree of rotation. Here is an example of custom Shear/Angle settings used for Health/Shield bars in one of my projects:</span></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-inEMoXg6XMU/YYZYp4Qh4ZI/AAAAAAAAMSU/t9u3BJRi0BUEtggJ78j0aRTF1uNvcZh9gCLcBGAsYHQ/s1920/swwidget.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://1.bp.blogspot.com/-inEMoXg6XMU/YYZYp4Qh4ZI/AAAAAAAAMSU/t9u3BJRi0BUEtggJ78j0aRTF1uNvcZh9gCLcBGAsYHQ/s320/swwidget.png" width="320" /></a></div><p><span style="font-family: helvetica;"></span></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-H-v68yYoVgQ/YYZZJMma_aI/AAAAAAAAMSc/2m5oGbs1iWwQFAZ4gGjeUK20r7YISQFHACLcBGAsYHQ/s1920/swgameplay.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://1.bp.blogspot.com/-H-v68yYoVgQ/YYZZJMma_aI/AAAAAAAAMSc/2m5oGbs1iWwQFAZ4gGjeUK20r7YISQFHACLcBGAsYHQ/s320/swgameplay.png" width="320" /></a></div><p></p><p><span style="font-family: helvetica;">As you can see, by combining the Shear & Angle settings, you can easily create different types of designs for your health bars. Moreover, its not just limited to progress bars. As far as I know, all user widgets in Unreal have settings to customize their Render Transform. So you can essentially follow the same process to customize all types of widgets.</span><span style="font-family: helvetica;"><br /></span></p><p></p><p></p>Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com0tag:blogger.com,1999:blog-34855895719828090.post-71321100245762752832021-10-05T17:11:00.002+05:302021-11-01T13:06:44.158+05:30Unreal Engine Tips: Use Hotkeys to open assets without Content Browser<p><span style="font-family: helvetica;">The Content Browser in Unreal provides a system for managing assets within the editor. This includes everything from creating new assets, importing external files into the engine, organizing and editing them, etc. The process of editing an asset normally involves heading over to the asset location within the content browser's folder structure and then opening them. But instead of navigating your way across folders to the desired location, there is also an alternative and easier approach to open an asset, provided you have the file name.</span></p><p><span style="font-family: helvetica;">You can simply press <b>Ctrl+P</b> to instantly bring up a dropdown menu that contains a list of all assets in your project. Just search for the filename in its search bar to find the required asset and you can open it directly from here.</span></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-35xGsFrsL-A/YVw34bSgK_I/AAAAAAAAMRM/yi7aTO3UXEkrnZlh-BaYLN773690ts9kACLcBGAsYHQ/s1920/ctrlpanimseq.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://1.bp.blogspot.com/-35xGsFrsL-A/YVw34bSgK_I/AAAAAAAAMRM/yi7aTO3UXEkrnZlh-BaYLN773690ts9kACLcBGAsYHQ/s320/ctrlpanimseq.png" width="320" /></a></div><span style="font-family: helvetica;"></span><p></p><p><span style="font-family: helvetica;">The best part about this method is that you can use it from pretty much anywhere in the Unreal Editor. And it's not limited to any specific type of assets like say blueprints. For example, you can easily jump from a Character blueprint to a material instance, then open up a widget to make changes to the UI, and then bring up an animation sequence to add some notifies. Here are more examples showing it in action.</span></p><p></p><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-Oa9Gqg1k21k/YVw4QL_-C6I/AAAAAAAAMRY/a3Geti6Qs2cxKofarHl4j6UQg4w8zJuiQCLcBGAsYHQ/s1920/ctrlpchar.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://1.bp.blogspot.com/-Oa9Gqg1k21k/YVw4QL_-C6I/AAAAAAAAMRY/a3Geti6Qs2cxKofarHl4j6UQg4w8zJuiQCLcBGAsYHQ/s320/ctrlpchar.png" width="320" /></a></div><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-vRLz7uoT6z4/YVw4fNx39eI/AAAAAAAAMRc/yP8mtCX7WpsQmKwoKvanZBotsc06j3xmgCLcBGAsYHQ/s1920/ctrlpmat.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://1.bp.blogspot.com/-vRLz7uoT6z4/YVw4fNx39eI/AAAAAAAAMRc/yP8mtCX7WpsQmKwoKvanZBotsc06j3xmgCLcBGAsYHQ/s320/ctrlpmat.png" width="320" /></a></div>Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com0tag:blogger.com,1999:blog-34855895719828090.post-56910926943069636312021-08-23T17:13:00.000+05:302021-08-23T17:13:51.456+05:30Unreal Engine blueprints finally gets an "Add Component by Class" function!!<p><span style="font-family: helvetica;">Adding components to an actor at runtime has always been kind of messy if you've been using blueprints in Unreal Engine. There was never a generic function like "Spawn Actor from Class" where you could just happily plug in the required class and be done with it. Instead when it came to components, we always had to specifically add each type of component by name. For example, given below is a scenario where I'm adding a couple of components to provide an actor with Damage Buff and HP Regen abilities: </span></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-QlPJ4WZPK2w/YR5DFR-DYPI/AAAAAAAAMQU/ya8XpiHvT54-7Ihje4i9uRKjrW9eQyRawCLcBGAsYHQ/s1920/219comp.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://1.bp.blogspot.com/-QlPJ4WZPK2w/YR5DFR-DYPI/AAAAAAAAMQU/ya8XpiHvT54-7Ihje4i9uRKjrW9eQyRawCLcBGAsYHQ/s320/219comp.jpg" width="320" /></a></div><p><span style="font-family: helvetica;">As you can see from the screenshot, I'm using an enum to first determine which component has to be added, and then adding the associated component on a case by case basis. This might not seem like an issue here given that we have only two of these, but it feels like redundant busywork once we start dealing with a dozen or more of these components.</span></p><p><span style="font-family: helvetica;">The UE4 blueprint community has been asking for a generic class based component spawning system for quite some time. And finally about a few months back, we got our wish in the form of a new <b>Add Component by Class</b> function.</span></p><p></p><p><span style="font-family: helvetica;">The Add Component by Class as the name suggests lets us spawn in any component by simply specifying the required class. That's it. No longer do we have to add each type of component individually. The process is now just as easy as spawning an actor at runtime. Shown below is an example of the new function in action:</span></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-DJukDQErVkw/YR5EXbbb8vI/AAAAAAAAMQc/Cm17ZDm8VWoHuBa-v9u8dP1CE2rxeMrrACLcBGAsYHQ/s1920/220comp.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://1.bp.blogspot.com/-DJukDQErVkw/YR5EXbbb8vI/AAAAAAAAMQc/Cm17ZDm8VWoHuBa-v9u8dP1CE2rxeMrrACLcBGAsYHQ/s320/220comp.jpg" width="320" /></a></div><p><span style="font-family: helvetica;">U</span><span style="font-family: helvetica;">nlike the previous screenshot, here we have a very straightforward execution flow. No enums, no switch case, and no need to have a whole bunch of add component nodes.</span></p><p></p><p><span style="font-family: helvetica;">When I first noticed this node a few months ago, I was surprised to find no mention of it anywhere in the latest Unreal Engine release notes. But whoever was responsible for adding this node, thanks a lot for exposing this feature to blueprint users.<br /></span></p>Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com0tag:blogger.com,1999:blog-34855895719828090.post-63583642267668527362021-08-12T17:56:00.003+05:302021-08-12T17:58:28.401+05:30Unreal Engine Tips: Change Widget Component's Widget Class at Runtime<p><span style="font-family: helvetica;">The <b>Widget Component</b> in Unreal Engine provides the option of rendering widgets that are attached to an actor in the level. Unlike widgets that are directly drawn on the Player HUD, the widget component can render widgets both on screen space as well as the world space, and can thus be used to create spatial/diegetic UI systems (<i>like in Dead Space</i>). <br /></span></p><p><span style="font-family: helvetica;">Adding a widget component to your actor follows the same process as adding any other component. But once added, it also requires us to set a widget class so that it knows what widget to render. And this is specified through its <b>Widget Class</b> parameter.</span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-Rh07ZVxQ6D0/YRUL4Wu5SaI/AAAAAAAAMPE/agRRrQ1S9H05fKpi2d6dJDX1O599Jem8gCLcBGAsYHQ/s1920/widgetclassdef.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://1.bp.blogspot.com/-Rh07ZVxQ6D0/YRUL4Wu5SaI/AAAAAAAAMPE/agRRrQ1S9H05fKpi2d6dJDX1O599Jem8gCLcBGAsYHQ/s320/widgetclassdef.png" width="320" /></a></div><p></p><p><span style="font-family: helvetica;">Now while the above solution is ideal for specifying a widget in the editor, it doesn't provide us with any means to change the widget at runtime. Fortunately, the widget component has a BP function specifically for this purpose: the <b>Set Widget</b> node.</span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-2iqGIkbraaY/YRUNZ4nPZ8I/AAAAAAAAMPM/S8eLJQRgnys7hIv5dOk5BQ1cT_IrgayOQCLcBGAsYHQ/s1920/setwidget.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://1.bp.blogspot.com/-2iqGIkbraaY/YRUNZ4nPZ8I/AAAAAAAAMPM/S8eLJQRgnys7hIv5dOk5BQ1cT_IrgayOQCLcBGAsYHQ/s320/setwidget.png" width="320" /></a></div><p></p><p><span style="font-family: helvetica;">However, using this Set Widget node is not as straightforward as setting the Widget Class method mentioned earlier. When we specify the widget class in the component details panel, it creates a widget of said class and assigns it to the widget component automatically. So in order to change the widget at runtime, we have to first create the new widget ourselves and then pass it as input when calling the Set Widget function.</span></p><p><span style="font-family: helvetica;"></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"><a href="https://1.bp.blogspot.com/-eVQM6Cn9ceA/YRUOri_kG5I/AAAAAAAAMPU/I5l93glmNWIM-44Rt4qO4NtZKqINAhj5wCLcBGAsYHQ/s1920/createpasswidget.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="180" src="https://1.bp.blogspot.com/-eVQM6Cn9ceA/YRUOri_kG5I/AAAAAAAAMPU/I5l93glmNWIM-44Rt4qO4NtZKqINAhj5wCLcBGAsYHQ/s320/createpasswidget.png" width="320" /></a></span></div><p></p><p><span style="font-family: helvetica;">And that's all there is to it. You should now see the new widget replace the one created by default. Here is an example preview of my widget component changing its widget at runtime:</span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-Wigr6Dmchz4/YRUS2nK7HmI/AAAAAAAAMPc/C-8PGtiiiOEehE1O2zqaRmttVH4-WtfegCLcBGAsYHQ/s800/ezgif.com-gif-maker.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="450" data-original-width="800" height="180" src="https://1.bp.blogspot.com/-Wigr6Dmchz4/YRUS2nK7HmI/AAAAAAAAMPc/C-8PGtiiiOEehE1O2zqaRmttVH4-WtfegCLcBGAsYHQ/s320/ezgif.com-gif-maker.gif" width="320" /></a></div>Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com0tag:blogger.com,1999:blog-34855895719828090.post-15834869924553580712021-05-17T12:55:00.001+05:302021-05-17T12:56:22.016+05:30Moving on from Feedburner<p><span style="font-family: helvetica;">On the 14th of April, this year, Google sent out a notice stating that they will be moving Feedburner on to a new infrastructure in the coming months. And as part of this transition, they're <b>shutting down the Feedburner email subscription services</b>. </span></p><p><span style="font-family: helvetica;"></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"><a href="https://1.bp.blogspot.com/-bAfW-oKfNaM/YKIQykSRtJI/AAAAAAAAMLA/Yp1_FIaTfTQbv2PlXyJJXv-FUzNlDKhYgCLcBGAsYHQ/s1607/fbnot.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="827" data-original-width="1607" src="https://1.bp.blogspot.com/-bAfW-oKfNaM/YKIQykSRtJI/AAAAAAAAMLA/Yp1_FIaTfTQbv2PlXyJJXv-FUzNlDKhYgCLcBGAsYHQ/s320/fbnot.png" width="320" /></a></span></div><p></p><p><span style="font-family: helvetica;">Now I'm not exactly sure what this transition entails for the future of Feedburner, but it got me looking at other options that can provide a wholesome subscription package for my subscribers, while also minimizing the setup cost at my end.</span></p><p><span style="font-family: helvetica;">After going through my options, I've decided to go ahead and try out <b>follow.it</b>. You can find the new Subscribe button on the right hand Sidebar. I've just started using it and am still in the process of familiarizing myself with its full feature set. But from what I've read so far, apart from basic subscription services, it does offer support for filtering your feeds as well as opting for additional delivery channels like say, receiving your feeds via Telegram. I'm not exactly the target audience for these extra features, but so far it looks like a good <a href="https://follow.it/" target="_blank">Feedburner alternative</a>.<br /></span></p><p><span style="font-family: helvetica;"></span></p><p><span style="font-family: helvetica;">While integrating follow.it to Blogger, I noticed that there was an option to migrate all of my Feedburner subscribers over to it. But I figured it would be better to leave you guys the option to choose your own platform. And while the Feedburner Subscribe button will still be available on the blog, as mentioned earlier, I do not know any information regarding its state after July. So I'm sharing this update with you guys so that those of you who are subscribed to the blog via email can make the necessary changes before Feedburner shuts down its subscription services. </span><br /></p>Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com0tag:blogger.com,1999:blog-34855895719828090.post-74647555333423050452021-05-11T13:44:00.003+05:302021-05-11T13:45:21.006+05:30Introducing Hexagonal Grids to Grid Creation Systems<p><span style="font-family: helvetica;">Grid Creation Systems finally introduces a new member to its family of grids in the latest v1.6 update: <b>Hexagonal Grids</b>.</span></p><p><span style="font-family: helvetica;"></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"></span></div><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"></span></div><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"><iframe allowfullscreen="" class="BLOG_video_class" height="266" src="https://www.youtube.com/embed/NLg0eWVfnqQ" width="320" youtube-src-id="NLg0eWVfnqQ"></iframe></span></div><p></p><p><span style="font-family: helvetica;">As shown in the video, the Hexagonal Grid Generator supports basic drag & drop support plus in-editor customization, and also comes with basic utility functions for retrieving grid points at specified (x,y) indices:</span></p><ul style="text-align: left;"><li><b><span style="font-family: helvetica;">GetIndicesOfGridCellsAt(X)</span></b></li><li><b><span style="font-family: helvetica;">GetIndicesOfGridCellsAt(Y)</span></b></li><li><span style="font-family: helvetica;"><b>GetIndexOfGridCellAt(X&Y)</b><br /></span></li></ul><p><span style="font-family: helvetica;"> </span></p><p><span style="font-family: helvetica;">With the inclusion of Hex Grids, <a href="https://www.unrealengine.com/marketplace/en-US/product/grid-creation-systems" target="_blank"><b>GCS</b> </a>now has 9 unique grid configurations:</span></p><ul style="text-align: left;"><li><span style="font-family: helvetica;">Rectangular/Square </span><span style="font-family: helvetica;">configuration</span></li><li><span style="font-family: helvetica;">Circular </span><span style="font-family: helvetica;">configuration</span></li><li><span style="font-family: helvetica;">Cuboid </span><span style="font-family: helvetica;">configuration </span></li><li><span style="font-family: helvetica;">Spherical/Geographic </span><span style="font-family: helvetica;">configuration </span></li><li><span style="font-family: helvetica;">Square Pyramid </span><span style="font-family: helvetica;">configuration</span></li><li><span style="font-family: helvetica;">Concentric Circles configuration</span></li><li><span style="font-family: helvetica;">Hollow Square </span><span style="font-family: helvetica;"><span style="font-family: helvetica;">configuration</span></span></li><li><span style="font-family: helvetica;"><span style="font-family: helvetica;">Flying Wedge </span></span><span style="font-family: helvetica;"><span style="font-family: helvetica;"><span style="font-family: helvetica;">configuration</span></span></span></li><li><span style="font-family: helvetica;">Hexagonal </span><span style="font-family: helvetica;">configuration</span></li></ul><p><span style="font-family: helvetica;"></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"><a href="https://1.bp.blogspot.com/-cyOls914IXE/YJo45Sv3ziI/AAAAAAAAMKY/dyTCoul146oPj40LQAd450zlLMvysFkqwCLcBGAsYHQ/s1920/gcs16.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" src="https://1.bp.blogspot.com/-cyOls914IXE/YJo45Sv3ziI/AAAAAAAAMKY/dyTCoul146oPj40LQAd450zlLMvysFkqwCLcBGAsYHQ/s320/gcs16.png" width="320" /></a></span></div><p></p><p><span style="font-family: helvetica;">With this update, I've finally added all the different types of grids that I wanted to provide in this package. Over the next few updates, I plan to add more features to flesh out the Hex Grid, including an example demo that showcases how to handle grid interaction. Also, I've recently started work on a few other interesting projects. Hoping to share more on that soon.<br /></span></p>Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com0tag:blogger.com,1999:blog-34855895719828090.post-64777459624630551702021-04-23T12:48:00.008+05:302023-06-26T16:52:04.262+05:30Tower Defense Starter Kit Tutorial: How to set up Global Ability Deployment<p></p><h4 style="text-align: left;"><span style="font-family: helvetica;"><span style="font-size: medium;">A Quick Introduction</span></span></h4><p><span style="font-family: helvetica;"><span><span>The Tower Defense Starter Kit comes with an inbuilt Global Ability system that enables the player to deploy powerful abilities that aid in their defense against the enemy waves. Unlike Towers which cost a fixed amount of resources to construct, these abilities automatically recharge themselves after use. As a result, the Global Abilities provide players with an additional arsenal of tools that can essentially be used free of cost, and one that relies more on timing and strategy.</span></span></span></p><p><span style="font-family: helvetica;"><span><span>The toolkit provides four Global Abilities out of the box: Airstrike, Tower Guardians, Proximity Mine, & Regen Field. Airstrikes, as the name suggests deploys a series of lethal strikes that deal AoE damage to all targets caught within its blast radius. Tower Guardians, on the other hand, is a defensive ability that spawns in two Guardians to block enemy AI units in their path. Proximity Mine enables you to lay down mines along enemy paths, while Regen Field (<a href="https://forums.unrealengine.com/t/tower-defense-starter-kit/57044/342?u=stormrage256" target="_blank"><i>added in the new v2.19 update</i></a>) restores the HP of all Towers within its range.<br /></span></span></span></p><p><span style="font-family: helvetica;"><span><span>While each of these abilities differ from a functional standpoint, they also differ in terms of where exactly they can be deployed in the map. </span></span><span><span><span><span>Taking the
aforementioned Tower Guardians for example, this ability can be activated only on enemy AI paths, thus preventing the player from spawning in
reinforcements on parts of the map that do not support AI navigation.</span></span> This is achieved through a 2-step verification process, and in this tutorial, I'll show you how to set up your own rules for deploying Global Abilities.</span></span></span></p><p><span style="font-family: helvetica;"><span><span>[<u>Additional Notes:</u> <i>This
tutorial is based on the latest v2.19 edition of Tower Defense Starter
Kit].</i></span></span></span></p><p><span style="font-family: helvetica;"><span><span><i> </i></span></span></span></p><h4 style="text-align: left;"><span style="font-family: helvetica;"><span style="font-size: medium;">Tutorial</span></span></h4><p><span style="font-family: helvetica;"><span><span><b>The first step involves setting up our target actor to block the custom trace channel "CustomTargeting"</b>, which is used to detect the surface underneath the mouse cursor with respect to the ability targeting system.</span></span></span></p><p><span style="font-family: helvetica;"></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"><span><span><a href="https://1.bp.blogspot.com/-b-q5RAz6mbk/YIJdGcnb_EI/AAAAAAAAMJo/XsNp8nizGckvLWBPxQ4DLAuLKdXUqD7qgCLcBGAsYHQ/s1920/blockgatrace.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" src="https://1.bp.blogspot.com/-b-q5RAz6mbk/YIJdGcnb_EI/AAAAAAAAMJo/XsNp8nizGckvLWBPxQ4DLAuLKdXUqD7qgCLcBGAsYHQ/s320/blockgatrace.png" width="320" /></a></span></span></span></div><p><span style="font-family: helvetica;"><span><span>Any actor that blocks this trace channel, will show the targeting reticule at the blocked location. <br /></span></span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"><span><a href="https://1.bp.blogspot.com/-Ivo6DEZvvhQ/YFnXeQc3ceI/AAAAAAAAMHg/62l69UU60kEZBhR49Q5hwfrBTV-5ZGpDQCLcBGAsYHQ/s1920/gaemptyspace.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" src="https://1.bp.blogspot.com/-Ivo6DEZvvhQ/YFnXeQc3ceI/AAAAAAAAMHg/62l69UU60kEZBhR49Q5hwfrBTV-5ZGpDQCLcBGAsYHQ/s320/gaemptyspace.png" width="320" /></a></span></span></div><p><span style="font-family: helvetica;"><span><span>By
default, the GlobalAbilityTargeting trace channel is blocked only by
instances of BP_AIPath and BP_GridGenerator, plus an invisible volume
placed just below them to ensure that the targeting reticule is
displayed even when we point the cursor at empty space as seen in the screenshot
(</span><span><span><i>if not, the reticule would just disappear, and we wouldn't know where it is</i>)</span>.</span></span></span></p><p><span style="font-family: helvetica;"><span><span><b>The second step requires mapping each ability to their own individual target types for deployment.</b> For example, Airstrikes can be deployed only along enemy paths, where as the Regen Field can be activated only on Tower grid cells. <b>This is achieved through the use of a unique "TargetVerificationTag" for each ability in the "DT_GlobalAbilites" data table as shown below</b>:</span></span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"><a href="https://1.bp.blogspot.com/-C5o47q3ar2o/YIJafkWCeQI/AAAAAAAAMJg/NQ63yGOk4SAYkJn45sp3mhzBpFtIsuETACLcBGAsYHQ/s1920/gatag.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" src="https://1.bp.blogspot.com/-C5o47q3ar2o/YIJafkWCeQI/AAAAAAAAMJg/NQ63yGOk4SAYkJn45sp3mhzBpFtIsuETACLcBGAsYHQ/s320/gatag.jpg" width="320" /></a></span></div><p><span style="font-family: helvetica;"><span><span>With the help of these verification tags, we can individually configure each of our Global Abilities for activation only on target actors relevant to them. <b>Once you have specified the verification tags in the data table, just head over to the target blueprints (<i>like BP_AIPath for Tower Guardians ability</i>) and add the aforementioned tag to their list of Actor Tags</b>.</span></span></span></p><p><span style="font-family: helvetica;"></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"><span><a href="https://1.bp.blogspot.com/-QYqCtpkXVno/YIJdsJPjZRI/AAAAAAAAMJw/imDlF7yda9Qv83M5OyWH46rICXsyA4QTACLcBGAsYHQ/s1920/gaactortag.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" src="https://1.bp.blogspot.com/-QYqCtpkXVno/YIJdsJPjZRI/AAAAAAAAMJw/imDlF7yda9Qv83M5OyWH46rICXsyA4QTACLcBGAsYHQ/s320/gaactortag.jpg" width="320" /></a></span></span></div><p><span style="font-family: helvetica;"><span><span>And that's it. You should now see the targeting reticule turn from white to red when pointed at these actors, indicating that the ability can be deployed on the targeted surface. </span></span></span></p><p><span style="font-family: helvetica;"></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"><span><span><a href="https://1.bp.blogspot.com/-p48NhF4ThMQ/YGb_WD8bYCI/AAAAAAAAMIY/KrDF2DUNVV8ub5ggTFLa3a6SVR_pyUhJwCLcBGAsYHQ/s1920/gatargetable.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" src="https://1.bp.blogspot.com/-p48NhF4ThMQ/YGb_WD8bYCI/AAAAAAAAMIY/KrDF2DUNVV8ub5ggTFLa3a6SVR_pyUhJwCLcBGAsYHQ/s320/gatargetable.png" width="320" /></a></span></span></span></div><h4 style="text-align: left;"><span style="font-family: helvetica;"><span style="font-size: medium;"><br />Conclusion</span></span></h4><p><span style="font-family: helvetica;">So, with that we've come to the
end of this tutorial. If you have any doubts regarding the workflow, or
have run into some issues with the implementation, just let me know in
the comments. Or if you're interested in knowing more about the toolkit, you can check it out here: <b><a href="https://www.unrealengine.com/marketplace/en-US/product/tower-defense-starter-kit">https://www.unrealengine.com/marketplace/en-US/product/tower-defense-starter-kit</a></b>.<br /></span></p>Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com0tag:blogger.com,1999:blog-34855895719828090.post-30499056326288432072021-01-08T17:24:00.001+05:302021-04-14T18:24:40.554+05:30Unreal Engine Tips: Fixing "Unknown structure" Packaging Error<p><span style="font-family: Roboto;"><span style="font-size: medium;"><span><span>Lately, I've been doing some freelance work on the side for some of my UE4 marketplace customers who required custom modifications for the blueprint templates. And one of these projects has a heavy focus on data-driven design through the use of Structures, Data Tables, Data Assets, etc. Without going into specifics, the advantage of doing so is essentially to enable the customer to make changes to the project mostly through data without tinkering with blueprint logic.</span></span></span></span></p><p><span style="font-family: Roboto;"><span style="font-size: medium;"><span><span>While working on this project, I recently had to make some changes to a Structure which was being used across a lot of blueprints. After doing some testing, everything seemed to be working fine, with no compiler errors or gameplay crashes. So I decided to wrap it up and package the project, but then the packaging process failed and threw a whole bunch of "Unknown structure" errors. And it had to do with the edited structure.</span></span></span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: Roboto;"><span style="font-size: medium;"><span><a href="https://1.bp.blogspot.com/-IYyvCMAIXIk/X_hHnrmWNMI/AAAAAAAAMFQ/Uc5mZaqv62sJCupcbATO85Oys8vnLlI0ACLcBGAsYHQ/s1834/pkgerror.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="455" data-original-width="1834" src="https://1.bp.blogspot.com/-IYyvCMAIXIk/X_hHnrmWNMI/AAAAAAAAMFQ/Uc5mZaqv62sJCupcbATO85Oys8vnLlI0ACLcBGAsYHQ/s320/pkgerror.png" width="320" /></a></span></span></span></div><p><span style="font-family: Roboto;"><span style="font-size: medium;"><span><span>Granted the errors show the blueprints that contain this structure, but disconnecting & reconnecting every single one of those "Break Struct" nodes would have been quite time consuming. However, thankfully I stumbled upon an option under the blueprints menu that made this process a whole lot smoother.</span></span></span></span></p><p><span style="font-family: Roboto;"><span style="font-size: medium;"><span><span>Fixing the errors still does require going to each of the listed blueprints, but instead of going to each struct related node, you can essentially go to the <b>File</b> option in the top menu, and select <b>Refresh All nodes</b>.</span></span></span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: Roboto;"><span style="font-size: medium;"><span><a href="https://1.bp.blogspot.com/-nt_Ap6cBOR0/X_hB9_aNyDI/AAAAAAAAMFE/Qh8D5i5bP7E3lJkkRiRcDOscF2BIoPImQCLcBGAsYHQ/s1920/refreshstruct.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" src="https://1.bp.blogspot.com/-nt_Ap6cBOR0/X_hB9_aNyDI/AAAAAAAAMFE/Qh8D5i5bP7E3lJkkRiRcDOscF2BIoPImQCLcBGAsYHQ/s320/refreshstruct.png" width="320" /></a></span></span></span></div><p><span style="font-family: Roboto;"><span style="font-size: medium;"><span><span>Compile & save, and then do the same for all of the required blueprints. And that's it. If you try packaging the project again, there should be no "Unknown structure" errors putting a halt to the process anymore.</span></span></span></span></p><p><span style="font-family: Roboto;"><span style="font-size: medium;"><span><span>This simple solution helped me save a decent chunk of time that would have been otherwise spent doing the same repetitive task across several blueprints. <span>So I figured I'll share this information here. Maybe, it'll save you some time in the future.<br /></span></span></span></span></span></p>Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com5tag:blogger.com,1999:blog-34855895719828090.post-11800701879789343562020-12-05T19:53:00.003+05:302021-03-04T18:31:01.438+05:30Tower Defense Starter Kit Tutorial: How to add new Tower Functions<h4 style="text-align: left;"><span style="font-family: helvetica;">A Quick Introduction</span></h4><p><span style="font-family: helvetica;">What are Tower Functions? Well, you can think of them as special abilities for the Towers that can be activated to provide additional help in your defense against the enemy AI waves. The toolkit already comes equipped with a couple of Tower Functions, namely the Overdrive & Repair. Both of these functions are
handled through dedicated actor components that are added to the
selected Tower when activated.</span></p><p><span style="font-family: helvetica;">The Overdrive function temporarily boosts the output of your towers, while the Repair function restores a damaged tower back to its original HP. And in this tutorial, I'll show you how to add your own custom Tower Functions into the mix.</span></p><p><span style="font-family: helvetica;">[<u>Additional Notes:</u> <i>This tutorial is based on the latest v2.17 edition of Tower Defense Starter Kit, but should also work just fine on most prior v2.x editions of the toolkit.</i></span></p><p><span style="font-family: helvetica;"><i>v2.18 introduced a new and more streamlined workflow for Tower Functions. More information on the new workflow will be shared on the blog soon.</i>] <br /></span></p><p><span style="font-family: helvetica;"> </span></p><h4 style="text-align: left;"><span style="font-family: helvetica;">Tutorial: Event Begin Play<br /></span></h4><p><span style="font-family: helvetica;">1. Add a new entry to the enum <b>ETowerFunctions </b>for our new Tower Function. I'm going to call it "PrintTest" since I'll be creating a simple ability that will keep printing a string at timed intervals for as long as the Tower Function is active.</span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"><a href="https://1.bp.blogspot.com/-SzukiqHWVBY/X8tv5orbZOI/AAAAAAAAMBU/0O2JvFlYNQ0riujsg-9CUlxCeOyarkYSACLcBGAsYHQ/s1920/tfenum.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" src="https://1.bp.blogspot.com/-SzukiqHWVBY/X8tv5orbZOI/AAAAAAAAMBU/0O2JvFlYNQ0riujsg-9CUlxCeOyarkYSACLcBGAsYHQ/s320/tfenum.png" width="320" /></a></span></div><p><span style="font-family: helvetica;">2. Next create a new blueprint <b>Actor Component</b> for our Tower Function. Open the BP, add a new float variable <b>AbilityDuration </b>to it, and set it to <b>Instance Editable</b> & <b>Expose on Spawn</b> through the variable details panel.</span></p><p><span style="font-family: helvetica;">Finally it's time to add the implementation for our Tower Function. Since my component is just going to print some strings, I've added a timer to do just that as shown below. Just replace it with your own logic and we're done with the component setup.</span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"><a href="https://1.bp.blogspot.com/-BG-z6q-9psA/X8uOICTfd8I/AAAAAAAAMBg/DPSHchQ9OowScdqKKitHfqTkYpj3mssYQCLcBGAsYHQ/s1920/tfcomp.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" src="https://1.bp.blogspot.com/-BG-z6q-9psA/X8uOICTfd8I/AAAAAAAAMBg/DPSHchQ9OowScdqKKitHfqTkYpj3mssYQCLcBGAsYHQ/s320/tfcomp.png" width="320" /></a></span></div><span style="font-family: helvetica;"><br />3. Now open up the blueprint interface <b>BPI_TowerFunctions</b>, and add a new function to it: Add"<i>TowerFunctionName</i>"AbilityComponent. Next add the following three input parameters to this function: <b>AbilityDuration </b>(float), <b>StatusBarFillColor </b>(Linear Color), & <b>UIImage</b> (Texture 2D).<br /><br /></span><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"><a href="https://1.bp.blogspot.com/-Wiw2VSy-fF4/X8uPYEFwjxI/AAAAAAAAMBo/khsscaunSTwSyUO5xzcndzABjPQW5mcuQCLcBGAsYHQ/s1920/tfint.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" src="https://1.bp.blogspot.com/-Wiw2VSy-fF4/X8uPYEFwjxI/AAAAAAAAMBo/khsscaunSTwSyUO5xzcndzABjPQW5mcuQCLcBGAsYHQ/s320/tfint.png" width="320" /></a></span></div><p><span style="font-family: helvetica;">4. We'll now have to implement this interface function in the <b>BP_Tower_Parent </b>blueprint. The implementation involves the following steps: destroy any existing tower function component, add our new tower function component & store a reference to it, and initialize the UI icon for the tower function. Here is an example workflow that you can follow:<br /></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"><a href="https://1.bp.blogspot.com/-gTI7obQB4lw/X8uQxx-ZESI/AAAAAAAAMB0/oFFtWUHs7KA9ibH3MJdiK-7mUapiNtWxwCLcBGAsYHQ/s1920/tfintimp.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" src="https://1.bp.blogspot.com/-gTI7obQB4lw/X8uQxx-ZESI/AAAAAAAAMB0/oFFtWUHs7KA9ibH3MJdiK-7mUapiNtWxwCLcBGAsYHQ/s320/tfintimp.png" width="320" /></a></span></div><span style="font-family: helvetica;"><br />5. Now we need to let the game know about our new Tower Function. To do that, open the <b>DT_TowerFunctions </b>data table, and a new entry to it for the Tower Function. Set the various parameters as per your requirements, but the two most important ones here are <b>FunctionType </b>& <b>FunctionComponentClass</b>, both of which have to be set to the enum and component we created earlier.<br /><br /></span><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"><a href="https://1.bp.blogspot.com/-yLUW0TeFiGU/X8uT5OlGPeI/AAAAAAAAMCA/eHNLhFEXQmEs3tWoeyaznmTZ6qzki_3AQCLcBGAsYHQ/s1920/tfdt.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" src="https://1.bp.blogspot.com/-yLUW0TeFiGU/X8uT5OlGPeI/AAAAAAAAMCA/eHNLhFEXQmEs3tWoeyaznmTZ6qzki_3AQCLcBGAsYHQ/s320/tfdt.png" width="320" /></a></span></div><p><span style="font-family: helvetica;">6. Finally, open up the <b>BP_TowerManager </b>blueprint, and first add a new element to the <b>AvailableTowerFunctions </b>array and set it to our new Tower Function enum.</span></p><p><span style="font-family: helvetica;">Then head over to the <b>ActivateTowerFunctionForTower </b>function, and call the interface function we created earlier, for the switch case flow associated with our new Tower Function as shown below:</span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"><a href="https://1.bp.blogspot.com/-wBgLSNycWDo/X8uU9AjVigI/AAAAAAAAMCI/XaapKp0AFFAOtlk-BfdbPXKbJxWjiuHSwCLcBGAsYHQ/s1920/tftmintcall.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" src="https://1.bp.blogspot.com/-wBgLSNycWDo/X8uU9AjVigI/AAAAAAAAMCI/XaapKp0AFFAOtlk-BfdbPXKbJxWjiuHSwCLcBGAsYHQ/s320/tftmintcall.png" width="320" /></a></span></div><h4 style="text-align: left;"><span style="font-family: helvetica;"> </span></h4><h4 style="text-align: left;"><span style="font-family: helvetica;">Tutorial: Event End Play</span></h4><p><span style="font-family: helvetica;">And that's it. When you select a Tower from the game next time, you should see an additional interactive icon for activating the new Tower Function, and clicking on it should run the logic added in the component earlier.</span></p><p><span style="font-family: helvetica;">Now that you've set up your own Tower Function, I just wanted to leave you with an optional step that will enable you to update the duration of the Tower Function left after it has been activated. You can call the UpdateAbilityStatusDisplay interface function on your Tower (from the component) to do just that. The Overdrive & Repair functions already use this function for that purpose since both are temporary abilities. So if you're interested, I'd suggest checking out their blueprint implementations to see how its done.</span></p><p><span style="font-family: helvetica;">So, with that we've come to the end of this tutorial. If you have any doubts regarding the workflow, or have run into some issues with the implementation, just let me know in the comments.</span></p>Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com0tag:blogger.com,1999:blog-34855895719828090.post-39958477424858677432020-09-24T17:13:00.001+05:302020-09-24T17:36:08.162+05:30Unreal Engine Tutorial: Setting custom Game Modes at runtime using Blueprints<p><span style="font-family: helvetica;">For the longest time, I believed that it was not possible to change Game Modes at runtime through blueprints. That it had to be specified in the editor either through Project Settings or the World settings for individual maps. Fortunately, I was wrong and there actually does seem to be a method for overriding the default Game Mode through blueprints.</span></p><p><span style="font-family: helvetica;">I was recently involved in a project that required setting up completely different types of gameplay based on whether the player chose to play as the attacker or the defender. While it was definitely achievable by creating separate maps for each game mode, it just seemed redundant given that the maps are identical in all other respects. </span><span style="font-family: helvetica;"><span style="font-family: helvetica;">It made a lot more sense to have two separate game modes with their own player controllers and HUD classes. </span>And after some research along that line of thought, I realized that the <b>Open Level</b> node had more tricks up its sleeves than just opening a new level.<br /></span></p><p><span style="font-family: helvetica;">The Open Level node as the name suggests, is what you call when you want to move to a different level. But<u> if you expand the node, you'll come across a new input parameter named <b>Options</b>. This can be used to pass in additional string commands when you open the new level</u>. I'm not sure what exactly that entails in terms of possibilities, but we can definitely use it to override the default Game Mode associated with the level. All you have to do is specify the asset reference path for your Game Mode as per the format shown below:</span></p><p><b><span style="font-family: helvetica;">?Game=GameModeReferencePath</span><span style="font-family: helvetica;">_C</span></b></p><p><span style="font-family: helvetica;">You can <u>get the asset path by right-clicking on your Game Mode asset in the Content Browser, and selecting the Copy Reference option</u>. What we need is basically the part within the single quotation marks. For example, this is what I get upon using Copy Reference: <br /><span style="color: #01ffff;">Blueprint'/Game/TowerDefenseStarterKit/Blueprints/GameModes/BP_GameMode_TowerDefense.BP_GameMode_TowerDefense'</span></span></p><p><span style="font-family: helvetica;">So my reference path is: </span><br /><span style="color: #01ffff;"><span style="font-family: helvetica;"><span style="font-family: helvetica;">/Game/TowerDefenseStarterKit/Blueprints/GameModes/BP_GameMode_TowerDefense.BP_GameMode_TowerDefense</span></span></span></p><p><span style="font-family: helvetica;">With the path obtained, the final string command for this example scenario will be as shown below: </span><br /><span style="color: #01ffff;"><span style="font-family: helvetica;"><span style="font-family: helvetica;">?Game=/Game/TowerDefenseStarterKit/Blueprints/GameModes/BP_GameMode_TowerDefense.BP_GameMode_TowerDefense_C</span></span></span></p><p><span style="font-family: helvetica;">Now all that's left is to <u>type this in the Options</u> parameter, and next time this Open Level node gets called, it will also make sure that our custom Game Mode overrides the default Game Mode. If that sounds confusing, here is an example of what it looks like in my project (<i>Select node not required; the path can be directly entered in the Options parameter</i>):</span></p><p><span style="font-family: helvetica;"></span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-culg9Vj3eBs/X2yB1kTc2II/AAAAAAAAL-U/qSg7-UcjhIwbS6e7bbSHien5pilZYYmkQCLcBGAsYHQ/s1920/gmruntime.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" src="https://1.bp.blogspot.com/-culg9Vj3eBs/X2yB1kTc2II/AAAAAAAAL-U/qSg7-UcjhIwbS6e7bbSHien5pilZYYmkQCLcBGAsYHQ/s320/gmruntime.png" width="320" /></a></div><p></p><p><span style="font-family: helvetica;"><br />And that's all there is to it. This was pretty much completely new information to me, and it saved me the trouble of going about some roundabout fashion to meet the design requirements. And now hopefully, this information will be of help to others as well.<br /></span></p>Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com8tag:blogger.com,1999:blog-34855895719828090.post-8659172186127570252020-08-20T17:14:00.004+05:302020-08-20T17:14:46.704+05:30Unreal Engine Tips: How to use Keyboard Inputs when Input Mode is set to UI Only<font face="helvetica">I had recently migrated some of the HUD workflow from Prototype Menu System to Tower Defense Starter Kit. While going through the HUD blueprints, I noticed that the Input Mode was being set to Game and UI when activating the Pause Menu. Since I didn't want the player to have the option to interact with the game outside of the menu in this state, I went ahead and changed it to UI Only, only to find out that the Escape button could no longer be used to quit the Pause Menu (in spite of it being set to Execute when Paused). It turns out that setting the Input Mode to UI Only also prevents us from interacting with the UI using keyboard.</font><div><font face="helvetica"><br /></font></div><div><font face="helvetica">At first, it seemed like I'd have to revert it back to Set Input Mode Game & UI. But further inspection led to a workaround to tackle the issue: <u>Handling the keyboard input directly through the widget itself</u> instead of the player controller.</font></div><div><font face="helvetica"> </font></div><div><font face="helvetica">The first step is to ensure that the widget can be focused. We can do this by setting its <b>IsFocusable</b> attribute to <b>True</b>.</font></div><div><font face="helvetica"><br /></font></div><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-gTwu-eeODUs/Xz5drgoS1eI/AAAAAAAAL9E/AAsawmLuYawKHEqo93AQ-krH8xZq5-GJgCLcBGAsYHQ/s1920/isfocusable.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" src="https://1.bp.blogspot.com/-gTwu-eeODUs/Xz5drgoS1eI/AAAAAAAAL9E/AAsawmLuYawKHEqo93AQ-krH8xZq5-GJgCLcBGAsYHQ/s640/isfocusable.png" width="640" /></a></div><div></div><div><font face="helvetica"><br /></font></div><div><font face="helvetica">Next we need to make sure that the widget has keyboard focus, which can be easily achieved by calling the <b>Set Keyboard Focus</b> function in the <b>Event Construct</b> of the widget. This will enable the widget to receive keyboard inputs.</font></div><div><font face="helvetica"><br /></font></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-eH0hiHsfOk4/Xz5eejmUp1I/AAAAAAAAL9Q/O_4hnkSZg4o_FdXXz7VSQ30ONIcJ7dp4QCLcBGAsYHQ/s1920/keyfoc.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" src="https://1.bp.blogspot.com/-eH0hiHsfOk4/Xz5eejmUp1I/AAAAAAAAL9Q/O_4hnkSZg4o_FdXXz7VSQ30ONIcJ7dp4QCLcBGAsYHQ/s640/keyfoc.png" width="640" /></a></div><font face="helvetica"></font></div><div><font face="helvetica"><br /></font></div><div><font face="helvetica">With that taken care of, all that's left is to override the widgets' default keyboard input response. So we'll override its <b>On Key Down</b> function and add the required logic. For example, in my project, that involves unpausing the game as shown below:</font></div><div><font face="helvetica"><br /></font></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-gNoHyY2GHKs/Xz5fwhmEC8I/AAAAAAAAL9c/YL3E1V24hYYyC365uxeuGg_mVHDaC3kTwCLcBGAsYHQ/s1920/keypressed.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" src="https://1.bp.blogspot.com/-gNoHyY2GHKs/Xz5fwhmEC8I/AAAAAAAAL9c/YL3E1V24hYYyC365uxeuGg_mVHDaC3kTwCLcBGAsYHQ/s640/keypressed.png" width="640" /></a></div><font face="helvetica"></font></div><div><font face="helvetica"><br /></font></div><div><font face="helvetica"> </font></div><div><font face="helvetica">And that's all there is to it. You should now be able to interact with your widgets using the keyboard even when the Input Mode is set to UI Only.</font></div><div><font face="helvetica"> </font></div><div><font face="helvetica">I'll also be adding these changes to the Prototype Menu System in the next update. So it should be available on <b><a href="https://github.com/RohitKotiveetil/UnrealEngine--PrototypeMenuSystem" target="_blank">GitHub</a> </b>soon.<br /></font></div>Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com5tag:blogger.com,1999:blog-34855895719828090.post-86490338404017149542020-05-04T16:13:00.001+05:302020-05-27T02:02:42.690+05:30Controlling Player Progression in FPS Tower Defense Toolkit<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">Hi, it's been quite a while since I've written anything at all about my products on the Unreal Engine Marketplace. Lately, I've been working on a lot of improvements to the older products, starting with the Tower Defense Starter Kit earlier this year and now the FPS Tower Defense Toolkit as well.</span><br />
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><br /></span>
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">Over the years, FPS Tower Defense Toolkit has received several additional features through updates to make sure that it provides maximum value right out of the box. But with the inclusion of all of those new features also came added complexity. And as a result, I've taken the liberty of having most of the recent updates focus on making the toolkit easier to use and customize based on the community feedback received over the years. </span><br />
<br />
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">Even with the project being almost fully commented across all blueprints, with a large foundational framework like <a href="https://www.unrealengine.com/marketplace/en-US/product/fps-tower-defense-toolkit" target="_blank"><b>FPS Tower Defense Toolkit</b></a>, things can still get quite intimidating for newcomers. And it is my hope that these articles will <u>help in giving a clearer understanding of the core design of the toolkit</u>.</span><br />
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><br /></span>
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">So in this article, we will <u>focus on the process of controlling player progression</u> in your games, specifically <u>from the standpoint of what towers are available to them in each level</u>. You normally wouldn't want to overwhelm the players with every single tower in your game right from the get-go. More often than not, it would be better to slowly introduce new towers as they learn how to play the game. Plus, doing so also has the added benefit of keeping a steady stream of novelty from a gameplay standpoint since the player is being given new toys to play with overtime.</span><br />
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><br /></span>
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">Before delving into the actual workflow (<i>which is just a one-step process</i>), I'll just give you <u>a brief primer on the towers of FPS Tower Defense Toolkit</u>. The toolkit comes equipped with an assortment of towers like Machine Gun Tower, Laser Tower, Sniper Tower, and so on. But in addition to these standard varieties, you also have access to what's called a Tower Base, which serves the dual purpose of both providing a platform on which Towers can be built, as well as the means to block and control enemy paths. Finally, you also have a Trap class, which can be directly placed on the ground (<i>without Tower Bases</i>) causing all enemies walking over it to take damage. Out of all these towers, the <u>Tower Base is the only entity that must be included</u> in the player's arsenal since they facilitate the construction of towers.</span><br />
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><br /></span>
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">With that out of the way, <u>I'm going to show you how to specify which towers are available to the player in each level</u>. For this purpose, we need to have an instance (actor) of <b>BP_TowerManager </b>placed in the level. If you aren't familiar with the Tower Manager, you can check out this <a href="https://forums.unrealengine.com/unreal-engine/marketplace/50583-fps-tower-defense-toolkit-support-thread?p=647339#post647339" target="_blank">post</a> to get a basic understanding of what it represents. Now if we select the Tower Manager from the level editor, we'll be presented with a list of parameters <u>under the Config section in its details panel</u>, but what we're interested in is the <b>BaseTowerModels</b> array.</span><br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-WGeYuZjoWqw/Xq_wH0RYXlI/AAAAAAAAL4E/XDNcYFf5zagPxOn-EnN-VpmlY5FZPvZ9wCEwYBhgL/s1600/btma.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-WGeYuZjoWqw/Xq_wH0RYXlI/AAAAAAAAL4E/XDNcYFf5zagPxOn-EnN-VpmlY5FZPvZ9wCEwYBhgL/s320/btma.png" width="320" /></a></div>
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><br /></span>
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">The <b>BaseTowerModels </b>parameter is an array of type <b>ETowerModels </b>(<i>ETowerModels is an enumeration for keeping a list of all towers in your game</i>) that determines what towers are available to the player in that particular map of your game. By default, you'll see that it contains a Tower Base, all unupgraded Towers models, and a Trap. With the exception of Tower Base which is mandatory (<i>as a Tower construction platform</i>), all other entries can be modified to suit your game's progression. For example, if you want the player to have access to only the Machine Gun Tower and the Laser Tower during the opening levels of your game, then you can do so by editing the array to have entries only corresponding to the Tower Base and the required Tower Models as shown below:</span><br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-9sjxG2x31dw/Xq_zPKJH5pI/AAAAAAAAL4g/Dkb1rjAlc3ospLLbgCxpKf_44I_PejBMQCLcBGAsYHQ/s1600/mgandlaser.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-9sjxG2x31dw/Xq_zPKJH5pI/AAAAAAAAL4g/Dkb1rjAlc3ospLLbgCxpKf_44I_PejBMQCLcBGAsYHQ/s320/mgandlaser.png" width="320" /></a></div>
<br />
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">The next time you start that those levels, you'll find the changes reflected in the Loadout Selection menu (if you have it turned on) or the In-Game HUD (if loadout menu is turned off) as can be seen in the following screenshots:</span><br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-I8WaGqQSMr0/Xq_xDXc0owI/AAAAAAAAL4M/i_CbAiEYQo8KLuy6SJXuVaQniwNatVwFQCLcBGAsYHQ/s1600/loadout.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-I8WaGqQSMr0/Xq_xDXc0owI/AAAAAAAAL4M/i_CbAiEYQo8KLuy6SJXuVaQniwNatVwFQCLcBGAsYHQ/s320/loadout.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-fJAssO8OnqE/Xq_xGSkNYlI/AAAAAAAAL4Q/jf7cvOyvX806OEfz-Hm_c0ZGlntZbvG0wCLcBGAsYHQ/s1600/inghud.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-fJAssO8OnqE/Xq_xGSkNYlI/AAAAAAAAL4Q/jf7cvOyvX806OEfz-Hm_c0ZGlntZbvG0wCLcBGAsYHQ/s320/inghud.png" width="320" /></a></div>
<br />
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><br /></span>
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">And that's all there is to it. You should now be able to control the Towers available to the player for tackling each mission on an individual basis. I'll be covering more topics like these for my Marketplace products in the coming months. So feel free to reach out to me through the support email if you have any specific requests along that line. Hoping to get the next post up and running soon.</span></div>
Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com0tag:blogger.com,1999:blog-34855895719828090.post-3391132784496334682020-03-14T12:49:00.002+05:302021-11-01T13:07:51.214+05:30Building the UT Translocator using UE4 Blueprints - Part II<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">Alright, so we're back again to continue from where we left off with our tutorial on building a Translocator in Unreal Engine. In the <a href="https://unrealpossibilities.blogspot.com/2020/03/building-ut-translocator-using-ue4.html" target="_blank">first part of this tutorial series</a>, I had gone over the design process behind creating the Destination Module for the Translocator. Now we're going to create the other half of the device: the <b>Source Module</b>.</span><br /></span>
<span style="font-family: helvetica;"><br /></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">The Source Module has two fire modes: the <b>Primary Fire</b> mode which can be used to launch as well as retrieve back the Destination Module, while the <b>Alt-Fire</b> mode teleports the player to the Destination Module (and retrieves it in the process). So that's what we're going to implement in this second and final part of the Translocator tutorial. So without further ado, let's get started.</span><br /></span>
<span style="font-family: helvetica;"><br /></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">First, let us create an actor blueprint for the Source Module and set up its default properties. Once you're created the blueprint, open it, click on the <b>Add Component</b> button and add a <b>Static/Skeletal</b> <b>Mesh Component</b> </span><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">(choose one based on your weapon mesh type)</span>. Since the mesh is not going to be interacting with anything, we can set its <b>CollisionEnabled</b> parameter to <b>No Collision</b>. Next, add an <b>Arrow Component</b> and adjust its relative location until its right where you want to Destination Module to be spawned. Finally, let's add a new boolean variable and call this <b>bTranslocatorFired</b>.</span><br /></span>
<span style="font-family: helvetica;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><a href="https://1.bp.blogspot.com/-tqA4hXV9GDE/XmtzWlIgahI/AAAAAAAAL0s/rerq1zT-CwI_us9tq1lG_4g_kGibN-AswCPcBGAYYCw/s1600/sourcemesh.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-tqA4hXV9GDE/XmtzWlIgahI/AAAAAAAAL0s/rerq1zT-CwI_us9tq1lG_4g_kGibN-AswCPcBGAYYCw/s320/sourcemesh.png" width="320" /></a></span></div>
<span style="font-family: helvetica;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><a href="https://1.bp.blogspot.com/-gpXncUgqT8s/XmtzxXhMp1I/AAAAAAAAL00/D6x11CfnTG4sH9uDGH8gluXaoohaxwdxQCPcBGAYYCw/s1600/arrowbool.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-gpXncUgqT8s/XmtzxXhMp1I/AAAAAAAAL00/D6x11CfnTG4sH9uDGH8gluXaoohaxwdxQCPcBGAYYCw/s320/arrowbool.png" width="320" /></a></span></div>
<span style="font-family: helvetica;"><br /></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">Now that we have all the necessary components & variables set up, let's move on to the Event Graph. If you've played the original Unreal Tournament, you would have noticed that the Destination Module of the Translocator also gets spawned you equip the device. So that's what we're going to do first. In the <b>Event Begin Play</b>, we'll spawn in the Destination Module and attach it to the Arrow Component added in the previous step.</span><br /></span>
<span style="font-family: helvetica;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><a href="https://1.bp.blogspot.com/-Wox2UGvhJmY/Xmt0nUz3xWI/AAAAAAAAL04/9-NJ6bYLOiUdDIKGv_Y9XfaTOBsRS_WGQCLcBGAsYHQ/s1600/begin.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-Wox2UGvhJmY/Xmt0nUz3xWI/AAAAAAAAL04/9-NJ6bYLOiUdDIKGv_Y9XfaTOBsRS_WGQCLcBGAsYHQ/s320/begin.png" width="320" /></a></span></div>
<span style="font-family: helvetica;"><br /></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">Before moving on to the primary and alt-fire logic, we will first add a separate event to retrieve the destination module & reset the Translocator to its default state. Let's</span><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"> call this event <b>RetrieveDestinationModule</b>.</span> This event will be called as part of both the Primary as well as Alt-Fire logic. To start things off, we want to reset the Destination Module to its default state. But since we've already implemented the required logic for this in the first part of the tutorial, all we have to do now is call the Reset event in the Destination Module. Next, we set its actor rotation to match the player camera rotation in order to make sure that it aligns perfectly with the Source Module before snapping back in place. Finally, we wrap up the event by setting the variable <b>bTranslocatorFired </b>to false.</span><br /></span>
<span style="font-family: helvetica;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy39LmOpRAawcO399Hb2DhHxHAl8qcAsCI2kJfawJB0CLVpP2OKL8irga5OTcvGoZxBGDNdTs802kbwjtyNr9mqTeqkuS-yjzcSTTlU6Eq9I0O-HmZ6FRQ-L-yI34YdihoCOn7Yekc4A/s1600/reteieve.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy39LmOpRAawcO399Hb2DhHxHAl8qcAsCI2kJfawJB0CLVpP2OKL8irga5OTcvGoZxBGDNdTs802kbwjtyNr9mqTeqkuS-yjzcSTTlU6Eq9I0O-HmZ6FRQ-L-yI34YdihoCOn7Yekc4A/s320/reteieve.png" width="320" /></a></span></div>
<span style="font-family: helvetica;">
<span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"> </span><br /></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">Now let's start with the <b>Primary Fire</b> implementation. We'll create a new event <b>PrimaryFireTriggerPressed</b> for this. Since it works differently based on whether the Destination Module has been fired or not, we're going to first check that by passing our </span><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><b>bTranslocatorFired</b> variable through a Branch node</span>. If it hasn't been fired already, we detach the Destination Module, call its Launch event and set the value of <b>bTranslocatorFired</b> to True. If on the other hand, it has already been fired, we call the <span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><b>RetrieveDestinationModule</b> event created in the last step, thus priming the Translocator to be fired again.</span></span><br /></span>
<span style="font-family: helvetica;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><a href="https://1.bp.blogspot.com/-lymmSD3AspQ/Xmt2C0gpw-I/AAAAAAAAL1Q/xLCdRgCbrsg3Zelf_khBz4WHOUeACsvkACPcBGAYYCw/s1600/prim.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-lymmSD3AspQ/Xmt2C0gpw-I/AAAAAAAAL1Q/xLCdRgCbrsg3Zelf_khBz4WHOUeACsvkACPcBGAYYCw/s320/prim.png" width="320" /></a></span></div>
<span style="font-family: helvetica;"><br /></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">And so we arrive at the final piece of logic within the Translocator's Source Module: the <b>Alt-Fire</b> mode. Similar to the Primary Fire, we'll start with creating a new event <b>AltFireTriggerPressed</b>, followed by checking if the device has been fired already. If yes, then we'll <b>Teleport </b>the player pawn over to the location of the Destination Module, and follow it up with a call to the </span></span><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><b>RetrieveDestinationModule </b>event.</span></span></span></span><br /></span>
<span style="font-family: helvetica;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><a href="https://1.bp.blogspot.com/-rTXNF5bo--8/Xmt2mm_NKxI/AAAAAAAAL1U/56RUD9VnnSoqM6mY3RCt2yotYaetoURqQCLcBGAsYHQ/s1600/alt.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-rTXNF5bo--8/Xmt2mm_NKxI/AAAAAAAAL1U/56RUD9VnnSoqM6mY3RCt2yotYaetoURqQCLcBGAsYHQ/s320/alt.png" width="320" /></a></span></div>
<span style="font-family: helvetica;"><br /></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><b>At this point, you should have a working Translocator at your disposal</b>. But I'll also briefly show you how your player character can interact with it. In the Event Begin Play of your player character, use the SpawnActorFromClass node to spawn an instance of the Translocator, store a local reference to it, and attach it to your character mesh component.</span></span></span></span><br /></span>
<span style="font-family: helvetica;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><a href="https://1.bp.blogspot.com/-yihMQ-CjO-Q/Xmt27EcYhQI/AAAAAAAAL1Y/x6pvfRvtwzk-SZT--l4UVgH8_3ow74g9ACLcBGAsYHQ/s1600/spawn.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-yihMQ-CjO-Q/Xmt27EcYhQI/AAAAAAAAL1Y/x6pvfRvtwzk-SZT--l4UVgH8_3ow74g9ACLcBGAsYHQ/s320/spawn.png" width="320" /></a></span></div>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><br /></span></span></span></span></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">Now it's just a matter of getting the Translocator reference and calling its Primary and Alt-Fire events for each of the associated input action events.</span></span></span></span><br /></span>
<span style="font-family: helvetica;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><a href="https://1.bp.blogspot.com/-0YujMNAP5KM/Xmt3WebZroI/AAAAAAAAL14/4zPkyGfFJgQLB6w0q6DpxiQQ7VN-BNrSgCLcBGAsYHQ/s1600/input.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-0YujMNAP5KM/Xmt3WebZroI/AAAAAAAAL14/4zPkyGfFJgQLB6w0q6DpxiQQ7VN-BNrSgCLcBGAsYHQ/s320/input.png" width="320" /></a></span></div><span style="font-family: helvetica;">
<span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><br /></span></span></span></span></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">Here's a video showcasing the final result of what it should look like (ignore the lights & antenna on the Destination Module, they're something I just added for show)</span></span></span></span><br /></span>
<span style="font-family: helvetica;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/ZHWwCo5KyQY/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/ZHWwCo5KyQY?feature=player_embedded" width="320"></iframe></span></div>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><br /></span></span></span></span></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><br /></span></span></span></span></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">And thus we finally come to the end of this tutorial. I'll be sharing the project files on GitHub soon. Will update the link over here once it's done. Apart from that, I'm also planning to write an article on using EQS to create 2D Line of Sight Visualizations in Unreal. So if that's the sort of thing you're interested in, keep an eye out for it in the upcoming week.</span></span></span></span></span></div><span style="font-family: helvetica;">
</span>Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com0tag:blogger.com,1999:blog-34855895719828090.post-43136848407171742722020-03-04T22:00:00.005+05:302021-11-01T13:08:13.312+05:30Building the UT Translocator using UE4 Blueprints - Part I<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">As mentioned in the previous post, the original Unreal Tournament holds a special place in my memories when it comes to gaming experiences. And not necessarily because of the competitive elements, but more so because it took me to an assortment of diverse & beautiful fictional settings, inspired not just by science fiction, but also fantasy and medieval history as well. It also had a kick ass soundtrack to boot. So after playing the game again recently, I wanted to try and recreate some of its gameplay mechanics in Unreal Engine. While my first project was focused on <span style="color: cyan;"><a href="https://unrealpossibilities.blogspot.com/2020/02/creating-jump-pad-in-unreal-engine.html" target="_blank">Creating a Jump Pad</a></span> (inspired by the UT99 Jump Boots), this time, I figured why not go for something more iconic and decided to recreate the <b>Translocator</b>.</span></span><br /></span>
<span style="font-family: helvetica;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><a href="https://1.bp.blogspot.com/-7CKYPxhagWc/Xl6YsuHFJzI/AAAAAAAALyA/ovApr1vVtFEbLWASaup2R09OTxMeJYm_ACLcBGAsYHQ/s1600/translocut.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-7CKYPxhagWc/Xl6YsuHFJzI/AAAAAAAALyA/ovApr1vVtFEbLWASaup2R09OTxMeJYm_ACLcBGAsYHQ/s320/translocut.png" width="320" /></a></span></div>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><br /></span></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">At first glance, it would seem like all you'd have to do would be to just launch a projectile and then alt fire to teleport to its location. But upon closer inspection, you can find that there is a bit more to this device. For example, whenever the Translocator's Destination Module lands on the ground, it always ends up facing upwards by the time it comes to rest.</span></span><br /></span>
<span style="font-family: helvetica;"><br /></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">In terms of actual gameplay features, there is also the option to <b>Telefrag</b> (which I won't be covering in this tutorial) your opponents by throwing the Destination Module to their location before teleporting to it. So while the teleportation aspect is what comes to mind first when you think of it, the presence of the more obscured features makes the Translocator somewhat unique as a weapon/gadget when compared to a generic teleporter. So anyways, without wasting any more time on the specifications of the device, let's get right down to the design process</span><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">.</span></span><br /></span>
<span style="font-family: helvetica;"><br /></span>
<span style="font-family: helvetica;"><br /></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">Alright, so the first order of the business is to create an <b>Actor</b> blueprint for our projectile. I'm going to name it <b>BP_DestinationModule</b>. Now we're going to open the new blueprint and untick its <b>Start with Tick Enabled</b> parameter. We'll be turning it on and off manually at runtime, but more on that later.</span></span><br /></span>
<span style="font-family: helvetica;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><a href="https://1.bp.blogspot.com/-C3N_N0iSS3Y/Xl6qst7TWOI/AAAAAAAALyg/hRtjReEq9jk13iVYonFgsh9bTI8hkNCeQCLcBGAsYHQ/s1600/tickdef.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-C3N_N0iSS3Y/Xl6qst7TWOI/AAAAAAAALyg/hRtjReEq9jk13iVYonFgsh9bTI8hkNCeQCLcBGAsYHQ/s320/tickdef.png" width="320" /></a></span></div>
<span style="font-family: helvetica;"><br /></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">Now let's open up the new blueprint and add a <b>Static Mesh Component</b> to act as our projectile mesh. Since we don't want this mesh to collide with anything before we fire the Translocator, let's set its <b>Collision Enabled</b> parameter to <b>No Collision</b> by default.</span></span><br /></span>
<span style="font-family: helvetica;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><a href="https://1.bp.blogspot.com/-DBGrqJeqKbA/Xl6rhuvYAoI/AAAAAAAALyo/ySoJsrPHPuM40YPCLSCv5iR2FOCxmV86ACLcBGAsYHQ/s1600/staticmeshcoll.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-DBGrqJeqKbA/Xl6rhuvYAoI/AAAAAAAALyo/ySoJsrPHPuM40YPCLSCv5iR2FOCxmV86ACLcBGAsYHQ/s320/staticmeshcoll.png" width="320" /></a></span></div>
<span style="font-family: helvetica;"><br /></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">Normally you would add a Projectile Movement Component as the next step. However, unlike your typical bullet projectiles, the Translocator fires a pod that can be retrieved and fired again. And that brings us to a complication since the Projectile Movement Component cannot be restarted once the actor has totally come to a halt. You can try reactivating it or resetting the initial velocity, but that's not going to be of any help. Hence we're going for an alternative approach: adding/removing projectile movement components at runtime. Every time we launch the module, we'll add a component and once it comes to a stop or if it is retrieved back by the player, we'll destroy it.</span></span><br /></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><br /></span></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">With that said, we'll start out by adding a new boolean variable <b>bIsActive</b> to our Destination Module blueprint. This variable will be used to update and keep track of the module's state.</span></span><br /></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><br /></span></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">Next we're going to create a custom event for launching the Destination Module. As shown in the screenshot below, we first check if bIsActive is True. If the module is already active, we do not want to do anything. But if it isn't, we'll add a <b>Projectile Movement Component</b> (</span></span><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">you can find its default settings in the screenshot)</span></span> and </span></span><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">bind
a new event to the its <b>On Projectile Stop</b> event. Let's call this
new event <b>OnProjectileStopped</b>. We'll get back to its implementation in the next step, but basically what's happening here is that this new event will be called as soon as the projectile motion is completed. Finally we're also going to turn on the collision and set the actor to tick.</span></span></span></span><br />
<br /></span>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><a href="https://1.bp.blogspot.com/--8mVq6aFZG0/Xl-PYwFwKjI/AAAAAAAALzE/PhxcmSb-kIgWhbtk4sae-0A7ldhcm5nugCLcBGAsYHQ/s1600/projcomp.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/--8mVq6aFZG0/Xl-PYwFwKjI/AAAAAAAALzE/PhxcmSb-kIgWhbtk4sae-0A7ldhcm5nugCLcBGAsYHQ/s320/projcomp.png" width="320" /></a></span></div>
<span style="font-family: helvetica;"><br /></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">Alright, let's move on to the implementation for <b>OnProjectileStopped</b> event that we added in the previous step. First, we're going to destroy the Projectile Movement Component because we'll be spawning in a new one next time. The actor tick can also be disabled since it is no longer required during this phase. Since these two steps are going to be called again elsewhere we'll group them under a new event <b>DisableMovement</b>.</span><br /></span>
<span style="font-family: helvetica;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><a href="https://1.bp.blogspot.com/-miSI2IfChFw/Xl-Y8WFyg-I/AAAAAAAALzg/1k_7Cw5twDsHVdpOLITwVkA1Uvh2jtJAACLcBGAsYHQ/s1600/dismove.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-miSI2IfChFw/Xl-Y8WFyg-I/AAAAAAAALzg/1k_7Cw5twDsHVdpOLITwVkA1Uvh2jtJAACLcBGAsYHQ/s320/dismove.png" width="320" /></a></span></div>
<span style="font-family: helvetica;"><br /></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">With the launch system taken care of, we now move on to the process of resetting the Destination Module when the player retrieves it back. For this purpose, we add a new event <b>Reset</b> and it's also going to call the OnProjectileStopped event, followed by two additional nodes to disable the collision and reset the value of bIsActive variable.</span></span><br /></span>
<span style="font-family: helvetica;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><a href="https://1.bp.blogspot.com/-3grTigx3xfI/Xl-aNBbz_OI/AAAAAAAALzo/egARQB4f-g8MlEwYuzEYEB4dBVUIxLSJwCLcBGAsYHQ/s1600/reset.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-3grTigx3xfI/Xl-aNBbz_OI/AAAAAAAALzo/egARQB4f-g8MlEwYuzEYEB4dBVUIxLSJwCLcBGAsYHQ/s320/reset.png" width="320" /></a></span></div>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><br /></span></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">So at this point, we have essentially finished what I'd call the core logic of the Destination Module. But in the spirit of keeping it true to the inspiration, I'll also show you how to make sure that it always lands facing upwards. And this is where the <b>Event Tick</b> comes in to play<span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">.</span></span></span><br /></span>
<span style="font-family: helvetica;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><a href="https://1.bp.blogspot.com/-QvQab9hVH0M/Xl_JmNPXapI/AAAAAAAAL0E/Asga4m-6A3A4rIYCDEB7DYZfaei6-cAkQCLcBGAsYHQ/s1600/rotal.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-QvQab9hVH0M/Xl_JmNPXapI/AAAAAAAAL0E/Asga4m-6A3A4rIYCDEB7DYZfaei6-cAkQCLcBGAsYHQ/s320/rotal.png" width="320" /></a></span></div>
<span style="font-family: helvetica;"><br /></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">As shown above, we're using <b>FInterp To</b> nodes to interpolate the Roll & Pitch values of the Mesh rotation to 0.0 while keeping the Yaw as it is. This will ensure that the mesh always faces upwards. However, you might have noticed that there is a branch node placed at the start of the tick event. It's basically checking if the velocity (vector length squared) is below a certain threshold (which I've set to 625), thus causing the rotation updates to kick in only moments before the projectile comes to a rest.</span></span><br /></span>
<span style="font-family: helvetica;"><br /></span>
<span style="font-family: helvetica;"><br /></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">And with that, the Destination Module of our Translocator is ready for use. I had initially assumed that the entire tutorial would be shorter than this. But since this post has already gotten a bit too long, I will be sharing the remainder of the tutorial in a second part, which will cover the projectile firing and retrieval mechanisms for the Translocator. But if anyone's interested in what the final result looks like, you can find the <a href="https://www.youtube.com/watch?v=ZHWwCo5KyQY" target="_blank">video</a> in my YouTube channel. So see you in the next part of the tutorial.</span></span><br /></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><br /></span></span></span></div><span style="font-family: helvetica;">
</span>Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com0tag:blogger.com,1999:blog-34855895719828090.post-951213115587337912020-02-28T17:17:00.001+05:302020-02-28T17:24:17.800+05:30Creating a Jump Pad in Unreal Engine<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I was recently playing the original Unreal Tournament again and realized that the game holds up pretty well even now, couple of decades after its release. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I admit that nostalgia might partly be the culprit, but a</span>s soon as the intro scene started playing, hearing that voice and background score, it felt like getting into a time capsule back into the early 2000s. Booting up some levels, I was genuinely surprised by how atmospheric most of them felt.</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-sJWl--GVkjk/XlZQIE0O82I/AAAAAAAALvc/gNNxLTWXC6g73_xnDO4liPErMWI7OhiqgCLcBGAsYHQ/s1600/facing%2Bworlds.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-sJWl--GVkjk/XlZQIE0O82I/AAAAAAAALvc/gNNxLTWXC6g73_xnDO4liPErMWI7OhiqgCLcBGAsYHQ/s320/facing%2Bworlds.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-HnHiEmN0JMs/XlZQKY9LqxI/AAAAAAAALvg/wHS1trgwRmMZCT-d0KlcKTmlPkSfUQxRgCLcBGAsYHQ/s1600/deck.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-HnHiEmN0JMs/XlZQKY9LqxI/AAAAAAAALvg/wHS1trgwRmMZCT-d0KlcKTmlPkSfUQxRgCLcBGAsYHQ/s320/deck.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-Qg9-tQACRCY/XlZQLra9pOI/AAAAAAAALvk/2hd12BHGILQd1uiXvKEGFjOJt67kYXZ_gCLcBGAsYHQ/s1600/hyperblast.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-Qg9-tQACRCY/XlZQLra9pOI/AAAAAAAALvk/2hd12BHGILQd1uiXvKEGFjOJt67kYXZ_gCLcBGAsYHQ/s320/hyperblast.png" width="320" /></a></div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The
diverse background settings in which the matches took place along with
the excellent soundtrack that accompanies them, seemed to create a sense
of being in that virtual space that you don't often get in a lot of
games. And one of those levels that has really stuck with me is the Capture the Flag map "CTF-LavaGiant", with its beautiful skyscape and the sea of lava surrounding the core game space. </span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-QiNNc4Sjx3k/XlZRaVjB8PI/AAAAAAAALvw/ft3gHTfHwlY6hwx66Naq5ATJFvmTPFtxwCLcBGAsYHQ/s1600/lavagiants.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-QiNNc4Sjx3k/XlZRaVjB8PI/AAAAAAAALvw/ft3gHTfHwlY6hwx66Naq5ATJFvmTPFtxwCLcBGAsYHQ/s320/lavagiants.png" width="320" /></a></div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">After loading it up for a quick game, I came across a pair of <b>Jump Boots</b> on the way back from the enemy base, which I then used to vault over the walls of their fort.</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-PDB25-oWRZU/XlZUUGqqM9I/AAAAAAAALwM/IYlIGa_jvTckz8GwsLMglmIm2yo78NC2gCLcBGAsYHQ/s1600/Jumpingboots.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-PDB25-oWRZU/XlZUUGqqM9I/AAAAAAAALwM/IYlIGa_jvTckz8GwsLMglmIm2yo78NC2gCLcBGAsYHQ/s320/Jumpingboots.png" width="320" /></a></div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">It was quite fun jumping over the lava to make my way back to our base. And then I figured why not try to make something similar in Unreal Engine. It's quite simple, but I had never tried any experiments with jumping mechanics. Besides, I rarely find challenge to be a deciding factor when it comes to motivation. It's almost always about the joy of just exploring new possibilities.</span><br />
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">So the next day, after work, I went ahead and created a new UE4 project. Since I wanted to create a wall jumping mechanic as well (inspired by ULTRAKILL), I decided to go for a <b>Jump Pad</b> instead of Jump Boots for this project.</span><br />
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The basic set up was simple. Create an actor that has a collision volume, which when triggered by the player character, will push it in the upward direction. The <b><a href="https://unrealpossibilities.blogspot.com/2018/04/unreal-engine-experiments-blink-ability.html" target="_blank">Blink Ability</a></b> project that I had worked on a year or two back, involved some logic that pushed the character over the wall to roughly simulate climbing after teleporting to a ledge above you.</span><br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-4wOJdev_2o4/XlZYQgVxZWI/AAAAAAAALwo/xS0qqk57UFomPZ7fIygSqkjxnx39hN0ogCLcBGAsYHQ/s1600/ezgif.com-gif-maker%2B%25282%2529.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="300" data-original-width="600" height="160" src="https://1.bp.blogspot.com/-4wOJdev_2o4/XlZYQgVxZWI/AAAAAAAALwo/xS0qqk57UFomPZ7fIygSqkjxnx39hN0ogCLcBGAsYHQ/s320/ezgif.com-gif-maker%2B%25282%2529.gif" width="320" /></a></div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">And while I ended up using the "Move Component To" node in favor of the <b>Launch Character</b> node back then, here the latter seemed perfect. As soon as the Jump Pad collision box registers an overlap, it checks if the overlapping actor is a character type and if true, launches it in the upward direction.</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-TrNywzJjyMU/Xlj7NRk_MFI/AAAAAAAALxc/y_3nbYjmx_Ihu2UOY51UX0cVD4-fjTIDQCLcBGAsYHQ/s1600/jumpinitial.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-TrNywzJjyMU/Xlj7NRk_MFI/AAAAAAAALxc/y_3nbYjmx_Ihu2UOY51UX0cVD4-fjTIDQCLcBGAsYHQ/s320/jumpinitial.png" width="320" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">However, after testing the Jump Pad a few times, I noticed that the jump heights weren't always the same. When the character walked up to the Jump Pad, I was able to jump much higher than when it was falling on to the Jump Pad. The issue was fixed by setting the <b>ZOverride</b> parameter on the node to True.</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"></span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><a href="https://1.bp.blogspot.com/-9TdUquZuWpY/Xlj7oMjcshI/AAAAAAAALxk/TRP76E20lSEN28j07QvOw3HhzzMEK-Q9ACLcBGAsYHQ/s1600/jumpcorrect.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-9TdUquZuWpY/Xlj7oMjcshI/AAAAAAAALxk/TRP76E20lSEN28j07QvOw3HhzzMEK-Q9ACLcBGAsYHQ/s320/jumpcorrect.png" width="320" /></a></span></div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Basically what this does is ignore the Z component of the character's velocity and assign the launch velocity value to it. Now even if your character is falling down to the Jump Pad, the negative value of the fall velocity Z component is not taken into account when launching the character upwards. So I guess that is something new that I've learnt as part of this experiment. Anyways with taken care of, my character was jumping around the map quite fine.</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/miEQQX5WvUg/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/miEQQX5WvUg?feature=player_embedded" width="320"></iframe></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">And that's another experiment successfully completed. I also went ahead and recreated the <b>Translocator</b> from Unreal Tournament after this project. I want to try out the Shock Rifle at some point as well. But one thing at a time. Right now, I'm just glad to have started writing again after more than a year of hiatus. Hoping to keep this going.</span></div>
Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com0tag:blogger.com,1999:blog-34855895719828090.post-24975176574987206492020-02-07T15:47:00.002+05:302020-02-07T15:47:36.416+05:30Unreal Engine Utility Functions #1: Random Point in Sphere<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">It has been quite a while since I've posted something here. More than a year actually. The main culprit, being that creating gameplay systems with blueprints is a far more enjoyable process than writing about it. But I've decided to write "again", by making some free time every week, even if it's just for a few hours. So given the already established lack of motivation to do so, it made sense to start with something small. Hopefully that will make it easier to just keep going without giving up on writing for another year. And without wasting any more time explaining my motivations (or lack thereof), let's get right down to the actual project.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">So I was going through a backlog of ideas that I've always wanted to try out, but with the hope of finding something simple, yet enjoyable that I can do after work. And while this particular choice is not as exciting as say, creating a gameplay mechanic itself, I figured having a blueprint library for Utility Functions would be a good idea. The functions can be implemented one at a time quickly and might also prove useful in</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> future projects</span>. As good a place to start as any.</span><br />
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">And as the name suggests, this first function will give us the location of a random point inside a sphere, given its radius and the center location.</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-veKRbTnEUtE/Xj0faXnmIGI/AAAAAAAALuI/RTbWIoWjHEYycogfvQyGXBPzR73lW4C4gCEwYBhgL/s1600/RanPtInSphere.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-veKRbTnEUtE/Xj0faXnmIGI/AAAAAAAALuI/RTbWIoWjHEYycogfvQyGXBPzR73lW4C4gCEwYBhgL/s320/RanPtInSphere.png" width="320" /></a></div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">So if you're new to blueprints and reading this, what's happening here is that we first take a unit vector in a random direction and multiply it with a value less than the radius of the sphere.</span><br />
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This will give us a vector whose direction is randomized, but with a magnitude (or length) less than the radius of the sphere.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Now imagine adding this vector to the center location of the sphere. Since its magnitude is lesser than the sphere radius, the final location after addition will always be inside the sphere.</span><br />
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">And the randomized direction of the added vector means we get a completely randomized point within the spherical volume each time.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Here is the final result of the function being used in a test scenario:</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-C991gvmA810/Xj03Rde75AI/AAAAAAAALuk/lKqN8k0Y-kgq2GJtD5MROMRWWIfGbNvgQCLcBGAsYHQ/s1600/ezgif.com-video-to-gif.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="450" data-original-width="800" height="180" src="https://1.bp.blogspot.com/-C991gvmA810/Xj03Rde75AI/AAAAAAAALuk/lKqN8k0Y-kgq2GJtD5MROMRWWIfGbNvgQCLcBGAsYHQ/s320/ezgif.com-video-to-gif.gif" width="320" /></a></div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">And that's all there is to it. I hope to continue adding more functions to the library over time. If
the library ends up getting a decent collection of useful functions (before the motivation bar runs out), maybe I'll share
it on GitHub/Gumroad. But that's for later. One step at a time for now.</span></span></div>
Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com0tag:blogger.com,1999:blog-34855895719828090.post-88490655286970327472018-10-23T15:37:00.001+05:302019-10-03T13:25:03.849+05:30Unreal Engine Experiments: Enemy Tagging System<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I've been playing a fair bit of stealth & tactical action games of late and noticed that most of them have some form of enemy tagging systems to help the players form a better tactical awareness about the game world. I generally note down interesting gameplay systems that I come across, in order to study them in detail at a later time. But since this particular mechanic didn't seem like it would take up much time, I decided to jump into the process right away.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I started doing some research on the concept and various approaches taken by different games to implement it. And I took a particular liking to the Metal Gear Solid V's take on tagging systems, with its added support for range display as well as the highlighting of occluded objects. So I decided to go ahead and recreate it in Unreal Engine, and <b>this post is basically a high-level retrospective overview of the implementation process</b>. But before getting into the details, here is a super quick preview of what the end result is going to look like:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-FN4n1IBlWss/W82yPsKKf_I/AAAAAAAALVo/ekfrJF2Jh8E6CXYwjvUyZP7zEVVeUp0qwCLcBGAs/s1600/ezgif.com-optimize.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="405" data-original-width="720" height="180" src="https://4.bp.blogspot.com/-FN4n1IBlWss/W82yPsKKf_I/AAAAAAAALVo/ekfrJF2Jh8E6CXYwjvUyZP7zEVVeUp0qwCLcBGAs/s320/ezgif.com-optimize.gif" width="320" /></a></div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Alright, so without further ado, let's dive into the design process behind the experiment.</span></span><br />
<a name='more'></a><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The first order of business here is to <b>create a custom widget that can display the tag image as well as the distance to the player character</b>. Since the tag needs to hover above the target at all times, we can use a widget component and leverage its inbuilt functionality to attach itself to actors. However, since highlighting of occluded targets is also part of the agenda here, it makes sense to render the widget on screen space.</span></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-aHHtjkUTbzI/W87ufQJB5qI/AAAAAAAALV0/PEucLCRRjWkZIHZwiVUIGskTCtKly-FWwCLcBGAs/s1600/3dwidgetscreen.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://4.bp.blogspot.com/-aHHtjkUTbzI/W87ufQJB5qI/AAAAAAAALV0/PEucLCRRjWkZIHZwiVUIGskTCtKly-FWwCLcBGAs/s320/3dwidgetscreen.png" width="320" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">However, if we try this out in the editor, we'll notice an issue once we start moving away from the tagged actors. The widget will start covering most of the actor until at very large distances, the actor becomes barely visible at all. This happens because the relative distance from the actor to the widget component remains the same, while the widget being rendered in screen space retains its default size. And that is not desirable.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span> <span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Now there are two ways to resolve this. The first involves changing the widget size dynamically, while the other approach revolves around <b>updating the relative location of the component at runtime</b>. After taking another look at the workings of tagging systems from a few real games, I noticed that the second approach is generally favored, and that's the one that we're going to take here. While I tried out multiple types of alignment correction models, it finally came down to just using a simple linear multiplier based on the distance involved.</span></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-YHNDOq5ue4w/W87vC_kNjkI/AAAAAAAALV8/jxLVD174tVEQrdyfpm6wJvaM6RbalzKhACEwYBhgL/s1600/distalign.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-YHNDOq5ue4w/W87vC_kNjkI/AAAAAAAALV8/jxLVD174tVEQrdyfpm6wJvaM6RbalzKhACEwYBhgL/s320/distalign.png" width="320" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Here is a comparison of the tagging system with and without the <b>distance-based alignment corrections</b> (I also threw in some script to display the distance text):</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/4RnZG7crvYU/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/4RnZG7crvYU?feature=player_embedded" width="320"></iframe></div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> <span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Now that we have a working tag widget, we can throw in some <b>player input driven logic for adding tags to actors manually</b>. A simple line trace-driven check would suffice in this regard. We can take the hit result data and request activation of tag display if the hit actor has a tag widget component.</span></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-0Odfh4-W2K0/W87v1cjc5GI/AAAAAAAALWI/1Q9-VqpnQ7g-YypD2PSX3RLdciooTbBBQCLcBGAs/s1600/traceres.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://3.bp.blogspot.com/-0Odfh4-W2K0/W87v1cjc5GI/AAAAAAAALWI/1Q9-VqpnQ7g-YypD2PSX3RLdciooTbBBQCLcBGAs/s320/traceres.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">And that brings us to the final section: <b>implementation of occluded object highlights</b>. To this end, we can use a post-process material with custom stencils enabled. I'm not particularly good with materials, but fortunately, Rodrigo Villani has already created an awesome <a href="https://www.youtube.com/watch?v=rL7VUeZzRyQ" target="_blank"><b>tutorial</b></a> on how to create outlines in Unreal Engine. I took the basic material setup explained in the tutorial and threw in some additional script to add translucent filling within the outline area. And that's about it. Here is a preview video of the enemy tagging system in action:</span></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/8sZ1fNd5OlI/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/8sZ1fNd5OlI?feature=player_embedded" width="320"></iframe></div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">With that, we have come to the end of another experiment. Eventually, I hope to use this space to write about all of my experiments, but it is probably going to be a while, given my trajectory so far. But I generally keep my <a href="https://www.youtube.com/channel/UCzvzhcyARRwQZ3YDnrujnEA" target="_blank"><b>Youtube channel</b></a> updated with the latest projects. So if you like to see more cool experiments in Unreal Engine, you know where to find them. 😉</span></span></div>
Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com0tag:blogger.com,1999:blog-34855895719828090.post-89516310987194355242018-09-23T18:28:00.005+05:302021-11-01T13:07:18.666+05:30Unreal Engine Experiments: Last Known Position Visualization<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">The blog has been dark for a while now. But the past few months have been a quite fun experience as I got to experiment with a whole host of interesting gameplay systems in Unreal Engine. And I have to admit that the prospect of writing about them is not nearly as exciting as working on them. But I have finally summoned the willpower to get one article published over this weekend. So I figured that I'll go ahead and write about the most exciting project that I've worked on (since the <a href="https://unrealpossibilities.blogspot.com/2018/04/unreal-engine-experiments-blink-ability.html" target="_blank"><b>recreation of Blink ability from Dishonored</b></a>): the Last Known Position mechanic from Splinter Cell Conviction.</span><br /></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><br /></span> <span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">As the title suggests, we're going to cover the process of visualizing the player character's last known position (as perceived by the AI). The mechanic itself should be quite familiar to those who have played either of the last two entries in the Splinter Cell franchise. But in case you're not, here is a short animated preview of what exactly the end product is going to look like:</span></span><br /></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><br /></span></span></span>
<span style="font-family: helvetica;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><a href="https://4.bp.blogspot.com/-jOba6o87FDQ/W6eJO4gyeHI/AAAAAAAALTM/_Af69dMKSqIHWTKlgy5VtD44MxmSppRmwCLcBGAs/s1600/LKPV_Lossless.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="400" data-original-width="800" height="200" src="https://4.bp.blogspot.com/-jOba6o87FDQ/W6eJO4gyeHI/AAAAAAAALTM/_Af69dMKSqIHWTKlgy5VtD44MxmSppRmwCLcBGAs/s400/LKPV_Lossless.gif" width="400" /></a></span></div>
<span style="font-family: helvetica;"><br /></span>
<a name='more'></a><span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"> </span><br /></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">Alright, so with that out of the way, let's get into the nitty-gritty of the experiment. Basically, there are three main steps required for implementing the visualization system: </span><br /></span>
<ul style="text-align: left;">
<li><span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">Create a translucent silhouette material</span></span></li>
<li><span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">Setup an animation pose capture & mirror system</span></span></li>
<li><span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">Implement a basic AI perception system for tracking purposes</span></span></li>
</ul>
<div>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">Now let's go over each of them in order, starting with the material creation process.</span></span></div>
<div>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><br /></span></span></div>
<div>
<span style="font-family: helvetica;"><b><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">Silhouette Material</span></b></span></div>
<div>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><br /></span></span></div>
<div>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">I started out with this because I had absolutely no clue how to get this working. So if anything was going to be a showstopper, it was probably going to be this one. I mean you can't just throw in a basic translucent material and call it a day. The material script also needs to be able to cull the inner triangles of the mesh. B</span>eing a complete noob at materials, I turned to the internet for help. Thankfully, Tom Looman had already posted a <a href="http://www.tomlooman.com/the-many-uses-of-custom-depth-in-unreal-4/" target="_blank"><b>custom depth based solution</b></a> in his blog and it</span><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"> involves the use of two similar overlapping meshes: a translucent mesh rendered in the main pass, and an opaque one rendered in custom depth. Here is a preview of what the final result:</span></span></div>
<div>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><br /></span></span></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><a href="https://3.bp.blogspot.com/-jIEIZpwBDuE/W6eJkH3T0HI/AAAAAAAALTU/9QQL7p7oYnon8fT6Ms9bMI18r3CQcRvkQCLcBGAs/s1600/Lossy%2BGhost.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="320" data-original-width="640" height="160" src="https://3.bp.blogspot.com/-jIEIZpwBDuE/W6eJkH3T0HI/AAAAAAAALTU/9QQL7p7oYnon8fT6Ms9bMI18r3CQcRvkQCLcBGAs/s320/Lossy%2BGhost.gif" width="320" /></a></span></div>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><br /></span></span> <span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">Well, with that taken care of, let's head over to the next step in the process.</span></span></div>
<div>
<span style="font-family: helvetica;"><br /></span></div>
<div>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><b>Visualization Pose Capture</b></span></span></div>
<div>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><b><br /></b></span></span></div>
<div>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">I'm not very familiar with the animation side of UE4, but this part of the process actually had a relatively more straightforward solution. While the first idea that came to my mind was to copy the player character's animation poses over to a new skeletal mesh component</span><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">, I wasn't particularly keen on going down that route. The reason being that there was no real need for a full-fledged animation system for our visualization mesh. We just need to set a pose once and then forget about it. Fortunately, after doing some research, I stumbled upon this neat little thing called Poseable Mesh component.</span></span></div>
<div>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><br /></span></span></div>
<div>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">The Poseable Mesh component was exactly what was required for this scenario. It was intended to be used for one and only one thing. To mirror a single pose from another skeletal mesh. No unnecessary features involved. And it comes with an inbuilt function that lets you do that by passing in a reference to the target skeletal mesh component. Just copy the target's transform coordinates as well and we're done.</span><br /></span>
<span style="font-family: helvetica;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><a href="https://4.bp.blogspot.com/-gklpQXxk0zg/W6eS66Qgb9I/AAAAAAAALTg/bfijkfIv_Uw4g1520hJvXv5VcKgkQs37wCLcBGAs/s1600/lkpv1.png" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://4.bp.blogspot.com/-gklpQXxk0zg/W6eS66Qgb9I/AAAAAAAALTg/bfijkfIv_Uw4g1520hJvXv5VcKgkQs37wCLcBGAs/s320/lkpv1.png" width="320" /></a></span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><br /></span></div>
</div>
<div>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">And now on to the final part of the experiment.</span></span></div>
<div>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><br /></span></span></div>
<div>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><b>AI Perception</b></span></span></div>
<div>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><b><br /></b></span></span></div>
<div>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">I went ahead with Unreal's inbuilt AI Perception system for this one. I'm not going over the details here as there are quite a few good resources available within the community already. But the basic gist is that I'm using it to keep track of AI agents gaining/losing track of the player character.</span><br /></span>
<span style="font-family: helvetica;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><a href="https://3.bp.blogspot.com/-qa0gyu5E2nc/W6eTgl3Y3RI/AAAAAAAALTo/B8rYJ97aPUMTV0YJMNKKLMcQqIuhU4VJACLcBGAs/s1600/guardai.png" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://3.bp.blogspot.com/-qa0gyu5E2nc/W6eTgl3Y3RI/AAAAAAAALTo/B8rYJ97aPUMTV0YJMNKKLMcQqIuhU4VJACLcBGAs/s320/guardai.png" width="320" /></a></span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><br /></span></div>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">With this information, we just plop down our visualization actor every time the player evades the AI.</span> </span></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><span style="text-align: left;"><br /></span></span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><span style="text-align: left;"><br /></span></span></div>
</div>
<div>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">And there you have it: a recreation of the Last Known Position mechanic from Splinter Cell Conviction. Here is a video preview of the system in action:</span><br /></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><br /></span></span></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/DvVe5EJwLQI/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/DvVe5EJwLQI?feature=player_embedded" width="320"></iframe></span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: helvetica;"><br /></span></div>
</div>
<div>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">With that, we have come to the end of another experiment. I've shared the project files on <a href="https://github.com/RohitKotiveetil/UnrealEngine--LastKnownPositionVisualization" target="_blank"><b>GitHub</b></a>. So feel free to use it in your work. Also head over to my <a href="https://www.youtube.com/user/Stormrage256/videos?disable_polymer=1" target="_blank"><b>YouTube channel</b></a> if you're interested in checking out more cool experiments in Unreal Engine.</span><br /></span>
<span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif"><br /></span></span> <span style="font-family: helvetica;"><span face=""helvetica neue" , "arial" , "helvetica" , sans-serif">Alright, so that's it. I hope to publish the next post sometime during the next weekend. Until then, goodbye.</span></span></div>
</div><span style="font-family: helvetica;">
</span>Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com0tag:blogger.com,1999:blog-34855895719828090.post-21277031735085256052018-06-04T12:37:00.000+05:302019-10-03T13:26:48.614+05:30Unreal Engine Experiments: Waypoint Generator<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">A few weeks ago, I came across an article on Gamasutra about the various types of UI systems used in video games. I was never particularly interested in UI design, but this article piqued my interest in the subject. So I started reading up more on the subject matter and played through a few games like Dead Space and Tom Clancy's Splinter Cell: Conviction, both of which were lauded for their innovations in the UI design space. Even with the games being almost a decade old at this point, the UI systems employed by these games are starkly different when compared to most of their contemporaries.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span> <span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Anyways, playing through Splinter Cell: Conviction got me really interested in the concept of Spatial UI design. Basically, this form of design represents UI elements that are displayed within the game world but are not actually a part of the world/setting. After doing some research on various types of systems that come under this category, I decided to recreate some of these UI components in Unreal Engine. To that end, I started work on a couple of projects, the first one being the Waypoint Generator. Now, I </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">had previously developed a couple of functional waypoint generation systems as part of my Tower Defense toolkits. So instead of starting the project from scratch, I just migrated the required blueprints over to a new project and started working from there.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"></span><br />
<a name='more'></a><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The basic underlying logic revolves around the use of nav mesh to obtain path points from the player character towards the active objective. The path thus obtained is then divided up into smaller segments before adding them to a spline component. The generation of these additional path points serves the purpose of removing weird twisting spline artifacts that occur around sharp corners when dealing with a very limited set of spline points. With that potential problem</span></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> taken care of, all that's left is to lay down instanced static meshes to display waypoints along the path.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span> </span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-mWKBc1j51RE/WxP22XM8-GI/AAAAAAAALIU/NbsS7byNAHIdHCRHz9eeZj3mBWxEU6XUgCLcBGAs/s1600/WayGen.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://1.bp.blogspot.com/-mWKBc1j51RE/WxP22XM8-GI/AAAAAAAALIU/NbsS7byNAHIdHCRHz9eeZj3mBWxEU6XUgCLcBGAs/s320/WayGen.png" width="320" /></span></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span> <span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Moving on to design structure of the implementation, it's using a child actor component to attach the waypoint generator to the player. Within the construction script of the generator there's also an option to try out the system in the editor for debugging purposes as shown below:</span></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span> </span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-NfflnDOCRzw/WxP3WJ6HOvI/AAAAAAAALIc/j712GJuAdMkYEduGeX_J673r5jMQvkqdACLcBGAs/s1600/UE4Exp_WaypointGenerator.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><img border="0" data-original-height="422" data-original-width="800" height="168" src="https://2.bp.blogspot.com/-NfflnDOCRzw/WxP3WJ6HOvI/AAAAAAAALIc/j712GJuAdMkYEduGeX_J673r5jMQvkqdACLcBGAs/s320/UE4Exp_WaypointGenerator.gif" width="320" /></span></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span> <span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The system, however, does have a limitation when it comes to displaying waypoints along certain types of inclined surfaces. Basically, from what I've heard, the navigation system in Unreal Engine tries to reduce redundancy as much as possible while generating path points. This can sometimes lead to a situation where a line drawn from one path point to the next ends up passing under the surface or quite a bit above it when dealing with stairs and other steeply inclined surfaces. Splitting up the path into smaller segments as I've mentioned earlier will not help in this scenario because it doesn't really take the navigational paths into account. It's basically just dividing a line without any other concern. But in any case, I've added a system that can mitigate this issue to some extent by using line traces to check the ground location at all points before placing down the waypoint meshes. It may not be able to correct the rotational data between path points in certain scenarios, but it always makes sure that the meshes are placed just above the ground location. If anyone knows of a better way to get around this issue using blueprints, I would really like to hear about it. So feel free to share it in the comments section.</span></span></div>
Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com0tag:blogger.com,1999:blog-34855895719828090.post-12752635824187997112018-05-07T18:51:00.002+05:302020-05-27T02:21:55.334+05:30Unreal Engine Experiments: Prototype Menu System v2.0 Update<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">About three years ago, I had created a menu system with the intent of having UI elements that could be easily tacked on to all of my projects. The project was released for free on GitHub and had received a slew of updates for a while. But after shifting my focus over to creating content for the Unreal Engine Marketplace, I found myself having very little breathing area for working on side projects. And eventually, work on the menu system was </span><span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">abandoned, though it was still available for public use in its Unreal Engine v4.9 iteration. However, lately, I've been investing more of my spare time on some fun little side projects and to be honest, finding it quite enjoyable and refreshing. So after my recent foray into <a href="https://unrealpossibilities.blogspot.com/2018/04/unreal-engine-experiments-blink-ability.html" target="">recreating the Blink ability from Dishonored</a>, I found myself thinking about bringing the project back online and actually seeing it through to completion.</span></span><br />
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><br /></span> <span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">Loading up the project again in the latest version of Unreal Engine, I was surprised to find that it was quite compatible with the new version. But as I went through the code, it became glaringly obvious that most of it would have to be completely revamped. The menu system was working quite alright, but three years is a long time, and I had originally worked on it just a few months after I first started using Unreal Engine. And going through the project again, the code spoke for itself as to how cringeworthy some of the workflows were. As a result, most of the time spent working on this new update was focused on improving upon the existing codebase. In any case, the work is done and since I absolutely suck at making video demonstrations, </span>I'll just briefly go over the various menu screens available in the v2.0 edition.</span><br />
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"> <span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"></span></span><br />
<a name='more'></a><span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><b>Main Menu</b></span></span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-xDvVblKVYuw/WvBQfyJesTI/AAAAAAAALEc/EsEzgu0Wsyg8w5GP8PpNaSYSC4jgz9RKACLcBGAs/s1600/mainmenu.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://3.bp.blogspot.com/-xDvVblKVYuw/WvBQfyJesTI/AAAAAAAALEc/EsEzgu0Wsyg8w5GP8PpNaSYSC4jgz9RKACLcBGAs/s320/mainmenu.png" width="320" /></a></div>
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><b><br /></b></span></span> <span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"> <span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">The main menu allows you to either start a new game, go to the options menu, or quit the game.</span></span><br />
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><br /></span> <span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><b>Options Menu</b></span></span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-e1bGUMN5dbo/WvBQnEBIHxI/AAAAAAAALEg/89hU2dKvH88gIIT5yTB5InxikPoVAyG-gCEwYBhgL/s1600/optionsmenu.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://3.bp.blogspot.com/-e1bGUMN5dbo/WvBQnEBIHxI/AAAAAAAALEg/89hU2dKvH88gIIT5yTB5InxikPoVAyG-gCEwYBhgL/s320/optionsmenu.png" width="320" /></a></div>
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><b><br /></b></span></span> <span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"> <span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">While the options menu has four different sub-options available, only the display and graphics options are functional in the current state.</span></span><br />
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"> <span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><br /></span> <span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><b>Display Options Menu</b></span></span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-Qvp6mZ1Lrp4/WvBQzbQIf7I/AAAAAAAALEo/L7qy8MxK1ogX03GN4ol9_RxqSMkrSaNtACLcBGAs/s1600/displayoptions.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://3.bp.blogspot.com/-Qvp6mZ1Lrp4/WvBQzbQIf7I/AAAAAAAALEo/L7qy8MxK1ogX03GN4ol9_RxqSMkrSaNtACLcBGAs/s320/displayoptions.png" width="320" /></a></div>
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><b><br /></b></span></span> <span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"> <span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">Players can control the screen resolution and window mode settings through this menu.</span></span><br />
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"> <span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><br /></span> <span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><b>Graphics Options Menu</b></span></span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-JTil1tqhhIM/WvBQ5yvlbvI/AAAAAAAALEw/DdR5jqL24c4Y6zxFp4UNMAZDEMEjFRX4QCLcBGAs/s1600/graphicsoptions.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://4.bp.blogspot.com/-JTil1tqhhIM/WvBQ5yvlbvI/AAAAAAAALEw/DdR5jqL24c4Y6zxFp4UNMAZDEMEjFRX4QCLcBGAs/s320/graphicsoptions.png" width="320" /></a></div>
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><br /></span> <span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">As shown in the screenshot, the graphics options menu allows you to control the following settings:</span></span><br />
<br />
<ul style="text-align: left;">
<li><span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">AA Quality</span></li>
<li><span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">Foliage Quality</span></li>
<li><span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">Post-Processing Quality</span></li>
<li><span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">Texture Quality</span></li>
<li><span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">Shadow Quality</span></li>
<li><span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">View Distance Quality</span></li>
<li><span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">Effects Quality</span></li>
<li><span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">VSync</span></li>
</ul>
<br />
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"> <span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><b>Loading Screen</b></span></span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-ruBxgzhELfI/WvBQ_L0XOmI/AAAAAAAALE0/pKHN-g-o8xw1phRhPUALB5W1XhNmQnoAQCLcBGAs/s1600/loading.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://2.bp.blogspot.com/-ruBxgzhELfI/WvBQ_L0XOmI/AAAAAAAALE0/pKHN-g-o8xw1phRhPUALB5W1XhNmQnoAQCLcBGAs/s320/loading.png" width="320" /></a></div>
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><b><br /></b></span></span> <span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"> <span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">It's basically a screenshot that gets displayed for a specified period of time. A throbber is placed to indicate that the level is being loaded.</span></span><br />
<br />
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"> <span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><b>Pause Menu</b></span></span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-y_aGHOAedak/WvBREH5nUTI/AAAAAAAALE4/4TPP3RNEEfoaO4TbduKYtQdAsrqroZVJACLcBGAs/s1600/pausemenu.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://3.bp.blogspot.com/-y_aGHOAedak/WvBREH5nUTI/AAAAAAAALE4/4TPP3RNEEfoaO4TbduKYtQdAsrqroZVJACLcBGAs/s320/pausemenu.png" width="320" /></a></div>
<br />
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"> <span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">The pause menu provides the options to either resume the game, exit to the main menu or to quit directly to the desktop.</span></span><br />
<span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><br /></span> <span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;"><br /></span> <span style="font-family: "helvetica neue", "arial", "helvetica", sans-serif;">Well, that covers all the major features of the Prototype Menu System in its current state. I'm planning to introduce more features over future updates in order to make it a more robust and complete system. But for now, you can grab the source code from GitHub at: <a href="https://github.com/RohitKotiveetil/UnrealEngine--PrototypeMenuSystem" target="_blank"><b>https://github.com/RohitKotiveetil/UnrealEngine--PrototypeMenuSystem</b></a></span></span></div>
Rohit Kotiveetilhttp://www.blogger.com/profile/10311178990877620407noreply@blogger.com0