{"id":1004,"date":"2019-12-13T02:14:47","date_gmt":"2019-12-13T02:14:47","guid":{"rendered":"https:\/\/www.danielparente.net\/en\/2019\/12\/13\/how-to-make-your-game-in-multiplayer-mode-in-unreal-engine-4\/"},"modified":"2019-12-13T02:14:47","modified_gmt":"2019-12-13T02:14:47","slug":"how-to-make-your-game-in-multiplayer-mode-in-unreal-engine-4","status":"publish","type":"post","link":"https:\/\/www.danielparente.net\/en\/2019\/12\/13\/how-to-make-your-game-in-multiplayer-mode-in-unreal-engine-4\/","title":{"rendered":"How to make your game in multiplayer mode in Unreal Engine 4"},"content":{"rendered":"<p> [ad_1]<br \/>\n<\/p>\n<div><span class=\"wpfp-span\"><img decoding=\"async\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/plugins\/wp-favorite-posts\/img\/heart.png\" alt=\"Favorite\" title=\"Favorite\" class=\"wpfp-img\"\/><noscript><img decoding=\"async\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/plugins\/wp-favorite-posts\/img\/heart.png\" alt=\"Favorite\" title=\"Favorite\" class=\"wpfp-img\"\/><\/noscript><img decoding=\"async\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/plugins\/wp-favorite-posts\/img\/loading.gif\" alt=\"Loading\" title=\"Loading\" class=\"wpfp-hide wpfp-img\"\/><noscript><img decoding=\"async\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/plugins\/wp-favorite-posts\/img\/loading.gif\" alt=\"Loading\" title=\"Loading\" class=\"wpfp-hide wpfp-img\"\/><\/noscript><a class=\"wpfp-link\" href=\"https:\/\/indiewatch.net\/?wpfpaction=add&amp;postid=39725\" title=\"Add to favorites\" rel=\"follow noopener\" data-wpel-link=\"internal\" target=\"_blank\">Add to favorites<\/a><\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">Making <strong>multiplayer<\/strong> games is something most developers are becoming more and more interested in. I remember myself when I was starting to develop games using the<strong> Unreal Engine 4<\/strong>, sitting there and thinking about how to make the first basic combat system. In my mind, I would think of how to make all the cool stuff such as a HUD showing the character\/pawn\u2019s health, the damage to it, and how to make the character die when the health is 0. I&#8217;d wonder how to get all that working in <strong>multiplayer<\/strong>.<\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">So I figured it may be a good topic to cover in a tutorial. What we are doing here is exactly this. Based on the twin-stick shooter, we will first make the template multiplayer ready, then we build a small but solid system which enables you to deal damage to other players and their health is shown above the pawn\u2019s \u201chead\u201d.<\/span><\/p>\n<p><span class=\"s2\"><b>What do you need to get started?<\/b><\/span><span class=\"s1\"><br \/>You only need the Unreal Engine 4.20 and some basic skills. This for sure also works with other versions, 4.20 is just the version I used when creating this tutorial \ud83d\ude42<\/span><\/p>\n<p class=\"p1\"><span class=\"s1\"><br \/><\/span><span class=\"s2\"><b>1. Preparing a multiplayer ready project<\/b><\/span><span class=\"s1\"><br \/>First of all we create a new project, based on the \u201cTwin Stick Shooter\u201d blueprint template. I figured this is a good template to start with because it\u2019s basically a kind of third-person view and already comes with the ability to shoot projectiles.<\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">So, enter a <a href=\"https:\/\/indiewatch.net\/2016\/06\/07\/why-no-one-wants-to-hear-about-the-game-you-just-finished-making\/\" title=\"project\" alt=\"project\" data-wpel-link=\"internal\" rel=\"follow noopener\" target=\"_blank\">project<\/a> name and hit \u201cCreate Project\u201d to get it started.<\/span><\/p>\n<p><span class=\"s1\"><img fetchpriority=\"high\" decoding=\"async\" class=\"gr-progress alignnone wp-image-39793 size-full\" title=\"How to make your game in multiplayer mode in Unreal Engine 4\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/001-1.jpg\" alt=\"How to make your game in multiplayer mode in Unreal Engine 4\" width=\"1112\" height=\"776\"\/><noscript><img fetchpriority=\"high\" decoding=\"async\" class=\"gr-progress alignnone wp-image-39793 size-full\" title=\"How to make your game in multiplayer mode in Unreal Engine 4\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/001-1.jpg\" alt=\"How to make your game in multiplayer mode in Unreal Engine 4\" width=\"1112\" height=\"776\"\/><\/noscript><\/span><\/p>\n<p class=\"p4\"><span class=\"s1\"><b>1.1 The Player Start<\/b><\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">As soon as the new project is open, we have to do a small preparation step to make it work for multiplayer properly.<\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">Go to the World Outliner in the top right corner and search for the \u201cNetworkPlayerStart\u201d. Now remove this from the level by selecting it and hitting the delete key on your keyboard.<\/span><\/p>\n<p><img decoding=\"async\" class=\"alignnone wp-image-39794 size-full\" title=\"How to make your game in multiplayer mode in Unreal Engine 4\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/002.jpg\" alt=\"How to make your game in multiplayer mode in Unreal Engine 4\" width=\"409\" height=\"290\"\/><\/p>\n<p><noscript><img decoding=\"async\" class=\"alignnone wp-image-39794 size-full\" title=\"How to make your game in multiplayer mode in Unreal Engine 4\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/002.jpg\" alt=\"How to make your game in multiplayer mode in Unreal Engine 4\" width=\"409\" height=\"290\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">Now go to the right and take a \u201cPlayerStart\u201d. Drag it into the level and place it at the other end of the map, so it is looking towards the blue spaceship player pawn.<\/span><\/p>\n<p>Now click the small arrow, next to the play button in the top toolbar. There you can set a number of 2 players. Hit the play button and you are able to play with 2 small blue spaceships. (Second player game window is maybe hidden somewhere)<\/p>\n<p><img decoding=\"async\" class=\"alignnone wp-image-39795 size-full\" title=\"How to make your game in multiplayer mode in Unreal Engine 4\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/003.jpg\" alt=\"How to make your game in multiplayer mode in Unreal Engine 4\" width=\"383\" height=\"462\"\/><\/p>\n<p><noscript><img decoding=\"async\" class=\"alignnone wp-image-39795 size-full\" title=\"How to make your game in multiplayer mode in Unreal Engine 4\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/003.jpg\" alt=\"How to make your game in multiplayer mode in Unreal Engine 4\" width=\"383\" height=\"462\"\/><\/noscript><\/p>\n<p class=\"p4\"><span class=\"s1\"><b>1.2 Replicating Player Movement<\/b><\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">You will soon recognize that the second player can move his spaceship, but it is only moving on his screen, not inside the editor which is the server in our current setup. This happens because we have to do some proper replication for the spaceship pawn now.<\/span><\/p>\n<p>Therefore, end the play session and open the TwinStichPawn <a href=\"https:\/\/indiewatch.net\/2018\/03\/26\/save-the-date-for-7th-annual-global-game-congress\/\" title=\"Blueprint\" alt=\"Blueprint\" data-wpel-link=\"internal\" rel=\"follow noopener\" target=\"_blank\">Blueprint<\/a> (it\u2019s in TwinStickBP\/Blueprints\/ inside the ContentBrowser). There you have to look for this logic which is happening in the Tick Event:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39796\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/004-1.jpg\" alt=\"\" width=\"992\" height=\"532\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39796\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/004-1.jpg\" alt=\"\" width=\"992\" height=\"532\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">Right-click and select \u201cAdd Custom Event\u201d. Call it \u201cServer_ApplyMovement\u201d. Now, when having the new read node selected, you can go to the details panel on the right, set \u201cReplicates\u201d to \u201cRun on Server\u201d and check the \u201cReliable\u201d checkbox. Now create two inputs by clicking the plus next to \u201cInputs\u201d. The first one is called \u201cDeltaLocation\u201d and needs to be a Vector. The second one is called \u201cNewRotation\u201d and needs to be a Rotator.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39797\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/005.jpg\" alt=\"\" width=\"761\" height=\"364\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39797\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/005.jpg\" alt=\"\" width=\"761\" height=\"364\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">Next we have to move this new event node we just created and put it in-between the existing logic.<br \/>The new server node has to be connected to the <a href=\"https:\/\/indiewatch.net\/2016\/11\/06\/how-to-finish-your-project\/\" title=\"SetWorldRotation node\" alt=\"SetWorldRotation node\" data-wpel-link=\"internal\" rel=\"follow noopener\" target=\"_blank\">SetWorldRotation node<\/a>, the \u201cDelatLocation\u201d input connects to the AddActorWorldOffest and the NewRotation to the SetWorldRotation node.<\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">And lastly we have to execute our new event by doing a right click and typing \u201cServer_ApplyMovement\u201d. Add this to the even graph and connect it so it is executed by the True output of the branch node. Connect the Vector and Rotator input of our event with the RotationFromXVector as well as the yellow existing Vector line.<\/span><\/p>\n<p>Here is an image of what this has to look like:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39799\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/006.jpg\" alt=\"\" width=\"1490\" height=\"669\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39799\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/006.jpg\" alt=\"\" width=\"1490\" height=\"669\"\/><\/noscript><\/p>\n<p>\u00a0<\/p>\n<p class=\"p1\"><span class=\"s1\">Now click on \u201cShipMeshComponent\u201d in the components tab on the top right. Then search for \u201cComponent Replicates\u201d in the details panel on the right. Check this checkbox.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39800\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/007.jpg\" alt=\"\" width=\"533\" height=\"327\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39800\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/007.jpg\" alt=\"\" width=\"533\" height=\"327\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">The reason why we need this change is as follows: <\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">In a server-client constellation, the server is always the one holding all the information like a master. So when a pawn should move, this has to happen on the server, so all the clients (which are only connected to the server and not to each other) can grab this new information and show it on their side to the player.<br \/>We call now our Server_ApplyMovement event which is always executed on the server thanks to our replication setting inside the details panel. This means the movement gets applied on the server-side and is then replicated properly (thanks to checking the checkbox) to all the clients.<br \/>And that\u2019s all the magic behind it \ud83d\ude42<\/span><\/p>\n<p class=\"p4\"><span class=\"s1\"><b>1.3 Keeping Things Clean When it Comes to Networking<\/b><\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">Another thing you may have noticed is the red colored comment I wrote there for the server-side logic. It\u2019s always best practice to keep your logic organized so it\u2019s easily readable. When I do multiplayer projects I, therefore, work with multiple colors for the comments, depending on where the logic will be executed.<br \/><\/span><span class=\"s5\">Red: Executes on the Server<\/span><span class=\"s1\"><br \/><\/span><span class=\"s6\">Green: Executes on the Client<\/span><span class=\"s1\"><br \/><\/span><span class=\"s7\">Blue: General logic that may get executed on Server and\/or Client<\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">Give playing a short try to see how well the movement is replicated now.<\/span><\/p>\n<p class=\"p1\"><span class=\"s8\"><b>1.4 Replicating the Projectile<\/b><\/span><span class=\"s1\"><br \/>Next step is to also replicate the projectiles properly. As you may have noticed, they are only shown on the \u201cShooting Client\u201d but not replicated at all.<\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">First we have to do a small preparation inside the TwinStickProjectile Blueprint (inside TwinStickBP\/Blueprints).<\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">Click \u201cClass Defaults\u201d on the top and check the \u201cReplicates\u201d, as well as the &#8220;Replicates Movement\u201d checkbox on the right, inside the details panel.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39801\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/008.jpg\" alt=\"\" width=\"461\" height=\"837\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39801\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/008.jpg\" alt=\"\" width=\"461\" height=\"837\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">Now we take a quick moment to clean up the \u201cEvent Hit\u201d logic (so it is more readable) inside the EventGraph and also add a \u201cHasAuthority\u201d node to it, as you can see in this screenshot:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39802\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/009.jpg\" alt=\"\" width=\"1866\" height=\"678\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39802\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/009.jpg\" alt=\"\" width=\"1866\" height=\"678\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">This \u201cHasAuthority\u201d is another way for executing logic on the server side. When it\u2019s getting executed on the server, it is passing the execution to the \u201cAuthority\u201d output pin, otherwise to \u201cRemote\u201d. The difference to having a \u201cRun on Server\u201d replicated custom event is that this node only differentiates between where it is executed. In our case, this means the following logic is only executed on the server, not on any client. The replicated event on the other hand always executes the logic on the server, from wherever it is getting called. So it can probably also get called multiple times, one time for each client calling the event. And we want to avoid that and only handle our projectile hit event on the server since this is what matters \ud83d\ude42<\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">Now go back to the TwinStickPan Blueprint and look for this logic inside the tick event:<br \/><\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39803\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/010.jpg\" alt=\"\" width=\"749\" height=\"205\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39803\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/010.jpg\" alt=\"\" width=\"749\" height=\"205\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">We now have to move this logic now to the server-side, so the project is spawned there and replicated properly to all the clients. Therefore create a custom event and make it execute on the server only (as we did it in step 1.2). Call the event \u201cServer_FireShot\u201d and give it a \u201cDirection\u201d input of type Vector.<\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">Now move the \u201cFireShot\u201d node to the \u201cServer_FireShot\u201d event and wire it up. Right click and add a \u201cServer_FireShot\u201d execution node and execute it inside the tick event, where the \u201cFireShot\u201d was previously.<br \/>So it should look like this:<\/span><\/p>\n<p>\u00a0<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39804\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/011.jpg\" alt=\"\" width=\"860\" height=\"512\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39804\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/011.jpg\" alt=\"\" width=\"860\" height=\"512\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">This already makes our projectiles replicate properly since they are always spawned on the server.<\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">Now we have to make the shoot sound also work fine. Since it\u2019s now played on the server, it\u2019s not played properly anymore. Therefore we create a new custom event and call it \u201cMulti_PlayFireSound\u201d. Go to the details panel and set \u201cReplicates\u201d to \u201cMulticast\u201d. What this does is execute the event on all clients. But it, therefore, has to be executed from the server (which is done in our case). Also, add a \u201cLocation\u201d input to the event with type Vector.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39806\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/012.jpg\" alt=\"\" width=\"517\" height=\"265\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39806\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/012.jpg\" alt=\"\" width=\"517\" height=\"265\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">Now add a \u201cPlay Sound at Location\u201d node and connect it to the new Multicast event. Also connect the location input to our events location. Make a right click and search for \u201cGet Fire Sound\u201d. Add this variable and connect it to the Sound input of our new node. So it looks like this:<br \/><\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39807\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/013.jpg\" alt=\"\" width=\"570\" height=\"308\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39807\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/013.jpg\" alt=\"\" width=\"570\" height=\"308\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">Lastly, double-click the &#8220;FireShot\u201c node. This brings you into the function where you need to search for this logic:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39808\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/014.jpg\" alt=\"\" width=\"813\" height=\"346\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39808\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/014.jpg\" alt=\"\" width=\"813\" height=\"346\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">Remove the PlaySoundAtLocation node and replace it by our new \u201eMulti_PlayFireSound\u201c node. So it should look like this:<br \/><\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39809\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/015.jpg\" alt=\"\" width=\"760\" height=\"301\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39809\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/015.jpg\" alt=\"\" width=\"760\" height=\"301\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">Alright, now you are also able to shoot with proper replication. Give it a try!<\/span><\/p>\n<p class=\"p5\"><span class=\"s1\"><b>2. Adding the HUD<\/b><\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">Now we are adding the HUD to the Character. Therefore we first create a new widget by right-clicking and selecting \u201cUser Interface \/ Widget Blueprint\u201d. Call it \u201cBPW_PawnHUD\u201d and open it.<\/span><\/p>\n<p>Now drag a \u201cProgress Bar\u201d from the palette panel into the viewport and rename it as \u201cProgressBar_Health\u201d inside the Hierarchy tab in the bottom left.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39810\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/016.jpg\" alt=\"\" width=\"1505\" height=\"656\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39810\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/016.jpg\" alt=\"\" width=\"1505\" height=\"656\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">Now while having the progress bar selected, go to the details panel on the right, click the \u201cAnchors\u201d dropdown and select the center position:<br \/><\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39811\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/017.jpg\" alt=\"\" width=\"450\" height=\"455\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39811\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/017.jpg\" alt=\"\" width=\"450\" height=\"455\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">Next, set Position X and Y to 0 to move the bar to the center. Set Size Y to 10 to make it not that high (but that for sure depends on your preference). Also set Alignment X and Y to 0.5. This moves the pivot point of this widget to the center of the bar &#8211; so it\u2019s really in the center finally \ud83d\ude42<\/span><\/p>\n<p>Now also change the \u201eFill Color and Opacity\u201c to something more reddish. I used FF0003FF for the color.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39812\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/018.jpg\" alt=\"\" width=\"427\" height=\"593\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39812\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/018.jpg\" alt=\"\" width=\"427\" height=\"593\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">Now we jump into our TwinStickPawn blueprint again. There, add a widget component by clicking the \u201c+ Add Component\u201d button in the top left corner. Rename the new component to \u201cPawnHUD\u201d.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39813\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/019.jpg\" alt=\"\" width=\"285\" height=\"182\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39813\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/019.jpg\" alt=\"\" width=\"285\" height=\"182\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">Now, while having the PawnHUD selected, go to the details panel on the right. There set the location Z value to 180.0 to move the widget above the pawns \u201chead\u201d. Now set the \u201cSpace\u201d to \u201cScreen\u201d and for \u201cWidgetClass\u201d you select our newly created \u201cBPW_PawnHUD\u201d widget.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39814\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/020.jpg\" alt=\"\" width=\"546\" height=\"769\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39814\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/020.jpg\" alt=\"\" width=\"546\" height=\"769\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">When you play the game now, you\u2019ll see a nice health bar above your pawn.<\/span><\/p>\n<p class=\"p1\"><span class=\"s2\"><b>3. Adding and showing the current health<\/b><\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">Since we have a health bar now, we also want to show the pawns actual health. Therefore we create two new float variables inside the TwinStickPawn: \u201cHealth_Current\u201d and \u201cHealth_Max\u201d<br \/>You can do that using the small \u201c+\u201d button inside the \u201cMy Blueprint\u201d tab.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39815\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/021.jpg\" alt=\"\" width=\"301\" height=\"422\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39815\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/021.jpg\" alt=\"\" width=\"301\" height=\"422\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">Now compile and save. Then click the \u201cHealth_Max\u201d variable and look at the details panel on the right. Here we can now set a default max health of 100 for our pawn.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39816\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/022.jpg\" alt=\"\" width=\"549\" height=\"455\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39816\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/022.jpg\" alt=\"\" width=\"549\" height=\"455\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">Next, click the \u201cHealth_Current\u201d variable and again look at the details panel. Here we now do something special. We set \u201cReplication\u201d to \u201cReplicated\u201d. This lets the variable always be replicated (\/synchronized) from the server to the clients. This way we can make sure this value is the same everywhere as long is its changes are written through the server.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39817\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/023.jpg\" alt=\"\" width=\"546\" height=\"461\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39817\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/023.jpg\" alt=\"\" width=\"546\" height=\"461\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">Now we go into the Event Graph and do a right click. Type \u201cEvent BeginPlay\u201d and hit enter.<\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">Next, add a sequence node (to be prepared for further logic which may not need to be executed on the server) and a SwitchHasAuthority node. Lastly, we set our \u201cHealth_Current\u201d value to \u201cHealth_Max\u201d. You can get such variable nodes by doing a right click and typing \u201cGet Health_Max\u201d or \u201cSet Health_Current\u201d.<\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">Your logic should then look like this:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39818\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/024.jpg\" alt=\"\" width=\"920\" height=\"307\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39818\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/024.jpg\" alt=\"\" width=\"920\" height=\"307\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">It\u2019s setting the current health to our predefined max value. And that\u2019s happening on the server so it\u2019s properly replicated to all clients.<\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">For the next step we have to jump quickly to the \u201cBPW_PawnHUD\u201d. There we click on \u201cGraph\u201d in the top right corner and then create a new variable called \u201cPawnRef\u201d. For the variable type use \u201cTwinStickPawn Object Reference\u201d. This will be our reference to the owning pawn so we can access its health. To keep things organized set the \u201cCategory\u201d to \u201cInternal|References\u201d for our new variable inside the details panel in the top left corner. This creates a new variable category called \u201cInternal\u201d and a subcategory, thanks to the \u201c|\u201d character, named \u201cReferences\u201d. Now your variables should look like this:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39819\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/025.jpg\" alt=\"\" width=\"359\" height=\"583\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39819\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/025.jpg\" alt=\"\" width=\"359\" height=\"583\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">Next, click on \u201cDesigner\u201d in the top right corner and select our progress bar. On the right, inside the details panel, search for \u201cPercent\u201d. Click the little \u201cBind\u201d button and select \u201cCreate Binding\u201d. This brings you back to the graph into a newly created function. Rename this function quick to \u201cGet_ProgressBar_Health_Percent\u201d to have a clean naming. You can do that on the left by right-clicking the function and selecting \u201cRename\u201d.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39820\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/026.jpg\" alt=\"\" width=\"346\" height=\"414\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39820\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/026.jpg\" alt=\"\" width=\"346\" height=\"414\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">Now we build our logic inside our new function to display the actual pawn health using our progress bar. <\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">Therefore we drag and drop our recently created PawnRef into the graph. Now click and drag the blue connector from the variable and let it go, which makes a context menu appear. There you type \u201cGet Health_Current\u201d and hit enter. Do the same for \u201cGet Health_Max\u201d.<\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">Now divide \u201cHealth_Current by Health_Max\u201d. You can create the needed divider node by doing a right click and typing \u201cfloat\/float\u201d and hitting enter. Connect the result of our calculation to the Return Node.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39821\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/027.jpg\" alt=\"\" width=\"804\" height=\"309\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39821\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/027.jpg\" alt=\"\" width=\"804\" height=\"309\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">You may ask what our calculation is doing there. I\u2019ll give you a few examples:<\/span><\/p>\n<pre class=\"p1\"><span class=\"s1\">Max Health = 100, Current Health = 50.<\/span>\n\n<span class=\"s1\">50 \/ 100 = 0.5 -&gt; since the bar expects a value between 0 and 1, this makes it half full = 50%.<\/span>\n\n<span class=\"s1\">Max Health = 100, Current Health = 100<\/span>\n\n<span class=\"s1\">100 \/ 100 = 1<\/span><\/pre>\n<p>I guess you get now how it\u2019s working \ud83d\ude42<\/p>\n<p class=\"p1\"><span class=\"s1\">Lastly, we jump back to our TwinStickPawn Blueprint. There we have to let our HUD know who the actual owner is.<span class=\"Apple-converted-space\">\u00a0 <\/span>Therefore we create the following logic:<br \/><\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39822\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/028.jpg\" alt=\"\" width=\"1099\" height=\"495\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39822\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/028.jpg\" alt=\"\" width=\"1099\" height=\"495\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">Drag in the PawnHUD from the top right and then click, drag and let go of the connector pin and type the name of the next node to be able to add it. Connect this new logic to the Sequence node which we prepared earlier inside the BeginPlay event. The reason why we are not doing this only on the server or even replicated is because it has to happen on every client and always pass a different reference to the HUD which exists independently on the clients and is not replicated at all.<\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">You are now able to play and see the actual pawn\u2019s health. Give it a try!<\/span><\/p>\n<p class=\"p5\"><span class=\"s1\"><b>4. The Final Step: Dealing Damage<\/b><\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">In this step, we make the projectile deal damage. Thanks to our good preparations this is fairly easy now. Open the TwinStickProjectile again, do a right click and type \u201cApplyDamage\u201d. Then hit enter to add the node.<\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">We now put this node after the first \u201cIsValid\u201d node. For the \u201cBaseDamage\u201d input we do a small random generation. Add a \u201cRandom Float in Range\u201d node and give it a Min and Max value. As its name is already telling you, it\u2019s generating a random value within the given range. Connect its output to the ApplyDamage node. Connect the DamagedActor input with the \u201cOther\u201d connection from our Event Hit node. The result should look like this:<br \/><\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39823\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/029.jpg\" alt=\"\" width=\"1236\" height=\"422\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39823\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/029.jpg\" alt=\"\" width=\"1236\" height=\"422\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">Lastly get back to the TwinStickPawn Blueprint. There do a right click and type \u201cEvent AnyDamage\u201d and hit enter to create the needed node. Now build the following logic:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39824\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/030.jpg\" alt=\"\" width=\"1058\" height=\"355\"\/><\/p>\n<p><noscript><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-39824\" src=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/030.jpg\" alt=\"\" width=\"1058\" height=\"355\"\/><\/noscript><\/p>\n<p class=\"p1\"><span class=\"s1\">This first subtracts the damage amount from our current health. Then we use a clamp node to limit it within 0 and the Health_Max to avoid unwanted numbers. After writing the result back to our Health_Current variable, we check if our result is &lt;= 0.0<br \/>If this is the case, we destroy our pawn since it is dead.<\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">You may also recognize that I commented this logic read again, even though we didn\u2019t call it specifically on the server. The AnyDamage event is always executed on the server, no matter where it is called. So, in that case, it\u2019s already handled for you.<\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">Now give it a try to play our final result and see how it works \ud83d\ude42<\/span><\/p>\n<p><strong>Bonus:<\/strong> I made the files for the project available for download right <a href=\"https:\/\/data-jeaegoras.netdna-ssl.com\/wp-content\/uploads\/MultiplayerHUD_Project.rar\" data-wpel-link=\"internal\" rel=\"follow noopener\" target=\"_blank\">here<\/a>. Enjoy!<\/p>\n<\/div>\n<p>[ad_2]<br \/>\n<br \/><a href=\"https:\/\/indiewatch.net\/2018\/11\/28\/how-to-make-your-game-in-multiplayer-mode-in-unreal-engine-4\/\" target=\"_blank\" rel=\"noopener\">Source link <\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>[ad_1] Add to favorites Making multiplayer games is something most developers are becoming more and more interested in. I remember myself when I was starting to develop games using the Unreal Engine 4, sitting there and thinking about how to make the first basic combat system. In my mind, I would think of how to [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1005,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","jetpack_post_was_ever_published":false},"categories":[18],"tags":[],"class_list":["post-1004","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-gamedev"],"blocksy_meta":[],"jetpack_featured_media_url":"https:\/\/e928cfdc7rs.exactdn.com\/info\/uploads\/sites\/3\/2019\/12\/How-to-make-your-game-in-multiplayer-mode-in-Unreal-scaled.jpg?strip=all","jetpack_shortlink":"https:\/\/wp.me\/p2TFCd-gc","jetpack_sharing_enabled":true,"jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/www.danielparente.net\/en\/wp-json\/wp\/v2\/posts\/1004","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.danielparente.net\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.danielparente.net\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.danielparente.net\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.danielparente.net\/en\/wp-json\/wp\/v2\/comments?post=1004"}],"version-history":[{"count":0,"href":"https:\/\/www.danielparente.net\/en\/wp-json\/wp\/v2\/posts\/1004\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.danielparente.net\/en\/wp-json\/wp\/v2\/media\/1005"}],"wp:attachment":[{"href":"https:\/\/www.danielparente.net\/en\/wp-json\/wp\/v2\/media?parent=1004"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.danielparente.net\/en\/wp-json\/wp\/v2\/categories?post=1004"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.danielparente.net\/en\/wp-json\/wp\/v2\/tags?post=1004"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}