# Game Development

# Unity

# Project Settings

At first when opening the Unity editor I was a bit overwhelmed by the many options available, and it can be hard to get going without at least knowing how to configure the most basic of settings for a Unity project. In the sections below, I'll cover some simple settings that are worthwhile to consider when creating a new project in Unity.


### Playmode Tint

This option is not found in `Project Settings`, but I think it is something everyone entering into Unity for the first time should consider. Navigate to the menu bar at the top of your editor and select `Edit->Preferences->Colors` and adjust the `Playmode Tint` to something very noticable. This will avoid forgetting you are in play mode and making some changes, only to be forced to revert them all once exiting play mode.

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591544219505.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591544219505.png)

For the rest of these sections, we will be working in the `Project Settings` panel opened with `Edit->Project Settings...` in the menu bar of the Unity editor.

[Official Unity Project Settings Documentation](https://docs.unity3d.com/Manual/comp-ManagerGroup.html)

### Project Name

It is not to be assumed that Unity will distribute builds of your game with your local Unity project name as you defined it when creating your project initially. In fact, Unity requires us to specify these details within the `Player` section of `Project Settings`. See the section below is adjusted to suit the needs of your project.

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591541753961.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591541753961.png)

### Game / Application Icons

It's important to change things like this from the default settings, otherwise even a finished project can end up looking incomplete. Navigate to the `Player` section and scroll down to adjust icon settings. It's important to be consistent across all platforms, and this can easily be done by checking the `Override for PC, Max & Linux Standalone` tick box at the top of the panel. This will apply your Icon settings on all platforms.

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591540882097.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591540882097.png)


### Splash Screen

*This is for Unity Professional Licenses only*

Within the `Player` panel we can find the below settings for modifying the splash screen of a game or application created with Unity.

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591541034571.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591541034571.png)

### Quality Settings

It's important to adjust quality settings to suit your development environment so you aren't running your game within the Unity editor in max settings.

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591541213761.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591541213761.png)

You can rename quality levels, add new, and adjust platform-specific modes as well. It's important to note that clicking the name of the quality setting in this table (just left of the check-marks) will apply the settings within your editor for testing. The `Default` drop-down arrors correspond with each platform at the top level of the table. 



### Graphics Settings

This is where you'll define the preconfigured graphics settings available to the player. Its important to adjust these to suit the platform the build will be running on. As an example, this feature could be useful when trying to distribute a test build of a Unity game with WebGL. We could reduce the settings to improve performance within the browser to make the game much less demanding. This allows us to build more efficiently to WebGL and not create an unecessarily demanding or slow performing game given this basic platform of WebGL.

Curious what WebGL is or looks like in use? I host some archived examples on my website, [click here](https://shaunreed.com/2017/02/26/webgl/) to check out some Unity WebGL games that I've already built and hosted online for playing. 

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591542267619.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591542267619.png)


### Input Manager

This section is very useful in configuring controls for your game that can then be used for scripting. For example, the section below I have defined a button for `Fire`, which is triggered when the player clicks the left mouse button

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591542336677.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591542336677.png)


By using a custom script that defines global constants, we can reduce the task of changing these values later on. Below, I'll cover an example of using the `Input Manager` paired with a few C# scripts to define controls in global variables which can be easily modified in a central location. This avoids a scenario where we have built a complex game and want to change controls later in development, requiring us to change static values across numerous scripts. This is not only tedious but also makes the project more prone to errors.

```csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Controls : MonoBehaviour
{
    // Constants used within the game to handle passing control settings to builtin unity functions with string parameters
    // Unity parses these strings against settings in Edit->ProjectSettings->InputSettings

    // Character walking controls for joystick / keyboard
    // Keyboard has boolean movement, joystick has variable 0.0f - 1.0f
    public const string c_MoveStrafe = "Horizontal";
    public const string c_MoveWalk = "Vertical";

    // Character look controls for mouse / joystick
    public const string c_LookMouseVertical = "Mouse Y";
    public const string c_LookMouseHorizontal = "Mouse X";
    public const string c_LookGamePadVertical = "Look Y";
    public const string c_LookGamePadHorizontal = "Look X";

    // Character movement modifiers
    public const string c_ModJump                    = "Jump";
    public const string c_ModSprint                  = "Sprint";
    public const string c_ModCrouch                  = "Crouch";
    
    // Character weapon controls
    public const string c_PrimaryAim                     = "Aim";
    public const string c_PrimaryGamepadAim              = "Gamepad Aim";
    public const string c_PrimaryFire                    = "Fire";
    public const string c_PrimaryGamepadFire             = "Gamepad Fire";
    public const string c_PrimarySwitchWeapon            = "Mouse ScrollWheel";
    public const string c_PrimaryGamepadSwitchWeapon     = "Gamepad Switch";
    public const string c_PrimaryHide              = "Primary Hide";
    public const string c_PrimaryNextWeapon              = "NextWeapon";
    
    // UI controls
    public const string c_UIPauseMenu               = "Pause Menu";
    public const string c_UISubmit                  = "Submit";
    public const string c_UICancel                  = "Cancel";
}
```

These constants can then be used in a relative `PlayerInput` class, which can handle recieving input from the player at a higher level so we won't need to refactor all of our scripts in the scenario that we want to modify our controls.

```csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// A script to pass player input to a relative GameObject's Controller script

public class PlayerInput : MonoBehaviour
{

    PlayerController playerController;

    // Start is called before the first frame update
    void Start()
    {
        playerController = GetComponent<PlayerController>();
        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;
    }

    // Update is called once per frame
    void Update()
    {
        // Always check if the player wants to unbind their cursor lock state
        UpdateLockState();
    }

    public bool CanProcessInput()
    {
        // If the cursor is locked within the game, return true
        return Cursor.lockState == CursorLockMode.Locked;
    }

    public Vector3 GetMovement() 
    {
        // If the cursor is not locked within the game, do nothing
        if (!CanProcessInput()) return Vector3.zero;
        
        // Create a file / class (Controls.cs) to hold strings which can be passed to functions in all scripts
        // Allows for easy control customization without reefactoring a lot of code
        // GetAxis returns 0.0f-1.0f strength of movement (allows joystick variable movement, keyboard movement is 1.0f if key pressed)
        // Horizontal = a,d     Vertical = w,s
        Vector3 move;
        switch(playerController.targetPov)
        {
            case Kamera.pov.Mounted:
            move = transform.forward * Input.GetAxis(Controls.c_MoveStrafe) * -1.0f  + transform.right * Input.GetAxis(Controls.c_MoveWalk) * 1.0f ;
            break;

            default:
            move = transform.right * Input.GetAxis(Controls.c_MoveStrafe) + transform.forward * Input.GetAxis(Controls.c_MoveWalk);
            break;
        }
        // Return the clamped amnount of movement to apply to a GameObject within some relative Controller script
        return move;
    }

    public float GetLookHorizontal()
    {
        return GetLookAxis(Controls.c_LookMouseHorizontal, Controls.c_LookGamePadHorizontal);
    }

    public float GetLookVertical()
    {
        return GetLookAxis(Controls.c_LookMouseVertical, Controls.c_LookGamePadVertical);
    }

    // If the player presses the UICancel key, the cursor is unlocked.
    void UpdateLockState()
    {
        if (Input.GetButton(Controls.c_UICancel)) Cursor.lockState = CursorLockMode.None;
        else if (Input.GetMouseButton(0)) Cursor.lockState = CursorLockMode.Locked;
    }

    // Checks whether the look input is via mouse or gamepad and returns a float 0.0f-1.0f of the strength 
    float GetLookAxis(string mouseLook, string stickLook)
    {
        if (CanProcessInput())
        {
            
            // Check if there is any input from a gamepad controller on the given axis
            bool isGamePad = Input.GetAxis(stickLook) != 0.0f;
            // If we are using a gamepad use stickLook's strength, otherwise use mouse input
            float str = isGamePad ? Input.GetAxis(stickLook) : Input.GetAxis(mouseLook);

            if (isGamePad)
            {
                // since mouse input is already deltaTime-dependant, only scale input with frame time if it's coming from sticks
                str *= Time.deltaTime;
            }
            else
            {
                // reduce mouse input amount to be equivalent to stick movement
                str *= 0.01f;
    #if UNITY_WEBGL
    // Mouse tends to be even more sensitive in WebGL due to mouse acceleration, so reduce it even more
                // str *= webglLookSensitivityMultiplier;
    #endif
            }

            return str;
        }
        else return 0.0f;

    }

    public bool GetCrouchDown()
    {
        return Input.GetButtonDown(Controls.c_ModCrouch);
    }
    public bool GetCrouchUp()
    {
        return Input.GetButtonUp(Controls.c_ModCrouch);
    }

    public bool GetSprintHeld()
    {
        return Input.GetButton(Controls.c_ModSprint);
    }

    public bool GetJumpPress()
    {
        return Input.GetButtonDown(Controls.c_ModJump);
    }

    public bool GetMouseFire()
    {
        return Input.GetButtonDown(Controls.c_PrimaryFire) || Input.GetButtonDown(Controls.c_PrimaryGamepadFire);
    }
    
    public bool GetMouseAlt()
    {
        return Input.GetButtonDown(Controls.c_PrimaryAim) || Input.GetButtonDown(Controls.c_PrimaryGamepadAim);
    }

    public bool GetLowerPrimary()
    {
        return Input.GetButtonDown(Controls.c_PrimaryHide);
    }


    public int GetNumberPress()
    {
        if(Input.GetKeyDown(KeyCode.Alpha0)) return 9;
        else if(Input.GetKeyDown(KeyCode.Alpha1)) return 0;
        else if(Input.GetKeyDown(KeyCode.Alpha2)) return 1;
        else if(Input.GetKeyDown(KeyCode.Alpha3)) return 2;
        else if(Input.GetKeyDown(KeyCode.Alpha4)) return 3;
        else if(Input.GetKeyDown(KeyCode.Alpha5)) return 4;
        else if(Input.GetKeyDown(KeyCode.Alpha6)) return 5;
        else if(Input.GetKeyDown(KeyCode.Alpha7)) return 6;
        else if(Input.GetKeyDown(KeyCode.Alpha8)) return 7;
        else if(Input.GetKeyDown(KeyCode.Alpha9)) return 8;
        else return -1;
    }

}
```

If you want to actually be able to apply damage, we need a `Target` script. See the simple example below for a script which enables this to occur. Later, within `WeaponControl.cs`, we will check if the object we hit has this script attached, and if it does we can deal damage to the set HP amount given to the `Target`


```csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Target : MonoBehaviour
{

    [SerializeField]
    private float health;

    [SerializeField]
    [Tooltip("If this is true we spawn the broken GameObject on destruction")]
    public bool isDestructable = false;

    [SerializeField]
    [Tooltip("The GameObject to spawn when this object is broken")]
    public GameObject broken;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    public void TakeDamage(float amount)
    {
        health -= amount;
        if (health <= 0)
        {
            if(isDestructable) Instantiate(broken, gameObject.transform, false);
            Destroy(gameObject);
        }
    }

}
```

We could then use this `PlayerInput.cs` script within a `WeaponControl.cs` script check if the player presses this button in `Update` called once per frame. If they have tried to shoot and have a weapon equipped, we can call the relative weapon's `ShootWeapon()` function. Note that you will have to attach the `playerInput` and `playerWeapons` variables to relative scripts within your editor.

```csharp
public class WeaponControl : MonoBehaviour
{
    [SerializeField]
    PlayerInput playerInput;
    [SerializeField]
    PlayerWeapons playerWeapons;
    [SerializeField]
    public Transform muzzle;
    [SerializeField]
    public GameObject projectile;
    [SerializeField]
    Camera mainCamera;
    [SerializeField]
    ParticleSystem muzzleFlash;
    [SerializeField]
    GameObject hitEffect;
    private float range = 500.0f;
    private float damage = 10.0f;


    void Update()
    {
        if (playerInput.GetMouseFire() && playerWeapons.hasWeapon) ShootWeapon();
    }

	    void ShootWeapon()
    {
        fireSFX.Play();
        GameObject projectileObj = Instantiate(projectile, muzzle.transform.position + mainCamera.transform.forward, mainCamera.transform.rotation);
        projectileObj.GetComponent<Rigidbody>().AddForce(transform.forward * 100);
            
        
        RaycastHit hit;
        if (Physics.Raycast(muzzle.transform.position, mainCamera.transform.forward, out hit, range))
        {
            Target temp = hit.transform.GetComponent<Target>();
            if (temp != null) temp.TakeDamage(damage);


            Debug.Log(hit.transform.name);
            muzzleFlash.Play();
            GameObject hitObject = Instantiate(hitEffect, hit.point, Quaternion.LookRotation(hit.normal));
            Destroy(hitObject, 1f);

            if (hit.rigidbody != null) hit.rigidbody.AddForce(-hit.normal * hitForce);

        }
    }

}
```

# Scripting

Scripting in Unity uses C# and is very well documented. In the sections below, I'll Provide examples and edge cases where possible, and link to the relative documentation for quick reference.

For a collection of classes and structs that are *required* for Unity to function, which means they will *always* be available to you when scripting in Unity, head over to [UnityEngine.CoreModule Documentation](https://docs.unity3d.com/ScriptReference/UnityEngine.CoreModule.html)


### Transform
This class controls and tracks object position, rotation, scale.

[Official Transform Class Documentation](https://docs.unity3d.com/ScriptReference/Transform.html)




#### Local Space

Local space is the transform relative to the object's parent. An example of this can be seen below where I have selected an object and the transform controls are centralized on the exact transform of that object relative to its local position.

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591551913335.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591551913335.png)

Take notice of three things in the above screenshot. First, we have selected `Local` position in the top-left near our transform controls. Clicking this button again will toggle between Local and World space. Second, take note of the World Space axis shown at the top-right of the scene view. Third, in contrast to the World space axis, notice the GameObject's axis shown in the scene view are different in orientation. The transform axis shown on the GameObject are modifying and referring to the GameObject's transform within Local space.

#### World Space

World space is the position of the GameObject rooted within the scene. An example of this is seen in selecting the exact same object in the editor and toggling world space transform view. This makes sure the transform controls are the same as the World Space axis, instead of referring directly to the transform of a local object.

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591552157841.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591552157841.png)

Again, take notice of three things in the above screenshot. First, we have selected `Global` position in the top-left near our transform controls. Clicking this button again will toggle between Local and World space. Second, take note of the World Space axis shown at the top-right of the scene view. Third, in contrast to the World space axis, notice the GameObject's axis shown in the scene view are different in orientation. The transform axis shown on the GameObject are modifying and referring to the GameObject's transform within World space.

### Vector3

[Official Vector3 Struct Documentation](https://docs.unity3d.com/ScriptReference/Vector3.html)

#### Axis

In Unity 3D you will use the `X`, `Y`, and `Z` axis frequently both in positioning within the editor and scripting. It helps to have a clear understanding of the names these axis can be referred to with, as it will greatly improve your ability to access and modify these values without over complicating things.

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591629600009.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591629600009.png)

The `X` axis can be accessed with the `right` keyword when accessing any class which stores axis information\
The `Y` axis can be accessed with the `Up` keyword when accessing any class which stores axis information\
The `Z` axis can be accessed with the `forward` keyword when accessing any class which stores axis information

Similarly, when modifying a `Vector`, we can easily flip these axis by accessing the opposite of these keywords -\
The `X` negative axis can be accessed with the `left` keyword when accessing any class which stores axis information\
The `Y` negative axis can be accessed with the `down` keyword when accessing any class which stores axis information\
The `Z` negative axis can be accessed with the `back` keyword when accessing any class which stores axis information

So, the `Vector3` equivalents to these would be \
`X` axis, `Vector3(1.0f, 0.0f, 0.0f)`, is equivalent to `right`\
`Y` axis, `Vector3(0.0f, 1.0f, 0.0f)`, is equivalent to `up`\
`Z` axis, `Vector3(0.0f, 0.0f, 1.0f)`, is equivalent to `forward`

`X` negative axis, `Vector3(-1.0f, 0.0f, 0.0f)`, is equivalent to `left`\
`Y` negative axis, `Vector3(0.0f, -1.0f, 0.0f)`,  is equivalent to `down`\
`Z` negative axis, `Vector3(0.0f, 0.0f, -1.0f)`, is equivalent to `back`


### Quaternion

[Official Quaternion Struct Documentation](https://docs.unity3d.com/ScriptReference/Quaternion.html)

###

# Shortcuts

Since Unity has many features and shortcuts available that will widen the gap between an experienced developer and a beginner, I'll list some of my most frequently used shortcuts and tricks here. Though these can all be viewed and modified by opening the panel below in `Edit->Shortcuts...`, there is a huge amount of shortcuts and this can be a lot to look at.

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591549322011.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591549322011.png)

### Transform Controls

[Official Positioning Documentation](https://docs.unity3d.com/Manual/PositioningGameObjects.html)

At the top-left of your Unity editor, you'll notice the transform control buttons where you can switch between `Hand`, `Move`, `Rotate`, `Scale`, `Rect`, and `Universal` controls. Each of these can also be toggled by pressing `Q`, `W`, `E`, `R`, `T`, and `Y`, respectively.

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591548971392.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591548971392.png)

#### Snapping to Collision

There will be many cases where you want to place an object on a table or ground within your scene. You should not need to manually fumble with axis to do this, but instead given that both objects have collision of some kind you can simply hold `Shift+Ctrl` while using the `Move` tool *and dragging the grey box that appears in the center of the object*, NOT the axis themselves. This will immediately snap the object to the collision nearest to your cursor as you drag it around the scene. There may be minor adjustments needed, but overall this should do the trick for most basic items.

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591555254244.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591555254244.png)


### Object to Scene View Transform

You will frequently want to move an object to the position and rotation of your current scene view in World space. You could manually drag the object across the scene in unity, adjusting each axis as needed. Alternatively, you can fly to a position near your desired location for the object, select the object, then press `Shift-Ctrl-F` to move the object to your exact position and rotation. This is *very* useful when setting up cameras, as you can just fly to the view you want the camera to display, select the camera, and press `Shift-Ctrl-F` to set it to that exact position with a lot less fumbling around.

### Unclickable Objects

Tired of clicking in the scene view and selecting the terrain or some other GameObject? Within the scene hierarchy you can toggle whether or not an object should be clickable. Simply click the small hand next to the object's name in the hierarchy.

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591557456670.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591557456670.png)

You can also toggle hiding and showing objects by clicking the eye icon just to the left of this setting

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591557501040.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591557501040.png)

# Prefabs

Since the Unity workflow is built around prefabs, I figured I'd document some specific use cases for the many features introduced in the Unity LTS 2019 release which added support for prefab variants and nested prefabs. On this page, I'll cover some good practices and features these prefab features provide.

I'd highly recommend heading over to [devassets.com](http://devassets.com/) to grab some of the assets you see featured across the Unity pages on Knoats. They are entirely free and give you a lot to work with when learning. If you can afford it, I would recommend donating to the developers. Not only does this unlock more assets you can get with the package you donated to, but it shows support to the developer that organized all of these great assets in one place for you to learn with.

### Positioning Prefabs

Being relatively new to Unity, I began by grabbing some assets off the Unity Store. Like most free assets on the store, these did not come entirely assembled for me and required me to work a bit to get things in a state that is usable for even the most basic games. This has been a good learning experience, and required no scripting, so if you are new to Unity and not quite ready to script, doing this will give you experience creating prefabs, working with materials, shaders, lighting, textures, and much more. 

At first when creating a prefab of an object that exists within your scene, you may see something like the below when opening the prefab to edit

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591556270971.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591556270971.png)

This is clearly not the orientation that we expect this `SciFi_Rover` vehicle to have when initially placed in our scene. To fix this, be sure you are editing the prefab in the prefab editor and NOT directly within your scene. Then adjust the transform to be in the orientation desired. 

Below, we see the initial transform settings

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591556400262.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591556400262.png)

First, set all but the `Scale` of your object to `0`. Shown in the screenshot below, there will be many cases that this does not produce the desired results, so we still need to modify the transform further

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591556607873.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591556607873.png)

After making some adjustments, the object's final orientation within the prefab editor is seen below

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591556709523.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591556709523.png)

And the final transform properties of the root GameObject are now much cleaner -

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591556742042.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591556742042.png)

# Post Processing

Good graphics are good. That's why I was excited to find adding Post Processing to my Unity 3D project was not only easy to do, but a huge improvement to the visuals within my scene. This enables common modern graphics features like Motion Blur, Ambient Occlusion, Depth of Field, and more.

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591622057414.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591622057414.png)

### Add Post Processing

Post Processing is added to each scene individually, and not a project as a whole. To add this to a Unity 3D project, we first need to add the `Post-process Layer` component to our scene's main camera. Next we'll add a Post Processing Volume that globally effects our entire scene. Then we can add a `PostProcessing_Profile` for our scene and add new visual effects accordingly. 


#### Configuring the Camera
Its important that the camera the player views the game from contains this component. Otherwise, if the player can toggle between a camera which has the `Post-process Layer` and one that does not, they effects gained by post processing will only be rendered in one view and not the other.

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591571962826.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591571962826.png)

Once we've added the above component to the scene's main camera, we need to adjust the layer of both this component and our main camera to reflect this. Change to the `Postprocessing` Layer in the `Post-process Layer` component. 

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591572189049.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591572189049.png)

Now change the layer of the camera itself to the `Postprocessing` Layer as well

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591572228339.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591572228339.png)


#### Creating the Volume
Now anywhere within your current scene hierarchy, add an empty GameObject and name it `PostProcessingVolume` or otherwise something relative to your specific scenario. Set this GameObject's layer to `Post Processing`. Select this new GameObject and within the inspector `Add Component->Post-processing Volume` as seen below

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591572363971.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591572363971.png)

At a glance, there is not much here. But once we add a Post Process Profile and finish configuring our scene we will use this component to adjust some pretty neat looking visuals. 

<p class="callout warning">Be sure to apply the <code>Post Processing</code> layer to the Camera and Volume GameObjects within your scene before continuing or the effects will not be applied</p>

##### Creating the Profile

Within the GameObject created for our Volume click `New` to the right of the `Profile` field in the new `Post-processing Volume` component.

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591572506570.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591572506570.png)

Unity will automatically create a Post Processing Profile and place it in a directory relative to your scene. Now we can check the `Global` tick box to apply this volume to our entire scene and start adding new effects to our scene!

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591572699575.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591572699575.png)

An example of some effects that I added to my scene to achieve the screenshot at the top of this page

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591572848307.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591572848307.png)

That's it! See the glow coming from the lights in the pictures below for an example of how this can be used to add the Bloom effect to an emissive light source.

**Post Processing on** \
[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591817450274.png)](https://www.knoats.com/up7loads/images/gallery/2020-06/image-1591817450274.png)
[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591817546494.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591817546494.png)

**Post Processing off** \
[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591818011855.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591818011855.png)
[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591817973490.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591817973490.png)

# Emission

### Emission Lighting

In my screenshot at the beginning of this page, I have a work light that both emits area light from the light source (bulbs) and shines a spot light. This is done using Emission Lighting and Post Processing Bloom within unity. The combination of the two makes for a GameObject which is pretty realistic, and for this Post Processing is required.

**Post Processing Enabled**\
[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591573524472.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591573524472.png)

**Post Processing Disabled**\
[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591573467518.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591573467518.png)

#### Defining the Source
First, you'll need to define the source of light emission. For my particular object, the only sources of light are isolated to the two bulbs at the top. It is important in this case to have the needed texture maps to configure emission from the source. Otherwise, you will have to create these texture maps yourself and apply them to the material, defining where the light source is. 

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591573267470.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591573267470.png)

For this GameObject's material, the albedo texture is seen below.

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591573674029.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591573674029.png)

It's easy to see the bulb near the center of this texture, but how do we define that area as our source of light? Below we see an Emission Color map, which simply shows the bulb in a lit state.

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591573802429.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591573802429.png)

Now we can apply the Emission Color map to our material by checking the `Emission` tick-box and applying this texture in the `Color` field. 

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591573869091.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591573869091.png)

#### Picking Color and Intensity

Now we can adjust the color swatch to the right of this texture as needed to adjust the emission light color. It's important to also adjust the `Intensity` of the color emission here to be relevant to your light source. For a work light, they are ultra bright so I wanted to wash the texture out with an ultra-white glow. Since you would literally be blinded by these things in real life if you were to stare into the bulbs, you would not see details of the light bulb or its material.

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591574884784.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591574884784.png)

That's it! See the glow coming from the lights in the pictures below for an example of how this can add visuals to any light source.

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591574821468.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591574821468.png)
[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591576507242.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591576507242.png)

### Emission Material
The other scenario here is just creating a new material which is entirely emissive of one color. This is very simple to do and not very practical, so I figured I'd show a more specific example using an Emission Color map. For simplicity though, it may be benficial to start with a simple setup like this just to see that Bloom and Emission is working correctly. Below, I've left a screenshot of an ultra-simple emssive material and the result of applying this to a barrel object within the same scene as my work light, with the same Post Processing configuration.

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591574658308.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591574658308.png)

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591574707703.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591574707703.png)

If you are having difficulties with Bloom not appearing or being very faint, try adjusting the Intensity and Threshold of your Post Processing Volume's Bloom effect.

[![](https://www.knoats.com/uploads/images/gallery/2020-06/scaled-1680-/image-1591577123440.png)](https://www.knoats.com/uploads/images/gallery/2020-06/image-1591577123440.png)

# New Input System

### Setup

Using the default configuration for a keyboard&mouse / Gamepad `Input Actions` asset in unity, we can implement universal controls given various input devices.

[![](https://knoats.com/uploads/images/gallery/2021-04/scaled-1680-/image-1618853283926.png)](https://knoats.com/uploads/images/gallery/2021-04/image-1618853283926.png)


<p class="callout info">Issues getting an input device to work? Click <code>Window->Analysis->Input Debugger</code> and at the top-left of the new window select <code>Options->Add Devices Not Listed in 'Supported Devices'</code> and any input device that was not previously working should now be passing input to unity. <br><br>
This was a weird bug for me to figure out, so I thought it was worth a mention. For me, I had to do this in order to get Unity to accept input from my Corsair gaming mouse. I searched up a lot of information on this new input system thinking I was using it wrong, and later found that my mouse was not passing input to unity and my code was correct.</p>

[![](https://knoats.com/uploads/images/gallery/2021-04/scaled-1680-/image-1618853641994.png)](https://knoats.com/uploads/images/gallery/2021-04/image-1618853641994.png)

---

### Use

We can call a specific function from a specific component

Using PlayerInput component->Behavior->Invoke Unity Events -

```C#
  Rigidbody playerRigidbody;
  public PlayerControls controls;
  Vector2 playerVelocity;
  public float playerSpeed = 5.0f;

  void Awake() {
    playerRigidbody = GetComponent<Rigidbody>();
    controls = new PlayerControls();
  }

  void OnEnable() {
    controls.Player.Enable();
  }

  void OnDisable() {
    controls.Player.Disable();
  }

  public void OnMove(InputAction.CallbackContext context) {
    print("Moving: " + context.ReadValue<Vector2>());
    playerVelocity = context.ReadValue<Vector2>();
  }
  
  public void OnLook(InputAction.CallbackContext context) {
    print("Look: " + context.ReadValue<Vector2>());
  }
  
  public void OnFire(InputAction.CallbackContext context) {
    print("Bang");
  }

  void Update()
  {
    playerRigidbody.position += new Vector3(playerVelocity.x * Time.deltaTime * playerSpeed,
      0,
      playerVelocity.y * Time.deltaTime * playerSpeed);
  }

```


Or we can let Unity call functions defined using the naming convention `void On\[ActionName\](InputValue value)`

Using PlayerInput component->Behavior->Send Messages -

```C#
  Rigidbody playerRigidbody;
  public PlayerControls controls;
  Vector2 playerVelocity;
  public float playerSpeed = 5.0f;


  void Awake() {
    playerRigidbody = GetComponent<Rigidbody>();
    controls = new PlayerControls();
  }

  void OnEnable() {
    controls.Player.Enable();
  }

  void OnDisable() {
    controls.Player.Disable();
  }

  public void OnMove(InputValue value) {
    playerVelocity = value.Get<Vector2>();
    print("Moving: " + value.Get<Vector2>());
  }


  public void OnMove(InputValue value) {
    playerVelocity = value.Get<Vector2>();
    print("Moving: " + value.Get<Vector2>());
  }


  void Update()
  {
    playerRigidbody.position += new Vector3(playerVelocity.x * Time.deltaTime * playerSpeed,
      0,
      playerVelocity.y * Time.deltaTime * playerSpeed);
  }

```

Broadcast messages is the same as Send Messages, except broadcasting invokes the same methods on all child objects who have a component with function definitions that match this naming convention.

# Unreal Engine 5

# Linux Setup

The setup process for UE4 on Linux is pretty straight forward, and the [official instructions](https://docs.unrealengine.com/4.27/en-US/SharingAndReleasing/Linux/BeginnerLinuxDeveloper/SettingUpAnUnrealWorkflow/) are very well documented. Follow those steps, and return here once you're done. Below, I just outline some of the issues I encountered using UE4 on Linux post-installation and how I solved them.

#### Marketplace Assets

Epic Games doesn't seem to provide any support for the UE4 Marketplace for Linux. As a result, Epic also does not support downloading and adding any assets to your project. Bummer.

I would like to note a blog post on this same issue by [alexandra-zaharia](https://alexandra-zaharia.github.io/posts/download-from-unreal-engine-4-marketplace-in-linux/), I would have very much preferred her solution but after attempting it I could not get it to work. I could install Epic Games through Lutris, but symlinking my projects (or copying them) into Wine Windows FS did not result in the Epic Games launcher detecting the projects.


What I ended up doing was using the **unofficial** [nmrugg/UE4Launcher](https://github.com/nmrugg/UE4Launcher) on GitHub. It works great, but I do miss some things like asset engine version information and browsing the marketplace.

You can install assets with it though, as long as you own them and they're linked to the Epic account you sign in with. That's all I need for now, I'm just playing with the idea of learning some C++ for UE4.


#### UI Scaling

[Related question on StackOverflow](https://stackoverflow.com/questions/62359942/a-couple-of-issues-with-installing-unreal-engine-under-linux/70670105)


Initially the UI for Unreal was very large and practically unusable. This could be due to the fact that I'm running on an integrated graphics CPU, but I'm not sure. To fix this, I just opened a project and navigated to `Edit->Editor Preferences` and then unchecked the `Enable High DPI Support` option under the `General/Appearance` settings menus. After restarting UE4, everything was good and UI was normal again.


#### Application Launchers

The shortcuts initialized by Unreal during the build process didn't work for me. I couldn't figure out why, so I just made my own. I placed these files into `~/.local/share/applications/`

<p class="callout warn">You will need to change the <code>Path</code> value to point to the same directories on your local system for the following configurations.</p>

For the Unreal Engine Editor, the following `UnrealEngine.desktop` file will launch a window to open or create a UE4 project

```bash
#!/usr/bin/env xdg-open

[Desktop Entry]
Version=1.0
Type=Application
Exec=UE4Editor
Path=/home/kapper/Code/Clones/UnrealEngine/Engine/Binaries/Linux
Name=Unreal Engine Editor
Icon=ubinary
Terminal=false
StartupWMClass=UE4Editor
MimeType=application/uproject
Comment=Open or create UE4 projects
````

And for the open source UE4Launcher, I created the following `UnrealEngineLauncher.desktop` file to run `npm start` in the UE4Launcher repository directory.

```bash
#!/usr/bin/env xdg-open

[Desktop Entry]
Version=1.0
Type=Application
Exec=npm start
Path=/home/kapper/Code/Clones/UE4Launcher/
Name=Unreal Engine Launcher
Icon=ubinary
Terminal=false
StartupWMClass=UE4Editor
MimeType=application/uproject
Comment=UE4 Project and asset management
````

#### Hardlinks for Editor Layouts

In the editor you can create and save layouts under the `Window->Load Layout` toolbar menus. After creating a layout, it will by default be output into the `UnrealEngine/Engine/Saved/Config/Layouts/` directory. 

I thought it'd be really useful to store the layout in the root directory of a project (tracked by github) and hardlink it from there to `~/Code/Clones/UnrealEngine/Engine/Saved/Config/Layouts` instead. This way, when you clone the project for development on another machine you keep your layout, and UE4 will still recognize it within the menus for loading and saving layouts.

To create the hardlink, I ran this command

```bash
ln ~/Code/Clones/UnrealEngine/Engine/Saved/Config/Layouts/EditorLayoutKapper.ini ~/Code/GameDev/UnrealProjects/ThirdPerson/EditorLayoutKapper.ini
```

#### Debugging

See [Build Configuration documentaiton](https://docs.unrealengine.com/4.27/en-US/ProductionPipelines/DevelopmentSetup/BuildConfigurations/) for more information of the various build targets that are made available when generating a C++ project solution with UE4. Also see [Compiling Projects](https://docs.unrealengine.com/4.27/en-US/ProductionPipelines/DevelopmentSetup/CompilingProjects/) for how to build and debug with Visual Studio.

I watched [this video on YouTube](https://www.youtube.com/watch?v=fydvKedIxKk) to learn how to debug UE4 projects using vscode. The instructions are for windows but it was very similar for linux. Just had to [install vscode on Linux](https://code.visualstudio.com/docs/setup/linux) first.

Once you have vscode installed, open the UE4 editor as you normally would to edit your project. Then, go to `Edit->Editor Preferences` and navigate to the `Source Code` settings menu from the left. Select Visual Studio Code from the drop down. You'll get a prompt to restart the editor, which you should do before continuing.

Once the UE4 editor has been restarted, navigate to `File->Generate Visual Studio Code Project`, there will be some loading screen that appears and once that finishes you can go to `File->Open Visual Studio Code`

Once inside our UE4 vscode project, push `CTRL+SHIFT+B` and run the `<YOUR_PROJECT_NAME>Editor (Development)` build task. This task was defined for us by UE4 when we generated our vscode project in the previous step, and the entry within my `launch.json` is seen below. 

```json
{
	"name": "ThirdPersonEditor (Development)",
	"request": "launch",
	"preLaunchTask": "ThirdPersonEditor Linux Development Build",
	"program": "/home/kapper/Code/Clones/UnrealEngine/Engine/Binaries/Linux/UE4Editor",
	"args": [
		"/home/kapper/Code/GameDev/UnrealProjects/unrealgame/ThirdPerson.uproject"
	],
	"cwd": "/home/kapper/Code/Clones/UnrealEngine",
	"type": "lldb"
},
        
```

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1641995919691.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1641995919691.png)

Running this task for the first time could take a bit of time depending on the size of your project. When this finishes building, it should automatically start a new UE4 editor with your project open and in debug mode. If it doesn't, just select the `<YOUR_PROJECT_NAME>Editor (Development)` debug configuration in the sidebar and click the run button.

I also had to run the following command to install a missing dependency. The first time I tried to build there was an error and after reading it I traced it to this package and installed. The development build was successful after installing.

```bash
sudo apt install libopenvr-dev
```

Now you can run the same debug configuration and once the UE4 editor launches make sure whatever script you're debugging is active within your scene or your code breakpoint will not be hit. 


Debugging on Windows under Visual Studios is very well documented, so while I do also have a windows development setup for UE4 I wont cover that here. 

No luck with CLion, I seen memory usage during the build jump from 6GB to 16GB, plus an additional 4GB of swap space was also ate up.

Possibly a better solution: [Running UE4 from Qt Creator](https://docs.unrealengine.com/4.27/en-US/SharingAndReleasing/Linux/BeginnerLinuxDeveloper/SettingUpQtCreator/)

Since writing this, I've been using [Rider for Unreal Engine](https://www.jetbrains.com/lp/rider-unreal/), It's in EA right now so you have to apply for access but I was accepted almost immediately so you shouldn't have any issues.

# Notes

Useful documentation / references

[Renaming classes](https://unrealxeditor.wordpress.com/2015/05/28/tip-renaming-c-classes-without-breaking-your-project/) community tip, and the official documentation for [Redirectors](https://docs.unrealengine.com/4.27/en-US/ProductionPipelines/Redirectors/) 

See [UE4 C++ Architecture](https://docs.unrealengine.com/4.27/en-US/ProgrammingAndScripting/ProgrammingWithCPP/UnrealArchitecture/) for information on how to use the various parts of UE4 through C++ such as Actors, Scenes, Lights, etc.

[C++ UE4 Class Creation Basics](https://docs.unrealengine.com/4.27/en-US/ProgrammingAndScripting/ClassCreation/)

[Event Dispatching](https://docs.unrealengine.com/4.27/en-US/ProgrammingAndScripting/ActorCommunication/EventDispatcherQuickStart/)

[Blueprints Quick Start](https://docs.unrealengine.com/4.27/en-US/ProgrammingAndScripting/Blueprints/QuickStart/)

[Gameplay Architecture](https://docs.unrealengine.com/4.27/en-US/ProgrammingAndScripting/GameplayArchitecture/)

[Gameplay Debugger](https://docs.unrealengine.com/4.27/en-US/ProgrammingAndScripting/GameplayDebugger/)


For unreal engine world space coordinate system: Positive `X` is forward. Positive `Y` is right. Positive `Z` is up.

Quoting from the [UE4 C++ coding standard](https://docs.unrealengine.com/4.27/en-US/ProductionPipelines/DevelopmentSetup/CodingStandard/) -

> Template classes are prefixed by T.
>
> Classes that inherit from UObject are prefixed by U.
>
> Classes that inherit from AActor are prefixed by A.
> 
> Classes that inherit from SWidget are prefixed by S.
> 
> Classes that are abstract interfaces are prefixed by I.
> 
> Enums are prefixed by E.
> 
> Boolean variables must be prefixed by b (for example, bPendingDestruction, or bHasFadedIn).
> 
> Most other classes are prefixed by F, though some subsystems use other letters.
> 
> Typedefs should be prefixed by whatever is appropriate for that type: F if it's a typedef of a struct, U if it's a typedef of a UObject and so on. 

Braces should be on newlines, and should always be present even for simple code blocks that could be formatted on a single line.

```cpp
// Good
if (bThing)
{
    return;
}

// Bad
if (bThing) return;
```

The standard says to use tabs and not spaces. I will be breaking this rule and using spaces. Sorry :(

Switch cases formatting -
```cpp
switch (condition)
{
    case 1:
        ...
        // falls through
          
    default:
        break;
}
```

[Logging text to Visual Logger](https://docs.unrealengine.com/4.27/en-US/TestingAndOptimization/VisualLogger/#loggingtext)


##### Tutorials

[All official UE4 sample and tutorials](https://docs.unrealengine.com/4.27/en-US/Resources/)

[Spawning and destroying actors (Blueprints or C++)](https://docs.unrealengine.com/4.27/en-US/ProgrammingAndScripting/SpawnAndDestroyActors/)

[Player / Camera pawn movement](https://docs.unrealengine.com/4.27/en-US/ProgrammingAndScripting/ProgrammingWithCPP/CPPTutorials/PlayerCamera/)

Highly recommended tutorial: [Advanced Player / Camera Movement With Animation](https://docs.unrealengine.com/4.27/en-US/InteractiveExperiences/HowTo/CharacterMovement/)


#### Game Feature Plugins

In UE5, you can create Game Feature Plugins to abstract content and features out from the base content of your game. To use these features, you'll need to enable these two plugins under `Edit -> Plugins...`

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642360021551.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642360021551.png)

[Epic Tutorial on Game Feature Plugins](https://www.youtube.com/watch?v=3PBnqC7TxvM&list=PLZlv_N0_O1gZmDqpSAEXEmATpv-HgQJYp)

[Unreal Directive tutorial on Game Feature Plugins](https://www.youtube.com/watch?v=HgnkfFWoHwk&lc=UgwKEPiY5sbWIdpiXlN4AaABAg.9XGPCZZVQPX9XGU8_kn_lR)

After watching these videos, I was curious how to create a Game Feature Plugin that held literal assets to use within the map. I asked [Unreal Directive](https://www.youtube.com/channel/UCtCAUfJR2y5x6ELcn3XZe0A) on YouTube via a comment and he replied to help me sort this out. Definitely check out his channel and [his website](https://www.unrealdirective.com/unreal-engine-tips-tricks/), they are great resources and have helped me get going this past week in UE5.

This is maybe a bad use case, since he indicated there would be reference errors if you remove the plugin from your game while the assets still exist within the scene. For me, this is fine because the reason I was creating the plugin was only to abstract out game assets I got from the marketplace into a Game Feature Plugin that could retain original file structure for these assets without cluttering up my `Content/` folder. Since I'm not really making a game, and my level is a simple terrain with a few object I'm currently playing with, removing these references from my scene is very simple. That paired with the Game Feature Plugins allows me to pull in various assets to implement a feature and then remove the feature at a later date once I've disassembled all the assets and learned everything I could. Usually, at that point I have made my own custom version of the same assets so removing them is no problem, if I hadn't already removed and replaced them during development.

Anyhow, to enable Game Feature Plugin assets to be used in your scene literally, you'll need to navigate to `Edit -> Project Preferences -> Game -> Asset Referencing Policy -> Project Content -> Default Project Content Rule -> Can Reference These Domains -> New Element -> Select Game Feature`

Here's what this setting looks like for me, after adding the `DungeonLamps` Game Feature Plugin to my project.

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642360004690.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642360004690.png)

#### Chaos Destruction

Chaose Destruction comes enabled by default for UE5. You won't need to install any plugins to use the default functionality of Chaos.

[Chaos Destruction Documentation](https://docs.unrealengine.com/4.27/en-US/InteractiveExperiences/Physics/ChaosPhysics/ChaosDestruction/ChaosDestructionOverview/)

[Epic Live Stream - Chaos Fundamentals](https://www.youtube.com/watch?v=hx9dHgcN0bE)

After generating Geometry Cluster, with the object selected and while in Fracture mode, you can use the following keybinds

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642357320484.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642357320484.png)

```
Shift+W To move up the fracture level hierarchy
Shift+S To move down the fracture level hierarchy
Shift+E To explode the object further, distancing the fractured pieces more
Shift+Q To decreate object explosion / expansion, bringing the fractures back together
Shift+B To toggle selection highlight texture
```

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642357416310.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642357416310.png)

#### Fixing Asset Referencces

Sometimes when deleteing a folder with assets inside, you might want to also remove that folder entirely from your game's `Content/`  directory. Upon trying to do this, you might get an error about redirectors within the directory that are still referenced in your scene. But, you check the Content Explorer in UE and there are no files in the directory, as you've relocated them all elsewhere. **Do not force delete the directory**

Right click the directory and select `Fix Up Redirectors in Folder` and then try to delete the directory again. It should be removed with no errors!


#### Configuration files


Plugin settings are stored in your `ProjectName.uproject` file when opened with a text editor. Simply removing an entry from the `Plugins` section will disable the plugin for your project.

```
{
	"FileVersion": 3,
	"EngineAssociation": "5.0",
	"Category": "",
	"Description": "",
	"Modules": [
		{
			"Name": "unrealgame5",
			"Type": "Runtime",
			"LoadingPhase": "Default",
			"AdditionalDependencies": [
				"Engine"
			]
		}
	],
	"Plugins": [
		{
			"Name": "ThirdPersonCharacter",
			"Enabled": false
		},
		{
			"Name": "Water",
			"Enabled": true
		},
		{
			"Name": "GameFeatures",
			"Enabled": true
		},
		{
			"Name": "ModularGameplay",
			"Enabled": true
		},
		{
			"Name": "GameplayAbilities",
			"Enabled": true
		}
	]
}
```

Additional settings in the `projectname.build.cs` file

```
// Copyright Epic Games, Inc. All Rights Reserved.

using UnrealBuildTool;

public class unrealgame5 : ModuleRules
{
	public unrealgame5(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

		PublicDependencyModuleNames.AddRange(new string[]
    {
      "GameplayAbilities", "GameplayTags", "GameplayTasks",
      "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay"
    });
  }
}
```

# Gameplay Ability System

**Links and sources**

[Example of using the GAS: GASShooter GitHub project](https://github.com/tranek/GASShooter)

[Unofficial but detailed GAS Documentation](https://github.com/tranek/GASDocumentation#concepts-a)

[Epic livestream in depth look at GAS](https://www.youtube.com/watch?v=YvXvWa6vbAA&list=PL2u3PgypHeMxgVYCSEY7D7Fw_chCHlt_J&index=3)

Highly recommended: [Setting up GAS youtube tutorial](https://www.youtube.com/watch?v=Yub52f4ZUU0)

#### Notes

Any Actor that wishes to use GameplayAbilities, have Attributes, or receive GameplayEffects must have one AbilitySystemComponent (ASC) attached to them. \
ASC can be assigned to weapons, players, or AI

The Actor with the ASC attached to it is referred to as the OwnerActor of the ASC. \
The physical representation Actor of the ASC is called the AvatarActor \
The OwnerActor and AvatarActor can either be the same or different depending on the use case

If your Actor will respawn and need persistence of Attributes or GameplayEffects between spawns (like a hero in a MOBA), then the ideal location for the ASC is on the PlayerState.



## Brief

In the sections below, my game is named `unrealgame5`, and any appearances of this string should be replaced by your own project name. This page outlines the process of setting up the Gameplay Ability System for use in an Unreal Engine 5 game using C++. Blueprints can still be used for prototyping new abilities, which can later be translated to C++.


### Project Plugins and Modules

To setup out UE5 project to use the required modules, we need to edit our `<PROJECT_NAME>.build.cs` file. This file should have been generated by Unreal Engine when your project was created, and for me my file is named `unrealgame5.build.cs`

Initial contents of `unrealgame5.build.cs`, before I made any changes.

```c++
using UnrealBuildTool;

public class unrealgame5 : ModuleRules
{
	public unrealgame5(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

		PublicDependencyModuleNames.AddRange(new string[] {"Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay"});
  }
}
```



Add ` "GameplayAbilities", "GameplayTags", "GameplayTasks"` modules to `unrealgame5.build.cs` so your file looks like the following. 
```c++
using UnrealBuildTool;

public class unrealgame5 : ModuleRules
{
	public unrealgame5(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay" });
		PublicDependencyModuleNames.AddRange(new string[] { "GameplayAbilities", "GameplayTags", "GameplayTasks" });
	}
}
```

Then within the editor go to `Edit->Plugins...` and enable the `Gameplay Abilities` plugin. You will need to restart the editor for the changes to apply.

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642607769456.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642607769456.png)


### C++ Initial Setup

To set up the scaffolding for the GAS, we need a few things - 

* Enumeration of abilities to correlate with input actions
* Core GameplayAbilitySystem 
* Set of attributes for our player and / or enemies
* Player character inheriting from `IAbilitySystemInterface` class
* GameplayEffect to apply default attributes for our player / enemies
* AnimGraphs with Montage slots for handling abilitiy animations

So, to complete this setup you will at least need to define a few new classes for your project.

For my project I follow the same naming convention used with GASDocumentation. I'll paste it below, but for the first few files required to set up the Gameplay Ability System (GAS), we are defining the backend of the system so none of these conventions apply. For these files, I added the `GAS_` convention.

```
Prefix 	Asset Type
GA_ 	GameplayAbility
GC_ 	GameplayCue
GE_ 	GameplayEffect
GAS_    GameplayAbilitySystem (Core Configurations)
```

#### Ability Enumeration

First, we need to modify the contents of the header file for our unreal project. My project is named `unrealgame5` so the file is `unrealgame5.h`, and the contents are below. If you already have information here, just make sure the `EGASAbilityInputID` enumeration is added to the header file and save your changes. This enumeration is used to correlate input actions to activate certain abilities in our game.

**Note:** `Attack` below must either be changed to match or made to match some keybind within your `Edit->Project Settings->Input` options menu.

```c++
// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"

UENUM(BlueprintType)
enum class EGASAbilityInputID : uint8
{
  None, 
  Confirm, 
  Cancel,
  Attack
};
```

#### Ability System Component

Next, we need to create an `AbilitySystemComponent`. This will be the component that we attach to actors that we want to take use with the GAS. To create this component, open your project in unreal and create a new C++ source file, inheiriting from the `AbilitySystemComponent` base class. 

This base class is provided by UE5, assuming you have the `GameplayAbilities` plugin installed to your project. In order to inherit from it, we need to create a new C++ Class. We must be in the `C++ Classes` subdirectory of our project in order to do this.

[![](https://knoats.com/uploads/images/gallery/2022-08/scaled-1680-/image-1661120353126.PNG)](https://knoats.com/uploads/images/gallery/2022-08/image-1661120353126.PNG)

Next click `All Classes` and search for `AbilitySystemComponent`.

[![](https://knoats.com/uploads/images/gallery/2022-08/scaled-1680-/image-1661120409203.PNG)](https://knoats.com/uploads/images/gallery/2022-08/image-1661120409203.PNG)

 Click next and name your class, I'll name this class `GAS_AbilitySystemComponent`.

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642612991508.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642612991508.png)

The generated files are seen below. You don't need to put anything else in here for now.  Note that UE5 prefixed our original class name `GAS_AbilitySystemComponent` with a `U` - it's name in the source code is `UGAS_AbilitySystemComponent`, this is normal and to be expected.

```c++
// GAS_AbilitySystemComponent.h
// All content (c) Shaun Reed 2021, all rights reserved

#pragma once

#include "CoreMinimal.h"
#include "AbilitySystemComponent.h"
#include "GAS_AbilitySystemComponent.generated.h"

/**
 * 
 */
UCLASS()
class UNREALGAME5_API UGAS_AbilitySystemComponent : public UAbilitySystemComponent
{
	GENERATED_BODY()
    
};
```


```c++
// GAS_AbilitySystemComponent.cpp
// All content (c) Shaun Reed 2021, all rights reserved

#include "GAS_AbilitySystemComponent.h"
```

#### Gameplay Abilities

Next we'll setup the base class that we will use for adding abilities to our game. To do this we need to create another new C++ Source file like we did in the previous step, only this time we will inherit from the `GameplayAbility` class provided with the `GameplayAbilities` UE5 plugin.

[![](https://knoats.com/uploads/images/gallery/2022-08/scaled-1680-/image-1661121051794.png)](https://knoats.com/uploads/images/gallery/2022-08/image-1661121051794.png)

I named this class `GAS_GameplayAbility` and the source code is seen below

```C++
// GAS_GameplayAbility.h
// All content (c) Shaun Reed 2021, all rights reserved

#pragma once

#include "../unrealgame5.h"

#include "CoreMinimal.h"
#include "Abilities/GameplayAbility.h"
#include "GAS_GameplayAbility.generated.h"

UCLASS()
class UNREALGAME5_API UGAS_GameplayAbility : public UGameplayAbility
{
	GENERATED_BODY()

public:
	UGAS_GameplayAbility();

	UPROPERTY(BlueprintReadOnly, EditAnywhere, Category = "Ability")
		EGASAbilityInputID AbilityInputID = EGASAbilityInputID::None;
};
```


```C++
// All content (c) Shaun Reed 2021, all rights reserved
// GAS_GameplayAbility.cpp

#include "GAS_GameplayAbility.h"

UGAS_GameplayAbility::UGAS_GameplayAbility() { }
```


#### Attribute Sets

Next, we need to create an `AttributeSet` for our game. Repeat the process of creating a new C++ sourcce file for your ue5 project, but this time inherit from `AttributeSet`

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642613191128.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642613191128.png)

I named this class `GAS_AttributeSet` and the files genereated are below


```c++
// GAS_AttributeSet.h
// All content (c) Shaun Reed 2021, all rights reserved

#pragma once

#include "AbilitySystemComponent.h"

#include "CoreMinimal.h"
#include "AttributeSet.h"
#include "GAS_AttributeSet.generated.h"

// Macros to define getters and setters for attributes (AttributeSet.h)
#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
		GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
		GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
		GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
		GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)

UCLASS()
class UNREALGAME5_API UGAS_AttributeSet : public UAttributeSet
{
	GENERATED_BODY()
    
  UGAS_AttributeSet();

public:
	virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;

	/*
	* Attribute Definitions
	*/

	// Health

	UPROPERTY(BlueprintReadOnly, Category = "Attributes", ReplicatedUsing = OnRep_Health)
	FGameplayAttributeData Health;
	// Use macros we defined from AttributeSet.h to generate getters and setters
	ATTRIBUTE_ACCESSORS(UGAS_AttributeSet, Health);

	UFUNCTION()
		virtual void OnRep_Health(const FGameplayAttributeData& OldHealth);

	// Stamina

	UPROPERTY(BlueprintReadOnly, Category = "Attributes", ReplicatedUsing = OnRep_Stamina)
	FGameplayAttributeData Stamina;
	ATTRIBUTE_ACCESSORS(UGAS_AttributeSet, Stamina);

	UFUNCTION()
		virtual void OnRep_Stamina(const FGameplayAttributeData& OldStamina);

	// Attack Power

	UPROPERTY(BlueprintReadOnly, Category = "Attributes", ReplicatedUsing = OnRep_AttackPower)
	FGameplayAttributeData AttackPower;
	ATTRIBUTE_ACCESSORS(UGAS_AttributeSet, AttackPower);

	UFUNCTION()
		virtual void OnRep_AttackPower(const FGameplayAttributeData& OldAttackPower);
};
```



```c++
// GAS_AttributeSet.cpp
// All content (c) Shaun Reed 2021, all rights reserved

#include "Net/UnrealNetwork.h"  // DOREPLIFETIME
#include "GAS_AttributeSet.h"

UGAS_AttributeSet::UGAS_AttributeSet()
{
}

void UGAS_AttributeSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
  Super::GetLifetimeReplicatedProps(OutLifetimeProps);
  
  DOREPLIFETIME_CONDITION_NOTIFY(UGAS_AttributeSet, Health, COND_None, REPNOTIFY_Always);
  DOREPLIFETIME_CONDITION_NOTIFY(UGAS_AttributeSet, Stamina, COND_None, REPNOTIFY_Always);
  DOREPLIFETIME_CONDITION_NOTIFY(UGAS_AttributeSet, AttackPower, COND_None, REPNOTIFY_Always);

}

void UGAS_AttributeSet::OnRep_Health(const FGameplayAttributeData& OldHealth)
{
  GAMEPLAYATTRIBUTE_REPNOTIFY(UGAS_AttributeSet, Health, OldHealth);
}

void UGAS_AttributeSet::OnRep_Stamina(const FGameplayAttributeData& OldStamina)
{
  GAMEPLAYATTRIBUTE_REPNOTIFY(UGAS_AttributeSet, Stamina, OldStamina);
}

void UGAS_AttributeSet::OnRep_AttackPower(const FGameplayAttributeData& OldAttackPower)
{
  GAMEPLAYATTRIBUTE_REPNOTIFY(UGAS_AttributeSet, AttackPower, OldAttackPower);
}
```


#### Character Setup

In the files below, my character is named `ThirdPersonCharacter`, so any appearances of this string may need to be replaced with your character's name instead. To setup your character that inherits from `ACharacter` base class, make the following changes to your files.

In the `ThirdPersonCharacter.h` file, make sure you're inheriting from `public IABilitySystemInterface`. The start of your class should look like this. Pay attention to the includes.

```c++
// All content (c) Shaun Reed 2021, all rights reserved

#pragma once

// GAS includes
#include "AbilitySystemInterface.h"
#include <GameplatEffectTypes.h>

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "ThirdPersonCharacter.generated.h"

UCLASS()
class UNREALGAME5_API AThirdPersonCharacter : public ACharacter, public IAbilitySystemInterface
{
	GENERATED_BODY()

public:

// more code....
```

##### Character Components

Next, we add an instance of our `GAS_AbilitySystem` class using the `UGAS_AbilitySystemComponent` typename, and we also add an instance of our `GAS_AttributeSet` class using the `UGAS_AttributeSet` type.

```c++
UCLASS()
class UNREALGAME5_API AThirdPersonCharacter : public ACharacter, public IAbilitySystemInterface
{
	GENERATED_BODY()

public:
	// GAS declarations
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "GAS")
	class UGAS_AbilitySystemComponent* AbilitySystemComponent;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "GAS")
    class UGAS_AttributeSet* Attributes;
// more code....
```

Now we need to modify the character's constructor to add the new components we've declared. I removed the code from my constructor that wasn't related to the GAS. The additions are below.

```c++
// ThirdPersonCharacter.cpp

AThirdPersonCharacter::AThirdPersonCharacter()
{
 	// Initializing any components unrelated to GAS...
	// ...

	  // Initialize GAS related components
	AbilitySystemComponent = CreateDefaultSubobject<UGAS_AbilitySystemComponent>(TEXT("AbilitySystemComponent"));
	AbilitySystemComponent->SetIsReplicated(true);
	AbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Minimal);
    Attributes = CreateDefaultSubobject<UGAS_AttributeSet>(TEXT("Attributes"));
}

```

So we have the components we need, and the next step is to provide the required definitions for virtual functions we've inheirted from `IAbilitySystemInterface` 

##### Virtual Functions

To start, we declare the required virtual functions that we will need to define to use the GAS.

```c++
UCLASS()
class UNREALGAME5_API AThirdPersonCharacter : public ACharacter, public IAbilitySystemInterface
{
	GENERATED_BODY()

public:
	// GAS declarations
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "GAS")
	class UGAS_AbilitySystemComponent* AbilitySystemComponent;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "GAS")
    class UGAS_AttributeSet* Attributes;
    
	virtual class UAbilitySystemComponent* GetAbilitySystemComponent() const override;
    
// more code....
```

We implement `GetAbilitySystemComponent`, which is just a simple getter that returns our `UGAS_AbilitySystemComponent` component.

```c++
// ThirdPersonCharacter.cpp
UAbilitySystemComponent* AThirdPersonCharacter::GetAbilitySystemComponent() const
{
	return AbilitySystemComponent;
}
```


Next we need to overload a virtual function `InitializeAttributes()` to handle initializing the attributes for our game at the start. We also declare the `DefaultAttributeEffect` member variable to help define and apply the default attributes for our character.

```c++
// ThirdPersonCharacter.h
UCLASS()
class UNREALGAME5_API AThirdPersonCharacter : public ACharacter, public IAbilitySystemInterface
{
	GENERATED_BODY()

public:
	// GAS declarations
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "GAS")
	class UGAS_AbilitySystemComponent* AbilitySystemComponent;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "GAS")
    class UGAS_AttributeSet* Attributes;
    
	virtual class UAbilitySystemComponent* GetAbilitySystemComponent() const override;
    
    // Add these lines
  	virtual void InitializeAttributes();
    UPROPERTY(BlueprintReadOnly, EditDefaultOnly, Category = "GAS")
    TSubclassOf<class UGameplayEffect> DefaultAttributeEffect;
// more code....
```

Define `InitializeAttributes()`

```c++
// ThirdPersonCharacter.cpp
void AThirdPersonCharacter::InitializeAttributes()
{
	// If the ASC and DefaultAttributeEffect objects are valid
	if (AbilitySystemComponent && DefaultAttributeEffect)
	{
		// Create context object for this gameplay effecct
		FGameplayEffectContextHandle EffectContext = AbilitySystemComponent->MakeEffectContext();
		EffectContext.AddSourceObject(this);

		// Create an outgoing effect spec using the effect to apply and the context
		FGameplayEffectSpecHandle SpecHandle = AbilitySystemComponent->MakeOutgoingSpec(DefaultAttributeEffect, 1, EffectContext);

		if (SpecHandle.IsValid())
		{
			// Apply the effect using the derived spec
			// + Could be ApplyGameplayEffectToTarget() instead if we were shooting a target
			FActiveGameplayEffectHandle GEHandle = AbilitySystemComponent->ApplyGameplayEffectSpecToSelf(*SpecHandle.Data.Get());
		}
	}
}
```


Similar to how we defined default attributes, we define default abilities for our character by overloading the `GiveAbilities()` function. We also add the `DefaultAbilities` array to store the default abilities for the character. 

Notice that we use the `UPROPERTY` macro to apply `EditDefaultOnly` to our components. This will later allow us to modify these components in the UE5 editor for our character's blueprint, so we can dynamically add and remove attributes and abilities for our player without modifying the code each time.  

```c++
// ThirdPersonCharacter.h
UCLASS()
class UNREALGAME5_API AThirdPersonCharacter : public ACharacter, public IAbilitySystemInterface
{
	GENERATED_BODY()

public:
	// GAS declarations

	// Define components to store ASC and attributes
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "GAS")
	class UGAS_AbilitySystemComponent* AbilitySystemComponent;
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "GAS")
  class UGAS_AttributeSet* Attributes;

	virtual class UAbilitySystemComponent* GetAbilitySystemComponent() const override;
	// Overload to initialize attributes for GAS, and component to store default attributes
	virtual void InitializeAttributes();
	UPROPERTY(BlueprintReadOnly, EditDefaultOnly, Category = "GAS")
  TSubclassOf<class UGameplayEffect> DefaultAttributeEffect;

	// Overload to initialize abilities for GAS, and component to store default abilities
	virtual void GiveAbilities();
	UPROPERTY(BlueprintReadOnly, EditDefaultOnly, Category = "GAS")
	TArray<TSubclassOf<class UGAS_GameplayAbility>> DefaultAbilities;
public:	
// more code....
```

And we define `GiveAbilities` below to handle the allocation of default abilities to our character.

```c++
// ThirdPersonCharacter.cpp
void AThirdPersonCharacter::GiveAbilities()
{
	// If the server has the authority to grant abilities and there is a valid ASC
	if (HasAuthority() && AbilitySystemComponent)
	{
		// Foreach ability in DefaultAbilities, grant the ability
		for (TSubclassOf<UGAS_GameplayAbility>& StartupAbility : DefaultAbilities)
		{
			// `1` below is the level of the ability, which could later be used to allow abilities to scale with player level
			AbilitySystemComponent->GiveAbility(
				FGameplayAbilitySpec(StartupAbility, 1, static_cast<int32>(StartupAbility.GetDefaultObject()->AbilityInputID), this));
		}
	}
}
```


For the next step, we need to override `PossessedBy` and `OnRep_PlayerState()` to define how to update the server and client of the player state respectively.


```c++
// ThirdPersonCharacter.h
UCLASS()
class UNREALGAME5_API AThirdPersonCharacter : public ACharacter, public IAbilitySystemInterface
{
	GENERATED_BODY()

public:
	// GAS declarations

	// Define components to store ASC and attributes
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "GAS")
	class UGAS_AbilitySystemComponent* AbilitySystemComponent;
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "GAS")
  class UGAS_AttributeSet* Attributes;

	virtual class UAbilitySystemComponent* GetAbilitySystemComponent() const override;
	// Overload to initialize attributes for GAS, and component to store default attributes
	virtual void InitializeAttributes();
	UPROPERTY(BlueprintReadOnly, EditDefaultOnly, Category = "GAS")
  TSubclassOf<class UGameplayEffect> DefaultAttributeEffect;

	// Overload to initialize abilities for GAS, and component to store default abilities
	virtual void GiveAbilities();
	UPROPERTY(BlueprintReadOnly, EditDefaultOnly, Category = "GAS")
	TArray<TSubclassOf<class UGAS_GameplayAbility>> DefaultAbilities;
public:	
// more code....
```

And see the definitions for these functions below

```c++
// ThirdPersonCharacter.cpp
void AThirdPersonCharacter::PossessedBy(AController* NewController)
{
	Super::PossessedBy(NewController);

	// Owner and Avatar are bother this character
	AbilitySystemComponent->InitAbilityActorInfo(this, this);

	InitializeAttributes();
	GiveAbilities();
}

void AThirdPersonCharacter::OnRep_PlayerState()
{
	Super::OnRep_PlayerState();

	AbilitySystemComponent->InitAbilityActorInfo(this, this);
	InitializeAttributes();

	if (AbilitySystemComponent && InputComponent)
	{
		// Where the 3rd parameter is a string equal to enum typename defined in unrealgame5.h
		const FGameplayAbilityInputBinds Binds("Confirm", "Cancel", "EGASAbilityInputID", static_cast<int32>(EGASAbilityInputID::Confirm), static_cast<int32>(EGASAbilityInputID::Cancel));
		AbilitySystemComponent->BindAbilityActivationToInputComponent(InputComponent, Binds);
	}
}
```


As a final modification, add the following code to the function equivalent to `ThirdPersonCharacter::SetupPlayerInputComponent()` in your project. This is the same code as the last portion of `OnRep_PlayerState`

```c++
void AThirdPersonCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	// Code unrelated to GAS...
	// ...  
  
	// Make sure GAS is valid along with player input component
	if (AbilitySystemComponent && InputComponent)
	{
		// Where the 3rd parameter is a string equal to enum typename defined in unrealgame5.h
		const FGameplayAbilityInputBinds Binds("Confirm", "Cancel", "EGASAbilityInputID", static_cast<int32>(EGASAbilityInputID::Confirm), static_cast<int32>(EGASAbilityInputID::Cancel));
		AbilitySystemComponent->BindAbilityActivationToInputComponent(InputComponent, Binds);
	}
}
```

And just to be sure we have all the headers we need, here are the final includes for my character

```c++
// ThirdPersonCharacter.h
// GAS includes
#include "AbilitySystemInterface.h"
#include <GameplayEffectTypes.h>
#include "GAS_AbilitySystemComponent.h"
#include "GAS_GameplayAbility.h"
#include "GAS_AttributeSet.h"

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "ThirdPersonCharacter.generated.h"
```

```c++
// ThirdPersonCharacter.cpp
// All content (c) Shaun Reed 2021, all rights reserved

#include "ThirdPersonCharacter.h"

// Custom includes (Not related to GAS)
#include "ActorSpawner.h"  // Fireball spawner object
#include "BallActor.h"  // Fireball object

// Includes for GAS
#include "../unrealgame5.h"

// Engine includes
#include "Kismet/GameplayStatics.h" // For spawning fireball static mesh
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
```


### Defining Abilities

At this point we have configured GAS for our project and our character, so we're ready to start defining our abilities!

In my assets folder, I just created an `Abilities` subdirectory and continued with the steps below, creating the assets within this directory.

#### Default Abilities

First I created a new Blueprint Class using the editor and derived from the `GameplayEffect` class. Applying this effect will result in the player or character being granted a set of default abilities. 

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642618895337.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642618895337.png)

I named this `GE_CharacterDefaults`, and opened it for editing. The screenshot below contains all settings I modified under the `Class Defaults` panel. If it isn't in this screenshot, I didn't change it.

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642619166479.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642619166479.png)

Then I opened my `BP_ThirdPersonCharacter` blueprint for editing and applied the following settings within the `details` panel. You should notice at this point that the `DefaultAttributeEffect` and `DefaultAttributes` in this screenshot are actually the components we exposed to the editor in our `ThirdPersonCharacter.h` file earlier with `UPROPERTY` and `EditDefaultsOnly`. 

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642620733145.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642620733145.png)

### Damage Effect

To prove the system is working, create a new blueprint that derives from `GameplayEffect` and apply the settings below

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642620096481.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642620096481.png)

Then, in the event chart for your `BP_ThirdPersonCharacter` add a `BeginPlay` node and apply the damage when the game starts.

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642620207711.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642620207711.png)

Hit play and then open a console and type `showdebug abilitysystem` to see that your HP should now be `80` on the lefthand side. Remove the damage to your player when youre done testing, but you can keep the `GE_Damage` asset around to use it later.

### Attack Ability

First, open the animation blueprint for your character and add a montage `Slot 'DefaultSlot'` to your anim graph. For me, the screen looks like the below after the changes have been made. Make sure to save and apply these changes.

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642620498605.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642620498605.png)

Make a new blueprint deriving from the `GAS_GameplayAbilitiy` class that we defined earlier. 

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642619331071.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642619331071.png)

I named this `GA_Attack` and opened it for editing. 

Make sure the `Ability Input ID` matches the input action we want the ability to be mapped to. This is found under the `details` panel.

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642619555930.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642619555930.png)

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642638033467.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642638033467.png)

Next, open `GA_Attack` for editing and add the following blueprint nodes. Add the `GetActorInfo` node in the context menu in the screenshot, be sure to uncheck 'Context Sensitive' if it isn't appearing at first.

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642638307704.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642638307704.png)

Now right click the `GetActorInfo` node and select `Split Struct Pin` to split the actor into its components

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642638381872.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642638381872.png)

And connect the skeletal mesh pins to finish the blueprint for `GA_Attack` 

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642638429487.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642638429487.png)

Under the `Montage To Play` pin on the `Play Montage` node, you may not have a montage available for your skeleton.

If you also don't have an animation, check out [Mixamo](https://www.mixamo.com/#/) for a free anmation and see the page on [Retargeting Skeleton Animations](https://knoats.com/books/game-development/page/retarget-skeleton-animations)

Then create a montage by watching [this quick youtube video](https://youtu.be/MhMJt3VWfk0). If you're doing a simple punch animation, you probably just need to create a montage and click and drag the animation into the center of the screen and save. It's pretty simple, but you can use Motages to do some pretty neat things. Maybe for the first montage try making a one-off animation that doesn't loop like punching or a grab motion for interactions.

Once you have the montage made, select it here in this node, and then play the game. You'll now be able to see your character performing the attack!

#### Additional Abilities

At a higher level, the steps for adding a new ability are below

1. Add the input action to the enum defined in `unrealgame5.h` (AKA `<YOUR_PROJECT_NAME>.h`)
2. Recompile in the editor or within the IDE of your choice
3. Restart the editor
4. Create a blueprint deriving from GAS_GameplayAbility
5. Define the `ActivateAbilitiy` event for this new blueprint, and assign an `Ability Input ID` within the `Details` panel
6. Create a new Animation Montage for the ability, if needed (and assign to play on `ActivateAbility` event)
7. Grant the abilitiy under the `Details` tab in the `Default Abilities` section while editing the `BP_ThirdPersonCharacter` blueprint
8. Add the input action to your project under `Edit->Input` if it doesn't already exist

#### Debugging

To see useful information on the GAS, enter play mode and hit the tilde (~) key to open a console. Then, type `showdebug abilitysystem`, and youll notice you can see your character stats even if there's no UI elements to represent them yet.

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642619759887.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642619759887.png)

# Retarget Skeleton Animations

[Mixamo to UE5](https://www.youtube.com/watch?v=0L0rH9nyVlU)

[Animation Retargeting UE5](https://www.youtube.com/watch?v=N7WdyAeeDrw)

<p class="callout warning">These systems have changed with the official release of UE5. See the links above for updated tutorials</p>


If you're not an animator, you might also get use out of sites like [Mixamo](https://www.mixamo.com/#/) that provide some free animations. To use these though, you need to retarget the animation for your skeleton in UE5. 

First, open the `Skeleton` asset for your character. For the UE4 Mannequin, it should be called something like `UE4_Mannequin_Skeleton`. Once it's open for editing, click `Retarget Manager` at the top of the screen.

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642638762853.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642638762853.png)

It will reveal a new side panel like the below. Select the the `Humanoid` option from the dropdown menu and it should automatically populate all the bones for your skeleton if you are using the UE4 mannequin. If you are not, you will probably have to manually make these assignments, as I did for the next skeleton in this section.

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642638801849.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642638801849.png)

Next, click the Save button in the above Set up Rig dialog, and save the rig someplace safe. 

Open the *other* `Skeleton` asset that was used for the animation you want to use, and again click the `Retarget Manager` button at the top of the screen. Then select the `Humanoid` option from the dropdown, and assign the bones to their respective members on the skeleton. 

When you're finished, it should look like the screenshot below. Click the Show Advanced button and do the same for as many bones as you can. Don't worry if you can't figure some of them out, you can still produce a good result most of the time. It might seem like overkill to assign each finger, but if you're doing a punching animation like I was it will look more like a slap if you don't.

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642639081006.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642639081006.png)

Click the Save button and storre this Rig asset somewhere. Then, **make sure you also save changes to both Skeleton assets**, and right click the animation you want to retarget. Select `Duplicate Anim Assets and Retarget` from the context menu as seen in the screenshot below.

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642639219141.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642639219141.png)

Select your skeleton on the left hand side and then set a name for the file and choose a location to save the retargeted animation. 

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642639280788.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642639280788.png)

If the Source and Target skeletons dont have similar poses in the above dialog, open the skeleton with the abnormal pose in the Retarget Manager and adjust it to match the more normal pose. Then, in the Set up Rig dialog select `Modify Pose->Use Current Pose` as seen in the screenshot below.

[![](https://knoats.com/uploads/images/gallery/2022-01/scaled-1680-/image-1642639451164.png)](https://knoats.com/uploads/images/gallery/2022-01/image-1642639451164.png)

Once you're happy with the poses of the skeletons, you can retarget the animation and see the results. If you aren't happy with the retargeted animation, try defining more bones in the Rig assets for your skeletons, or maybe select a different animation.

# New Page