Dear Community,
Replication Series
Part 1: Change Pawn Materials Based On a Unique PlayerID
Part 2: Efficiently Replicate Custom Special Effects & Projectile Bounces
Part 3: Grapple Hook and Custom Pawn Movements
Part 4: Listen Servers - Replicating Special Effects
In this tutorial I show you how you can replicate your own custom pawn movement mechanics!
I am showing you how you can create your own truly unique player movement mechanics for your multiplayer game!
In this example I am extending a previous tutorial on how to create a tether/grapple hook system for skeletal mesh pawns.
Video Tutorial: Grapple Hook / Tether System for Skeletal Mesh Pawns, Complete Code and Grapple Beam Effect For You
I modified the code in tutorial above to create a multiplayer version of this custom player movement mechanic!
As you can see from the video, the changes to the pawn's movement are:
1. player controlled, meaning the pawn movements cannot simply be predicted, but this allows for a truly new game mechanic to be replicated in unreal multiplayer games.
2. quite dramatic, enabling movement patterns not possible with standard jump or dodge pawn functions
~~~
Code For You
Below is the entire code I am using for the tether movements of the player pawns that you see in my video !
I took out all the code about the tether effect because all those effects are run clientside
The purpose of this tutorial is to show you how you can easily create custom player movement systems,
and below is the entire code for the very unusual player movements you see replicated in the video.
Things to Note
-All functions that are affecting the pawn's movement are being run on the SERVER, not the client.
-All the server functions are reliable because they must occur in right order so that the pawn's
position is same for all clients regardless of individual connection speeds
-tetherNetboost is used because vectors get compressed across network and so the end result is that the server needs to run with a higher velocity value, or else the compressed vector needs to be reexpanded later.
~~~
Why Running Player Movement Changes on Server?
The player can use WASD to affect the tether movements so instead of simulated I need to have the server update the pawn position on all client machines.
Additionally, the way unreal engine handles pawn movement can be quite intricate, to get an idea of it look at:
//playercontroller.uc
To avoid getting into all this complexity in order to create custom player pawn movements I chose to just update the pawn's velocity on the server.
It is not efficient to run a lot of code on the server however, so please note that all the tether special effects you see in video are running clientside, in the above code are the only server funcs, which are server funcs because it would be very hard to predict player input regarding the tether system.
~~~
Good Network Coding Policy
Run As Much Client-side As You Can
It is very good practice to run as much code as you can clientside !
The reason that the tether visual effects replicate so nicely in the video is because all tether effects, even for other players, are actuall run client side.
~~~
Tether Effect Overview
Basically I only replicate a single state change, determining whether or not the player is tethering or not using bool istethering.
Because this variable is repnotified, it will be updated for all players' machines, in addition to the player who is doing the tethering.
Because the actual visual game mechanic of tethering is simple, just drawing a beam from the player to the tether location, I can run the entire effect client side because the pawn's position is getting updated properly on the server via the code above.
This means that the pawn's position for all player machines is already up to date, and I can just draw the effect clientside!
I did not include all the tether effect code because it would complicate my focus for this tutorial
~~~
Summary
Using the code above as a guide, as well as referring to my earlier tether tutorial, you can see exactly how I created a custom pawn movement game mechanic that is able to work correctly in multiplayer !

Rama
Replication Series
Part 1: Change Pawn Materials Based On a Unique PlayerID
Part 2: Efficiently Replicate Custom Special Effects & Projectile Bounces
Part 3: Grapple Hook and Custom Pawn Movements
Part 4: Listen Servers - Replicating Special Effects
In this tutorial I show you how you can replicate your own custom pawn movement mechanics!
I am showing you how you can create your own truly unique player movement mechanics for your multiplayer game!
In this example I am extending a previous tutorial on how to create a tether/grapple hook system for skeletal mesh pawns.
Video Tutorial: Grapple Hook / Tether System for Skeletal Mesh Pawns, Complete Code and Grapple Beam Effect For You
I modified the code in tutorial above to create a multiplayer version of this custom player movement mechanic!
As you can see from the video, the changes to the pawn's movement are:
1. player controlled, meaning the pawn movements cannot simply be predicted, but this allows for a truly new game mechanic to be replicated in unreal multiplayer games.
2. quite dramatic, enabling movement patterns not possible with standard jump or dodge pawn functions
~~~
Code For You
Below is the entire code I am using for the tether movements of the player pawns that you see in my video !
I took out all the code about the tether effect because all those effects are run clientside
The purpose of this tutorial is to show you how you can easily create custom player movement systems,
and below is the entire code for the very unusual player movements you see replicated in the video.
Code:
//pawn class var float deltaTimeBoostMultiplier; //play regular animations or only skeletal controller? var bool SkeletalControllerOnly; var bool TetheringAnimOnly; //======================= // Tether System //======================= var actor curTargetWall; var vector wallHitLoc; var ParticleSystemComponent tetherBeam; var float tetherMaxLength; var float tetherlength; var float tetherNetBoost; var vector prevTetherSourcePos; var Rotator r; var vector vc; var vector vc2; //repnotified for clientside tether effects var repnotify bool isTethering; simulated function PostBeginPlay() { //very important line super.PostBeginPlay(); //NET MODE SPECIFIC if(worldinfo.netmode == NM_Standalone){ tetherNetBoost = 1; } else { tetherNetBoost = 3; } } //called from controller class reliable server function increaseTether() { if (tetherlength > tetherMaxLength) return; tetherlength += 20; } //called from controller class reliable server function decreaseTether() { if (tetherlength <= 0) { tetherlength = 0; return; } tetherlength -= 20; } //called from controller class reliable server function detachTether() { curTargetWall = none; //change pawn physics SetPhysics(PHYS_Walking); isTethering = false; TetheringAnimOnly = false; } //called from controller class reliable server function createTether(rotator playerRot) { local vector hitLoc; local vector hitNormal; local actor wall; //~~~ Trace ~~~ vc = getPowerStartLocation(); //trace from VictoryUnit vc2 = Vector(playerRot); vc += 60 * vc2; //trace to see if ball still close to most recent surface //trace only to tether's max length wall = Self.trace(hitLoc, hitNormal, vc + tetherMaxLength * vc2, vc ); if(Wall == none) return; //~~~~~~~~~~~~~~~ // Tether Success //~~~~~~~~~~~~~~~ //state isTethering = true; curTargetWall = Wall; wallHitLoc = hitLoc; //get length of tether from starting //position of object and wall tetherlength = vsize(hitLoc - Location); } //called every tick that istethering is true //on the server reliable server function tetherCalcs() { //~~~~~~~~~~~~~~~~~~~~~~~~ //Actual Tether Constraint //~~~~~~~~~~~~~~~~~~~~~~~~ //vector between player and tether loc vc = Location - curTargetWall.Location; if (Vsize(vc) > tetherlength) { TetheringAnimOnly = true; SetPhysics(PHYS_Falling); vc2 = normal(vc); //pc.optimize("velocity diff"@abs(vsize(Normal(velocity) - vc2))); //moving in same direction as tether? if(abs(vsize(Normal(velocity) - vc2)) > 1){ //limit max velocity applied to pawn in direction of tether if(vsize(velocity) < 3000 * deltaTimeBoostMultiplier){ velocity -= vc2 * 120 * tetherNetBoost; } } //not moving in direction of pawn //apply as much velocity as needed to prevent falling //allows sudden direction changes else { velocity -= vc2 * 120 * tetherNetBoost; } } else { //only stop regular anims when changing pawn velocity TetheringAnimOnly = false; } } Simulated Event Tick(float DeltaTime) { Super.Tick(DeltaTime); //for fps issues and keeping things properly up to date deltaTimeBoostMultiplier = deltatime * 40; //=== TETHER ==== if (isTethering) { tetherCalcs(); } }
-All functions that are affecting the pawn's movement are being run on the SERVER, not the client.
-All the server functions are reliable because they must occur in right order so that the pawn's
position is same for all clients regardless of individual connection speeds
-tetherNetboost is used because vectors get compressed across network and so the end result is that the server needs to run with a higher velocity value, or else the compressed vector needs to be reexpanded later.
~~~
Why Running Player Movement Changes on Server?
The player can use WASD to affect the tether movements so instead of simulated I need to have the server update the pawn position on all client machines.
Additionally, the way unreal engine handles pawn movement can be quite intricate, to get an idea of it look at:
//playercontroller.uc
Code:
unreliable server function ServerMove(float TimeStamp, vector InAccel, vector ClientLoc, byte MoveFlags, byte ClientRoll, int View) function ServerMoveHandleClientError(float TimeStamp, vector Accel, vector ClientLoc) SendClientAdjustment(); unreliable client function LongClientAdjustPosition ( float TimeStamp, name newState, EPhysics newPhysics, float NewLocX, float NewLocY, float NewLocZ, float NewVelX, float NewVelY, float NewVelZ, Actor NewBase, float NewFloorX, float NewFloorY, float NewFloorZ )
It is not efficient to run a lot of code on the server however, so please note that all the tether special effects you see in video are running clientside, in the above code are the only server funcs, which are server funcs because it would be very hard to predict player input regarding the tether system.
~~~
Good Network Coding Policy
Run As Much Client-side As You Can
It is very good practice to run as much code as you can clientside !
The reason that the tether visual effects replicate so nicely in the video is because all tether effects, even for other players, are actuall run client side.
~~~
Tether Effect Overview
Basically I only replicate a single state change, determining whether or not the player is tethering or not using bool istethering.
Because this variable is repnotified, it will be updated for all players' machines, in addition to the player who is doing the tethering.
Because the actual visual game mechanic of tethering is simple, just drawing a beam from the player to the tether location, I can run the entire effect client side because the pawn's position is getting updated properly on the server via the code above.
This means that the pawn's position for all player machines is already up to date, and I can just draw the effect clientside!
I did not include all the tether effect code because it would complicate my focus for this tutorial
~~~
Summary
Using the code above as a guide, as well as referring to my earlier tether tutorial, you can see exactly how I created a custom pawn movement game mechanic that is able to work correctly in multiplayer !

Rama
Comment