Showing posts with label Gameplay Programming. Show all posts
Showing posts with label Gameplay Programming. Show all posts

Friday, March 31, 2017

Programming Weapon Sway

Weapon sway in games can easily be taken for granted by players. However, when it's not implemented the game looks plain and undone with a stationary weapon in the first person view. So that begs the question, how do first person shooters implement that cool weapon sway?! The truth is it's quite simple and this post will provide a brief code snippet on how to do it. Keep in mind that there are 1000 ways to skin a cat and the technique I'm presenting is one of those ways..but it is fairly popular.

Let's talk about Lissajous curves. There are plenty of websites that go into great detail about all the history, equations, and cool stuff you can do with Lissajous curves. I'll explain it simply and in terms of weapon sway. Think in your mind of your favorite FPS. As you walk the weapon typically sways horizontally and vertically in nice harmonic pattern. This complex motion in the x and y dimension is a Lissajous pattern.

Now, to program sway via Lissajous curves you can simply combine sin and/or cosine waves. There are different forms of the equations that use sin and/or cosine waves but for our example we will use 2 sin waves. Basically the goal is to oscillate vertically and horizontally harmoniously. From there you can customize your waves to get the effect you want.

This code will get you that traditional figure eight sway (this is a Unity C# snippet). Enjoy!

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SimpleWeaponSway : MonoBehaviour 
{

    [SerializeField]
    Transform weapon;

    [Range(01f)]
    [SerializeField]
    float verticalSwayAmount = 0.5f;

    [Range(01f)]
    [SerializeField]
    float horiztonalSwayAmount = 1f;

    [Range(015f)]
    [SerializeField]
    float swaySpeed = 4f;

    // Update is called once per frame
    void Update () 
    {
        float x = 0, y = 0;
        y += verticalSwayAmount * Mathf.Sin((swaySpeed * 2) * Time.time);
        x += horiztonalSwayAmount * Mathf.Sin(swaySpeed * Time.time);        
        weapon.position = new Vector3(xyweapon.position.z);
    }
}