Dear Community,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For Physics Tether for Skeletal Mesh Pawns See This New Tutorial + Video
Tether / Grapple Hook for Skeletal Mesh Pawns
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In this tutorial I give you the simple and complete code for making a grappling hook / tether that is:
1. fully physics functional with Kactors
2. can be dynamically resized during game time, longer or shorter, and will pull up the attached object or lower it further down
3. doesnt require a weapon, but you could adapt this code for a weapon
I explain a lot of the properties of RB_Constraints in this tutorial so you can get your own setup going that does what you want
You do not need any extra art assests for this tutorial, just
~~~
The Basics, RB Constraint
Review the properties here please, and then you will be able to recognize all the properties in my RB Constraint class:
http://udn.epicgames.com/Three/Physi...Reference.html
~~~
Pawns?
To use my code with a pawn, you must change the phyicss of the pawn to PHYS_RigidBody and then change it back again when you are done with the tether.
~~~
My RB Constraint Class
This class is focused on making the grappling hook / tether effect, where linear motion is constrained to within a certain distance of the point of attachment of the grappling hook in all dimensions.
I restrict the swing as well, but that is not that important, the most important code is the restriction of the linear movement
Here is my entire class that you see in this video for your own use:
there are two main parts to this class
The RB_instance
You need to set up the instance via defaultproperties and your own class because all the value are const.
The need for the instance is not as great as for the constraintsetup, it is only to create some friction so that the object attached to the tether does not swing freely forever.
The exact values I am using in this class are tailored to my Kactor ball that I am using, you might need to adjust the values dramatically.
Notice how the velocity drive is turned on in all dimensions, so that means friction will be created in all directions.
The target velocity is 0, or no motion, and the allowed force is the amount of friction to generate while the object is swinging on the tether.
You could also use the velocity drive to GENERATE motion, by not having a target velocity of 0.
More info on RB_Instance here
The ConstraintSetup
This is the really important part.
There are three types of motion that can be constrained, or limited, to produce a variety of connections between physics objects.
By knowing what they do you can create your own unique behaviors / joints / hinges etc!
Linear motion in X Y and Z = forces/constrains the attached object to stay within a certain distance of the spawn location of the RB constraint. You can remove axis of movement completely by setting the LimitSize to 0.
From the player pawn/obj class:
You don't see me setting these values in the RB Constraint class because the length of the tether is variable.
Swing A direction of rotation of the object. If only swing is allowed the object cannot move from its fixed position, but it can rotate freely.
Twist Another direction of rotation.
So an object that has Swing and Twist allowed, and all the linear movement locked to 0 is a ball-socket joint, which is the default setup for a new instance of the RB_ConstraintSetup class.
An object that has linear movement in 1 or all axis but no swing or twist allowed, can physically move but not rotate.
And if you choose to have some limits on movement and some limits on rotation, well that is how you can make a whole variety of different joints and fun physics connections!
Allowing the Tether to be Stretched Beyond Normal Limits
The stiffness variable is the spring action, meaning once the object goes beyond the allowed limitsize for the linear motion, the tether will stretch and the try to pull the object back into the proper range, like a spring.
Lower stiffness levels mean the object can go further away from the normal Limitsize with less resistance.
The Dampening variable controls how forcefully the spring pulls the object back into the proper range. I wanted to make the pull back quite obvious so I left this at 0.
Restricting Rotation
Notice I choose to limit the swing because otherwise the ball looks like it is just spinning frictionless in the air and doesnt seem like it is attached to anything.
~~~
The Code To Create / Destroy Tether
This is the entire code to make the beam and the RB Constraint, you don't need a weapon class.
You can test this without a weapon class if you setup some keys to activate/deactiave your tether.
You can do this in udkgame/Config/DefaultInput.ini
I am using a Kactor as my player object, but if you are using a Pawn, just remember to use
for the duration of time you want the pawn to swing around like my Kactor does in the video.
In your Pawn/Player Object Class
In my default properties tetherMaxLength was set to 1200
Things to note:
Notice that the spawn location for the emitter is 64 unreal units directly above the player pawn/ kactor, that was for my code, but if you want to use a weapon you can attach this beam to a weapon socket.
Notice that Self is used as the Actor that this emitter is attached to (the last parameter).
This is why the beam stays with my kactor ball at all times wherever it goes.
You must make sure “use local space” is checked in the Required module of your beam effect for this to work
For the linkgun beam, this is the way to set the end point, since a vector parameter has been set up. You can make your own beam effect and parameter and use your own name of course. Or if you dont have any parameters you could try SetBeamEndPoint.
~~~
How to Make the Tether Shrink and Grow
Here's the rest of the core code you need to do exactly what I do in the video!
Things to note:
If you dont call this then the changes to the constraintsetup will not have any affect on the current isntance of the tether.
I am so glad it was this easy!
Notice I am not destroy and remaking the RB constraint instance, I am just re-initializing the current one.
This is why we had to store the wall that the beam hit as a global variable.
The most important lines for retractable tether/ grappling hook
Notice that if the player pawn / kactor is NOT within range of the proposed new and smaller size of the tether, then
the RB Constraint is NOT changed to be smaller!
If that return was not there, then the ball/pawn could be locked outside of the limitSize of the joint, and that would not be good. It would cause the ball to be stuck in space basically.
So as you implement this code for your own project, keep this in mind!
You can ONLY make the limitsize smaller if you know the player object is going to still be within range.
There is no such issue with making the tether longer as you can see in above code.
Lower the value 1200 for the addImpulse if your Player pawn goes flying about using this code, or increase it if you are not getting enough lift off
~~~
Player Controller Class
In my player controller class I have something like this in my PlayerTick
So the value of adding or subtracting 40 is based on the fact that I am using playertick. If you are going to use a timer or something else you will need to adjust how quickly the tether size is changed. If you are not getting the results you want, verify how frequently decrease/increaseTether() is being called with `log.
~~~
How to Make the Link Beam Less Curvy Near The Weapon Socket / Kactor Ball
Make a copy of the link beam asset, and right click to get the entire path to copy into your code, and then, in Cascade:
Source+, its the same for every beam in the whole emitter
Beam Strength
Look for the value of 1250, this is what makes the beam curve so much near its source point.
I used 250 to have a much less pronounced curve which looked odd when tether was short.
You could also try doing this via code:
SetBeamSourceStrength
~~~
It's That Simple
That's all the code you need right there!
Once you have this up and running you can easily experiment with modifying the RB ConstraintSetup values to make your own kind of joint / unique phyiscs experience!
Enjoy!
♥
Rama
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For Physics Tether for Skeletal Mesh Pawns See This New Tutorial + Video
Tether / Grapple Hook for Skeletal Mesh Pawns
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In this tutorial I give you the simple and complete code for making a grappling hook / tether that is:
1. fully physics functional with Kactors
2. can be dynamically resized during game time, longer or shorter, and will pull up the attached object or lower it further down
3. doesnt require a weapon, but you could adapt this code for a weapon
I explain a lot of the properties of RB_Constraints in this tutorial so you can get your own setup going that does what you want

You do not need any extra art assests for this tutorial, just
Code:
ParticleSystem'WP_LinkGun.Effects.P_WP_Linkgun_Altbeam'
The Basics, RB Constraint
Review the properties here please, and then you will be able to recognize all the properties in my RB Constraint class:
http://udn.epicgames.com/Three/Physi...Reference.html
~~~
Pawns?
To use my code with a pawn, you must change the phyicss of the pawn to PHYS_RigidBody and then change it back again when you are done with the tether.
Code:
//while tether is active on pawn: pawn.setphysics(PHYS_RigidBody);
My RB Constraint Class
This class is focused on making the grappling hook / tether effect, where linear motion is constrained to within a certain distance of the point of attachment of the grappling hook in all dimensions.
I restrict the swing as well, but that is not that important, the most important code is the restriction of the linear movement
Here is my entire class that you see in this video for your own use:
Code:
class joyRBCWithFriction extends RB_ConstraintActorSpawnable notplaceable; defaultproperties { bNoDelete=false //~~~ Constraint Instance ~~~ Begin Object Class=RB_ConstraintInstance Name=MyConstraintInstance //enable friction bLinearXVelocityDrive = true bLinearYVelocityDrive = true bLinearZVelocityDrive = true //target velocity is 0 LinearVelocityTarget = (X=0,Y=0,Z=0); //force to apply to reach velocity of 0 //the amount of friction basically LinearDriveForceLimit = 3 End Object ConstraintInstance=MyConstraintInstance Begin Object Class=RB_ConstraintSetup Name=MyConstraintSetup //the tether can be stretched //beyond normal limits //damping is how much to reduce //spring-back after stretching bLinearLimitSoft = true LinearLimitStiffness = 90 LinearLimitDamping = 0 //limit the rotation of the object bSwingLimited = true Swing1LimitAngle = 120 Swing2LimitAngle = 120 /* //soft limit on rotation bSwingLimitSoft = false; SwingLimitStiffness = 10; SwingLimitDamping = 10; */ //~~~ Twist //bTwistLimited = true; //TwistLimitAngle = 60; /* //soft twist limit bTwistLimitSoft = false; TwistLimitStiffness = 10; TwistLimitDamping = 10; */ End Object ConstraintSetup=MyConstraintSetup }
The RB_instance
You need to set up the instance via defaultproperties and your own class because all the value are const.
The need for the instance is not as great as for the constraintsetup, it is only to create some friction so that the object attached to the tether does not swing freely forever.
The exact values I am using in this class are tailored to my Kactor ball that I am using, you might need to adjust the values dramatically.
Notice how the velocity drive is turned on in all dimensions, so that means friction will be created in all directions.
The target velocity is 0, or no motion, and the allowed force is the amount of friction to generate while the object is swinging on the tether.
You could also use the velocity drive to GENERATE motion, by not having a target velocity of 0.
More info on RB_Instance here
The ConstraintSetup
This is the really important part.
There are three types of motion that can be constrained, or limited, to produce a variety of connections between physics objects.
By knowing what they do you can create your own unique behaviors / joints / hinges etc!
Linear motion in X Y and Z = forces/constrains the attached object to stay within a certain distance of the spawn location of the RB constraint. You can remove axis of movement completely by setting the LimitSize to 0.
From the player pawn/obj class:
Code:
curTether.ConstraintSetup.LinearYSetup.LimitSize = tetherlength; curTether.ConstraintSetup.LinearZSetup.LimitSize = tetherlength; curTether.ConstraintSetup.LinearXSetup.LimitSize = tetherlength;
Swing A direction of rotation of the object. If only swing is allowed the object cannot move from its fixed position, but it can rotate freely.
Twist Another direction of rotation.
So an object that has Swing and Twist allowed, and all the linear movement locked to 0 is a ball-socket joint, which is the default setup for a new instance of the RB_ConstraintSetup class.
An object that has linear movement in 1 or all axis but no swing or twist allowed, can physically move but not rotate.
And if you choose to have some limits on movement and some limits on rotation, well that is how you can make a whole variety of different joints and fun physics connections!
Allowing the Tether to be Stretched Beyond Normal Limits
Code:
bLinearLimitSoft = true LinearLimitStiffness = 90 LinearLimitDamping = 0
Lower stiffness levels mean the object can go further away from the normal Limitsize with less resistance.
The Dampening variable controls how forcefully the spring pulls the object back into the proper range. I wanted to make the pull back quite obvious so I left this at 0.
Restricting Rotation
Code:
bSwingLimited = true Swing1LimitAngle = 120 Swing2LimitAngle = 120
~~~
The Code To Create / Destroy Tether
This is the entire code to make the beam and the RB Constraint, you don't need a weapon class.
You can test this without a weapon class if you setup some keys to activate/deactiave your tether.
You can do this in udkgame/Config/DefaultInput.ini
I am using a Kactor as my player object, but if you are using a Pawn, just remember to use
Code:
SetPhysics(PHYS_RigidBody)
In your Pawn/Player Object Class
Code:
//global class vars, put with other class vars var actor curTargetWall; var vector wallHitLoc; var joyRBCWithFriction curTether; var ParticleSystemComponent tetherBeam; function detachTether() { if (curTether != none) { //RB curTether.termConstraint(); curTether.destroy(); curTether = none; curTargetWall = none; //beam tetherBeam.SetHidden(true); tetherBeam.DeactivateSystem(); tetherBeam = none; } } function createTether() { local vector hitLoc; local vector hitNormal; local actor wall; local vector startTraceLoc; local float tetherlength; //~~~ Trace ~~~ //pawn location + 100 in direction of player camera startTraceLoc = Location + Vector(PlayerController.Rotation) * 100; //trace only to tether's max length wall = Self.trace(hitLoc, hitNormal, startTraceLoc + tetherMaxLength * Vector(PlayerController.Rotation) , startTraceLoc); //replace this line with your own choice //of what actors can be attached to //if (!Wall.isa('Victorywall')) return; //attach to anything if (!Wall.isa('Actor')) return; //Clear any old tether and beam detachTether(); //store global vars for //tether resizing functions curTargetWall = Wall; wallHitLoc = hitLoc; //get length of tether from starting //position of object and wall tetherlength = vsize(hitLoc - Location); //~~~ RB Tether ~~~ //must spawn RB constraint near where you want movement to be limited //in this case, where the tether hits the target object (HitLoc) curTether = Spawn(class'joyRBCWithFriction', , , HitLoc, rot(0, 0, 0)); //variable length tether curTether.ConstraintSetup.LinearYSetup.LimitSize = tetherlength; curTether.ConstraintSetup.LinearZSetup.LimitSize = tetherlength; curTether.ConstraintSetup.LinearXSetup.LimitSize = tetherlength; //~~~ Initialize RB Constraint ~~~ //Self = the player pawn / kactor / object //which is the class this code belongs in //if not using weapon curTether.InitConstraint( Self, wall ); //~~~ beam ~~~ tetherBeam = WorldInfo.MyEmitterPool.SpawnEmitter( ParticleSystem'WP_LinkGun.Effects.P_WP_Linkgun_Altbeam', Location + Vect(0,0,1) * 64, rotator(HitNormal), Self); //make sure beam is active tetherBeam.SetHidden(false); tetherBeam.ActivateSystem(true); //beam end point, this is very important tetherBeam.SetVectorParameter('LinkBeamEnd', hitLoc ); }
Things to note:
Code:
tetherBeam = WorldInfo.MyEmitterPool.SpawnEmitter(
ParticleSystem'WP_LinkGun.Effects.P_WP_Linkgun_Altbeam',
Location + Vect(0,0,1) * 64, rotator(HitNormal), Self);
Notice that Self is used as the Actor that this emitter is attached to (the last parameter).
This is why the beam stays with my kactor ball at all times wherever it goes.
You must make sure “use local space” is checked in the Required module of your beam effect for this to work
Code:
//beam end point, this is very important
tetherBeam.SetVectorParameter('LinkBeamEnd', hitLoc );
~~~
How to Make the Tether Shrink and Grow
Here's the rest of the core code you need to do exactly what I do in the video!
Code:
function increaseTether() { //increase tether length if (curTether == none) return; if (curTether.ConstraintSetup.LinearYSetup.LimitSize >= tetherMaxLength) return; curTether.ConstraintSetup.LinearYSetup.LimitSize += 40; curTether.ConstraintSetup.LinearZSetup.LimitSize += 40; curTether.ConstraintSetup.LinearXSetup.LimitSize += 40; //re-initialize curTether.InitConstraint( Self, curTargetwall ); } function decreaseTether() { //decrease tether length if (curTether == none) return; if (curTether.ConstraintSetup.LinearYSetup.LimitSize <= 10 ) return; if (vsize(wallHitLoc - Location) > curTether.ConstraintSetup.LinearYSetup.LimitSize - 42 ) { //move ball to within range Self.StaticMeshComponent.AddImpulse( 1200 * Vector (Rotator(wallHitLoc - Location )) ); return; //<----- do not proceed past until above //condition is met } curTether.ConstraintSetup.LinearYSetup.LimitSize -= 40; curTether.ConstraintSetup.LinearZSetup.LimitSize -= 40; curTether.ConstraintSetup.LinearXSetup.LimitSize -= 40; //re-initialize curTether.InitConstraint( Self, curTargetwall ); }
Code:
//re-initialize
curTether.InitConstraint( Self, curTargetwall );
I am so glad it was this easy!
Notice I am not destroy and remaking the RB constraint instance, I am just re-initializing the current one.
This is why we had to store the wall that the beam hit as a global variable.
The most important lines for retractable tether/ grappling hook
Code:
if (vsize(wallHitLoc - Location) > curTether.ConstraintSetup.LinearYSetup.LimitSize - 42 ) { //move ball to within range Self.StaticMeshComponent.AddImpulse( 1200 * Vector (Rotator(wallHitLoc - Location )) ); return; //<----- do not proceed past until above //condition is met }
the RB Constraint is NOT changed to be smaller!
If that return was not there, then the ball/pawn could be locked outside of the limitSize of the joint, and that would not be good. It would cause the ball to be stuck in space basically.
So as you implement this code for your own project, keep this in mind!
You can ONLY make the limitsize smaller if you know the player object is going to still be within range.
There is no such issue with making the tether longer as you can see in above code.
Lower the value 1200 for the addImpulse if your Player pawn goes flying about using this code, or increase it if you are not getting enough lift off
~~~
Player Controller Class
In my player controller class I have something like this in my PlayerTick
Code:
if(keyisdownT){ pawn/Kactor.decreaseTether(); } else if(keyisdownG){ pawn/Kactor.increaseTether(); }
~~~
How to Make the Link Beam Less Curvy Near The Weapon Socket / Kactor Ball
Make a copy of the link beam asset, and right click to get the entire path to copy into your code, and then, in Cascade:
Source+, its the same for every beam in the whole emitter
Beam Strength
Look for the value of 1250, this is what makes the beam curve so much near its source point.
I used 250 to have a much less pronounced curve which looked odd when tether was short.
You could also try doing this via code:
SetBeamSourceStrength
~~~
It's That Simple
That's all the code you need right there!
Once you have this up and running you can easily experiment with modifying the RB ConstraintSetup values to make your own kind of joint / unique phyiscs experience!
Enjoy!
♥
Rama
Comment