Léna Piquet
June 23, 2011
Today we gonna discuss about the walljump function that I used in my project.
First, I’m not the original creator of this code, I found it on the official UDK forum, here : http://forums.epicgames.com/showthread.php?t=751172 and I have changed it a little after. Currently my walljump code cannot be used more than 3 times. After 3 times, the player must land (touch) the ground for reset the limit.
The 3 times limit is handled by the original function CheckJumpOrDuck already created in the PlayerController class. In my player controller I have simply changed it :
function CheckJumpOrDuck()
{
if ( Pawn == None )
{
return;
}
if ( bDoubleJump && (bUpdating || ((EXILAcrobaticPawn(Pawn) != None) && UTPawn(Pawn).CanDoubleJump())) )
{
//UTPawn(Pawn).DoDoubleJump( bUpdating );
if (maxJumpCount <= maxJumpLimitCurrent /*&& pIsInJumpVolume*/)
{
EXILAcrobaticPawn(Pawn).DoWallJump( bUpdating );
maxJumpCount++;
}
}
else if ( bPressedJump )
{
if (Pawn.Physics == PHYS_Falling)
{
if (maxJumpCount <= maxJumpLimitCurrent /*&& pIsInJumpVolume*/)
{
EXILAcrobaticPawn(Pawn).DoWallJump( bUpdating );
maxJumpCount++;
}
}
else
{
maxJumpCount = 0;
EXILAcrobaticPawn(Pawn).AirControlReset();
Pawn.DoJump( bUpdating );
}
}
if ( Pawn.Physics != PHYS_Falling && Pawn.bCanCrouch )
{
// crouch if pressing duck
Pawn.ShouldCrouch(bDuck != 0);
}
}
As you can see, I don’t perform the classic doubleJump from the default class with the UDK, instead I call my walljump function. The maxJumpCount variable is used to store the number of walljumped already performed. When this variable reach 3, the player can’t jump anymore. I reset to 0 this variable when the player is not in Air (phys_falling).
Located in the pawn (for an easier access to pawn’s variables, but you can put the walljump function into the playercontroller class), the code looks like this :
function bool DoWallJump( bool bUpdating )
{
local Vector HitLocation, HitNormal, End, Start;
local Actor HitActor;
//Perform trace
Start = Location + (Vector(Rotation) * GetCollisionRadius()/2);
End = Start + (vector(Rotation) * GetCollisionRadius() * 2.5);
HitActor = Trace(HitLocation, HitNormal, End, Start, true,);
`Log("Player try to jump on " @ HitActor);
//check on what we want to jump, we jump only on world surfaces
if (HitActor == WorldInfo || HitActor.isA('StaticMeshActor'))
{
`Log("-Player jump on the wall !");
self.FaceRotation(rotator(HitNormal), GlobalDeltatime);
Controller.SetRotation( rotator(HitNormal) );
if( HitNormal.Y != 0)
HitNormal.Y *= WallJumpBoostXY;
else if(HitNormal.X != 0)
HitNormal.X *= WallJumpBoostXY;
Velocity = HitNormal;
//PlayerController(Controller).PlaySound(playerSoundWallJump, false, true);
Velocity.Z = JumpZ + WallJumpBoostZ;
return true;
}
return false;
}
The operation is very simple, first we do a trace to be sure that the pawn is in front of a wall. With this trace we get the normal of the wall that we use to do the jump.
The "if" is used to be sure that we jump on a wall (worldinfo = bsp surface) or on a static mesh. Then in my case I change the rotation of the pawn and the camera with the normal vector and after I do the jump with updating the velocity of the pawn. My variable WallJumpBoostXY is just a number that I can change in the defaultproperties.
With this code we only jump perpendicularly of the wall (like I want for my game) but if you want to jump with the same angle as you were going to the wall, you must do this :
if (HitNormal.X != 0)
{
Velocity.X = HitNormal.X * WallJumpBoostXY;
}
if (HitNormal.Y != 0)
{
Velocity.Y = HitNormal.Y * WallJumpBoostXY;
}
Et voilà !