Timothy Marks Memoji

Timothy Marks

@imothee

Hi, I'm Tim, an engineer, founder, leader and hacker. Here you'll find my articles, apps, projects and open source stuff

Project Creation

Serfs Up 01 - Getting Started

Together let's build and create a Single Player, Third Person Adventure Game called Serfs Up, set in Medievil England where you are a Serf, particpating in a number of chores, tasks and quests to keep your town and castle upkept.

Serfs Up - Getting Started

If you're familiar with Unreal 5.1 or creating a new Project feel free to skip this very basic and non-comprehensive introduction to starting a new project.

Create a new project

Start by opening Unreal 5.1 and creating a new C++ ThirdPerson project. Make sure the Project Location and Project Name are setup.

Project Creationpng

Once the shaders and project finish compiling and loading you should land somewhere that looks like this.

Initial Projectpng

I won't go into the user interface or any of the workflow here, there's already a number of great tutorials out there, including [Understanding the Basics of Unreal](Understanding the Basics of Unreal Engine | Unreal Engine 5.1 Documentation).

I prefer to develop my C++ using Visual Studio but any IDE will work for following along.

Setting up Git/Gitignore

I'd recommend everyone use some kind of source control, even if just locally, to keep versions of your code and content checked in so you can easiily roll-back in case something breaks. There will be quite a few breakages, trust me.

Here's a copy of my .gitignore file

# Compiled Object files
*.slo
*.lo
*.o
*.obj

# Precompiled Headers
*.gch
*.pch

# Compiled Dynamic libraries
*.so
*.dylib
*.dll

# Fortran module files
*.mod

# Compiled Static libraries
*.lai
*.la
*.a
*.lib

# Executables
*.exe
*.out
*.app
*.ipa

# These project files can be generated by the engine
*.xcodeproj
*.xcworkspace
*.sln
*.suo
*.opensdf
*.sdf
*.VC.db
*.VC.opendb
.vscode

# Precompiled Assets
SourceArt/**/*.png
SourceArt/**/*.tga

# Binary Files
Binaries/*
Plugins/*/Binaries/*

# Builds
Build/*

# Whitelist PakBlacklist-<BuildConfiguration>.txt files
!Build/*/
Build/*/**
!Build/*/PakBlacklist*.txt

# Don't ignore icon files in Build
!Build/**/*.ico

# Built data for maps
*_BuiltData.uasset

# Configuration files generated by the Editor
Saved/*

# Compiled source files for the engine to use
Intermediate/*
Plugins/*/Intermediate/*

# Cache files for the editor to use
DerivedDataCache/*

# MacOS
.DS_Store

# Third Party Content
# Content/ThirdPartyLibraryName/*

See plus plus C++

Once you open the source files in your project, you'll see three main sets of files (.h and .cpp files). I won't explain how C++, header and CPP files work so I'll assume you already know that.

$yourgamename.h

This is the base h and cpp file that loads all your game modules, in this example it's named SerfsUp.h and SerfsUp.cpp.

You probably won't be doing too much in these files.

Game Mode

Game Mode and Game State in Unreal Engine | Unreal Engine 5.0 Documentation

The game mode is your core entrypoint to your game, controls what classes get loaded for each of the following (or a default of the base game engine version if not specified)

  • Default Pawn class
  • HUD class
  • PlayerController class
  • Game State class
  • Player State class
  • Spectator class

Character

The $yourgamenameCharacter.* files are the specific Character interface to the ThirdPerson model in the game. In this case, input devices/actions specific to the Character you possess as the player will be found there. Since we used the ThirdPerson template it will have the default WASD (movement) and Space (jump) input setup as well as mose movement/rotation of the controller.

You may have seen in some tutorials input handled in the PlayerController instead or as well.

Player Controllers in Unreal Engine | Unreal Engine 5.0 Documentation

The player controller is the interface between the Pawn/Character (your character) and you. In this case, input that is not specific to an individual character (ie. menu input, generic interaction input, accessing the inventory/character screen etc) should go here as it's common across all characters. In this way you can easily have inputs on a per character (pretend you're a horse or a tank vs a default human).

Source File Structure

There are quite a few ways to structure your C++ code files. You can have all the h and cpp files in a single directory (default) or start adding structure in.

You can split the private a public files so you have a structure like this

SerfsUp
    ├───Private
    │   ├───Abilities
    │   ├───Components
    │   ├───Game
    │   ├───Interactable
    │   ├───Libraries
    │   ├───Player
    │   └───UI
    └───Public
        ├───Abilities
        ├───Components
        ├───Game
        ├───Interactable
        ├───Interfaces
        ├───Libraries
        ├───Player
        └───UI

And including files looks like

#include "Player/SerfsUpCharacter.h"

Or you can bundle the files into grouped folders like so

SerfsUp
    ├───Abilities
    │   ├───Private
    │   ├───Public
    └───Components
        ├───Abilities
        ├───Components
.... etc

And including files looks like

#include "SerfsUp/Player/Public/SerfsUpCharacter.h"

Types File

One habit that I've leaned into heavily is defining all my Enums, Structs and DataTable Rows in a single top level Types file. This files should be named after your Game and is only a header file at the top of your folder

Source/SurfsUp/SurfsUpTypes.h
// This work is licensed under a Creative Commons Attribution 4.0 International License https://creativecommons.org/licenses/by/4.0/
include "Engine/DataTable.h"
#include "Misc/Guid.h"
#include "ThreadsTypes.generated.h"
#pragma once

/*
 * Enums
 */

UENUM()
enum class TrueFalse : uint8
{
  True,
  False
};

/*
 * Structs
 */
USTRUCT(BlueprintType)
struct FTruthy
{
  GENERATED_USTRUCT_BODY()

  UPROPERTY(EditAnywhere, BlueprintReadWrite)
  TrueFalse TruthyValue;
};

/*
 * DataTableRows
 */
USTRUCT(BlueprintType)
struct FTruthyValues : public FTableRowBase
{
  GENERATED_BODY()

  UPROPERTY(EditAnywhere, BlueprintReadWrite)
  FString Name;
  UPROPERTY(EditAnywhere, BlueprintReadWrite)
  FTruthy Truthy;
};

Appendix

Helpful links to set you up for success

December 26, 2022

0

🕛 5

© 2022 - 2023, Built by @imothee