Weapon sway[Solved]

Is there an algorithm to add weapon sway like in most fps games like for example csgo? I been lookin
everywhere can’t find in unreal. I was mainly trying to implement this in shooter game sample. Thanks in advance.


  1. Attach the weapon to the player.
  2. Delay it’s movement by 0.5 seconds.

I’m not sure how you would go about doing that, but that is the logic behind it. You could probably make it in a blueprint.

I’ve done this countless times in Unity3D, it shouldn’t be too hard to do in Unreal!

Good luck man.

Hey I tried this with the camera spring arm and added lag. It just didnt seem right tho. Like when flicking fast the gun went flying. Could you show me an example of what you meant?

What we do is we have the weapon attached to the character’s model and then the weapon sway is part of the idle animation on the model.

By weapon sway I meant the weapon movement when aiming not the weapon bob like when standing or aiming. Do you have that in your project?

Most of the good-looking implementations are a bit more complex than you’d expect. For example, you can have a look at how it’s done in Unreal Tournament: link text

Just a note - if you want the weapon to lead instead of lag, this implementation works when you set the MaxYawLag or MaxPitchLag to negative values as well.

P.S. I forgot that I’ve posted the full source code including my small additions a while back on the forums: Weapon Rotation Leading. This is probably easier to use as a reference.

ah sorry I was confused. I’d look at staticvoidlol’s answer then.

This seems like what I need. Do you have a video of what it looks like? Thanks a lot for the help!

One more thing - I’ve found that in addition to rotation lag/leading, it helps a lot if you also do some relative location offsets based on the lag/lead value at the same time. i.e. my current UpdateWeaponLoc function is as follows:

void APWNWeapon::UpdateLocRot(FVector newLoc, FRotator newRot, float deltaTime)
	FRotator finalRot = newRot;

	// Rotation Leading/Lag
	float lagDiff;	
	finalRot.Pitch = LagWeaponRotation(newRot.Pitch, LastRotation.Pitch, deltaTime, MaxPitchLag, 1, lagDiff);
	finalRot.Yaw = LagWeaponRotation(newRot.Yaw, LastRotation.Yaw, deltaTime, MaxYawLag, 0, lagDiff);
	finalRot.Roll = newRot.Roll;

	// Location offset
	float locDiff = lagDiff / MaxYawLag;
	locDiff *= MaxLocLagX;

	//UPWNGameGlobals::Log(TEXT("YAW"), lagDiff, true);
	ArmMesh->SetRelativeLocation(FVector(ArmMeshOffset.X, ArmMeshOffset.Y + locDiff, ArmMeshOffset.Z), false);

	// Set our loc	
	LastRotation = newRot;

Sure, I’ve uploaded a video here. I’ve increased the params slightly for illustrative purposes.

Thanks a lot that helped so much!

Just wanted to clarify so u put this function in the weapon class or in the pawn class to update the arms cuz im using the shooter game sample and wasnt sure how to implement it in there…
Actually nvm i figured it out

I’m happy you figured it out, but for others with this question, in my opinion this should go into your weapon class for proper separation of concerns.

The “UpdateLocRot” function as posted here assumes that the Character calls this function on the Weapon, passing it the Location and Rotation of the player’s camera. The rotation lag/leading function then takes the new given rotation and adds the calculated lag/lead to it. For the location lead/lag, I use the amount of lead/lag and adjust the weapon’s relative location.

Hey, I know this is an old post, but I have been stuck on this issue recently. The Unreal Tournament example doesn’t seem to work properly as the mesh never returns to the pawn’s control rotation. I was hoping to look at the forum post you posted since it seemed to be helpful, however, it tells me its either deleted or private. By any chance do you still have the logic?


@Forsicen: I had the same issue with the UT code, check the last two posts: https://forums.unrealengine.com/t/porting-weapon-rotation-leading-from-udk-ue3/9812/4

Hey thanks for this! For some reason the first link didn’t work. But this is great logic and it works perfectly.