Base Project Setup

From Augmotic Library

Prerequisites

Skill Level: Beginner
Version: 5.1
If this is your first time opening Unreal you may want to check out the official startup tutorials first.

Overview

This tutorial will cover setting up the bare-bones foundation for your project. The methods and ideology you will see are to be used as a rough guideline and not to be taken as gospel.

Although there are some C++ sections, it is up to you after the Tutorial how much you want to use going forward.
Every project has unique needs and challenges. Trying to shoehorn the wrong things will cause short- and long-term issues.
The best approach is to follow along and adjust it to your needs, don't be afraid to experiment; that is what version control is for :)

At the end of the tutorial, you will have an expandable starting point to begin working on your project. It is possible to take an existing project and change to this setup. However, having to reparent classes and dealing with the refactoring is tedious. Setting up in this manner at the start of the project will help minimize future refactors.

There will be an example project with a link to the GitHub Repo at the end of the tutorial.

C++ Will Not Hurt You... Much

Alright, before you grab the pitchfork, hear me out.

There are many subjective things in programming, which depend on the situation. Using the "correct" tool for a job, even if it's uncomfortable, will always net better results in the long run. I say "correct" with a grain of salt because there is always a case for an exception. The art is knowing when those situations arise and what tool to use where.

Using C++ in Unreal is no exception to this rule. However, this means using it where it makes sense. Ultimately you want to mix the usage of Blueprints and C++ for the best of both worlds. The topic of when to use what is highly dependent on many factors, other than a couple of straightforward cases, becomes something you have to get a feel for over time. Alex Forsythe has covered this very well in a YouTube Video.

So, follow this tutorial even if you have zero plans to touch C++. When the need for C++ arises, you will have a solid starting point to ease into it and minimize the amount of manual setup and refactoring. The reasoning will be explained as we get into the required sections.

Project Creation

We begin by launching your chosen version of Unreal from the Epic Launcher. Select the "Games" tab on the left, update the Project Location and Name, configure the project Defaults, and press Create.

The most important setting is to start with C++. Others can be adjusted to your needs.

Content from the other templates can be added to the project later. Selecting C++ here does not affect the available types. You are still able to add both Blueprints and C++ flavors.

The C++ option will cause the project to generate some initial files, but most importantly, it performs some setup for you at the start. If you were to choose blueprints and want to add C++ later, a few manual non-obvious steps are required to avoid build issues.

Once the project has been built and the editor has opened, we know everything was successful.
You now want to close the editor and open the project's solution file directly using your preferred IDE.
If this is your first time using C++, Visual Studio will be fine. Most screenshots will be from Jetbrains Rider, but Visual Studio has the same capabilities to do what is needed for this Tutorial.

After the project opens, it will do some initial parsing and setup. This may take some time, but it only has to happen once. The Run button will be available when it has parsed enough to start the editor.

Running from an IDE will start the Editor. Doing this from here allows debugging, troubleshooting for engine crashes, and proper compiling when there are changes to Header files.

Here are the run buttons from both Visual Studio and Rider.

Now that you have a running Editor again, it's time to start adding content.

Helper Folders

Create two folders in your Content directory. "_Sandbox" and "_Temp"

These folders will help contain some of the inevitable messiness that comes with testing and asset management. The underscore prefix is handy to bring them to the top of the list and to make it stand out as a unique type of folder.

Sandbox is helpful to contain experimental assets/maps/blueprints that have yet to make it into permanent use. Such as a new enemy that is being prototyped and will be moved into a more concrete folder later with other enemies. Doing so helps you better track assets, so something that didn't cut it doesn't sit in your standard folders for eternity after forgetting to delete it.

Temp works as a catch-all for things that need to be eventually removed. Such as a quickly imported model for visualization or an imported character used as a code reference.

There is no hard rule on how you use either of these folders. These are just some ways that have helped contain the asset folder monster.

Unreal Content

At this point, you can now add whichever Content Packs you want.
You are free to use Blueprints or C++ versions. The only requirement is that you add one; it will be needed later. For the Tutorial, Thirdperson Blueprints will be used.


Why C++?

I am putting this here as a disclaimer, what you are about to do can be done in Blueprints without using C++. However, I plead with you to step out of your comfort zone and chip away at learning the code side. It is daunting, and you will get frustrated at times, but when it finally clicks, it feels glorious to do certain things in a much more straightforward and cleaner way.

When it comes to implementing core systems, you usually want to do it on the C++ side so you can easily access it across the entire engine. There are also functionality bits that don't have a blueprint node equivalent. 

Even if you have no intentions to use C++, it is worth following through with the tutorial to have a base structure to accommodate the few times you have no choice but to use a little bit of C++.

Alright, time for the explanation that was promised. This answer will be based on the particular use case of the following sections.

Two layers of abstracted classes will be created in C++, a "Library" layer and a "Common" layer.

We will be using the HUD class as an example. Since this will be long-winded, here is a diagram to help glue everything together.

AUGHUD

In practically every project, you will have some form of a default cursor. You find you start repeating the same code in all of your projects to spawn a widget on start-up and set it to the default.

This is where you would make your "Library" version of the HUD class. We have created "AUGHUD" from the base "HUD" class. This implements the logic to set a default cursor on HUD spawn and can change back to it later. There are also some Mouse Cursor handling functions for Showing and Hiding the Cursor.

CommonHUD

So now you need another type of cursor to use when the inventory screen is open. The inventory system is a core component for gameplay, and you will use it for all game modes.

Here is where the "Common" layer of HUD shines. We create "CommonHUD" from "AUGHUD" and add the creation and handling of our Inventory Cursor.

Blueprint Layers

Now that you have added some core functionality, all your mode-specific HUDs can be Blueprints created from "CommonHUD." You may have a StoryHUD with an objective tracker and a TimeAttackHUD that shows a score and timer. Since you have a centralized parent class, you get to keep the Cursor functions without a need to replicate code each time.

Y Tho

You are probably asking, "But Why?". This lends an unfortunate response: "you will probably need it, but you might not."

The goal is to set up some standard use-case abstraction layers you usually use. It is better to do a pre-emptive setup than go back and reparent a bunch of blueprints. However, you don't want to go crazy with it and create five empty layers before you get to any logic.

By doing it in C++, you get easy access to these core functions from both sides. Compare that to writing a bunch of core features in all blueprint classes and using a bunch of ClassFinder or manually setting property types in the editor when you have to use C++.

As a disclaimer, it would be best if you did not try to shoehorn all functionality into these classes. There are cases where simple scripts work better in a Blueprint and others where a complex core feature should be implemented on the C++ side.

Blueprints can churn out multiple iterations before you can finish editing and compiling a C++ script. So feel free to prototype in a blueprint and move it to one of the C++ classes when it's solidified.

Library Layer

Now that everyone is on the same page, we can start the implementation.

We can start by creating the Library version of some commonly used classes. If you have already followed this Tutorial before and are using it as a refresher, you can pull in your current ones instead of creating them anew.

Let's start with the Character class. Once finished, you can work your way through the rest of the list.

Activate the "New C++ Class" dialogue using the Tools menu at the top of the Editor window.

Select Character and press Next.

Name your class and add "/Library" to the end of Path to place it in its folder.
You can choose whichever prefix you want for your library classes, AUG being short for Augmotic worked well for us.
If you have previously pressed either Public or Private buttons and are getting an extra folder in Path, backspacing to remove it will turn the buttons back off. Once everything is set, press Create.

So such file or directory Error
If you happen to get an error for "So such file or directory" this can be fixed by adding the include path in the (ProjectName).Build.cs file. You will need to replace "BaseProject" with your project name.
You must close the Editor and rerun it to verify the fix.

Create the remaining classes
It would be best if you used the same prefix the character class was made with to keep everything consistent.

Library Unreal
(Prefix)Character Character
(Prefix)GameMode GameModeBase
(Prefix)GameState GameStateBase
(Prefix)HUD HUD
(Prefix)PlayerController PlayerController
(Prefix)PlayerState PlayerState

Mark new classes as Abstract
Once all classes have been created, they need to be marked as "Abstract."
This will require you to create another C++ class or Blueprint from these classes to use it directly. It also prevents a class from appearing as an option in most editor menus and crowding out your actual Blueprints.

Common Layer

We will now create the classes for the next layer of abstraction, our Common Layer.

The process is almost the same, except you will use the previously created classes as your parent class and place them in the "Common" folder.

Create Class
Right-click your library class and use "Create C++ class derived from (class name)."

Class Choices
From here, the classes you create for Common will depend on your project. The main goal is to have a parent C++ class to derive from that will hold shared functionality when needed.

For example, if you have multiple units that would share similar functions, such as in an RTS, a CommonUnit class that all units derive from would work well.

Keep in mind to avoid getting caught up too much trying to form a rigid class structure preemptively. This is here to create a basic design and can be split up if needed.

PlayerCharacter
In this case, CommonPlayerCharacter will primarily serve as the C++ backing side of a future PlayerCharacter blueprint.

Parent Class
The new class should now be derived from our AUGCharacter class and marked Abstract.

Other Classes
You can now create the other Common classes. Here are a few that will usually be of use.

Common Library
CommonPlayerCharacter (Prefix)Character
CommonGameMode (Prefix)GameMode
CommonGameState (Prefix)GameState
CommonHUD (Prefix)HUD
CommonPlayerController (Prefix)PlayerController
CommonPlayerState (Prefix)PlayerState


Close And Rerun The Editor
After creating and marking the remaining classes as Abstract, close the editor and rerun it. This will force a compilation of the new classes and make them correctly accessible from the editor.

Sometimes the live coding will work after a new C++ class is created, but it is better to close the editor during Header file changes so the build system can properly reference files.

Blueprints Time!

Okay, now we can use blueprints :)

We will now create a few blueprints that come in handy for sandboxing. After these, you can begin working on your project with the hopefully helpful to you base structure we just set up.

Sandbox Blueprints
Some initial sandbox classes allow clean prototyping without the risk of dirtying up the main project folders.

Create the following Blueprints in your "_Sandbox" folder.

Blueprint Common
SandboxGameMode CommonGameMode
SandboxPlayerCharacter CommonPlayerCharacter
SandboxPlayerController CommonPlayerController

Sandbox Level
Creating a designated level to prototype and lay waste to is also very helpful. This prevents missing some old actors in the level or messing up any progress towards an actual level.

Create a new Level with your chosen type and save it in a new levels folder in "_Sandbox".
(_Sandbox/Levels/...)

Go Make Stuff

You are now free to begin working on your project!

From here, you have a good starting foundation of abstraction to prototype and implement your core features.

Feel free to experiment with and evolve the Common classes to best suit your project. There is never a one size fits all solution to how a project is laid out, so use these as a guideline and example. Only you will know what it needs.

A good starting point is to move what functionality you need from the Unreal Content Packs into your Sandbox classes. Once you have prototyped and solidified some features, consider moving some stuff into your common classes.

If you want to avoid touching the C++ side or have too many issues, feel free to use Blueprint versions of your Common classes instead.

A middle-ground compromise could be to make an extra layer after your C++ Common class using Blueprints and have that act as your starting point for your other Blueprint classes.

So the chain of classes would be something like this: Character -> AUGCharacter -> CommonPlayerCharacter -> PlayerCharacterBase -> SandboxPlayerCharacter

(PlayerCharacterBase and onward would be Blueprints)

Example

This example is barebones but demonstrates the Library and Common file structures. It has the Third Person template integrated into the Common and Sandbox Characters.

You are free to use it however you see fit.
Download it from the GitHub Repo.

To keep the size at a minimum the project will need to be built again and the .sln generated.

  • Open the .uproject file - (Builds the project and opens the editor. This may take some time.)
  • Tools -> Generate Visual Studio Project - (Creates a new .sln file.)


Feedback

We are a firm believer in iteration and making things better. Please let us know if you have suggestions or feedback.

Feel free to stop by our Discord and let us know.