Home

2024

Worklog

LETSGO Game

Unreal C++
💥

Unreal C++

Tags
UnrealResourceWIP
Owner
J
Justin Nearing
🎶
This is part of a ongoing series called Building A Music EngineBuilding A Music Engine

It documents the process of me smashing my head against the keyboard to build a game called LETSGOLETSGO

It’s gotten long enough to break into several sections:

Pain: the True Development Environment

Every other time I open my Unreal project, I get the following error:

image

PAIN

If I click Yes I get:

image

PAIN

When I successfully load into the project, and open Visual Studio, I see the following:

image

The red lines mean PAIN.

I found I can get rid of the missing modules error if I delete the Source folder.

This is not a solution. This is PAIN

But it is a good example of the necessity of version control!

💡
Actually the missing module thing only happens if I have Always load last project on startup selected on the Unreal Editor startup screen. So like, don’t click that? I feel you need to play the Curb Your Enthusiasm theme song while working with Unreal sometimes.

I found I could work around the Visual Studio errors by simply not using Visual Studio.

That’s right: I am now a radicalized JetBrains convert and fully embracing the Rider train.

We’ll see if I’m still converted when my 30 day free trial ends…
We’ll see if I’m still converted when my 30 day free trial ends…

You will note the lack of squiggly red lines.

Unreal C++ Fundamental Types

So there’s C++, and then there is Unreal C++

// STRINGS
std::string foo = ""; // Not a thing in Unreal
FString foo = "bar"; // Unreal has implemented its own string type 

foo + "wow"; // Concatenation, "barwow"
foo.Len(); // char length, 6
foo.IsEmpty(); // bool, false
foo += "wow"; // I assume `+` returns new string, += appends existing string: "barwowwow" 
foo.Equals("wow"); // bool, false
foo.Left(3); // get substring from start of string to index. "bar"
foo.Find("wow"); // Return index of first found substring "wow" = 3
foo.RemoveAt(3); // Removes all characters at index = "bar" 

// ARRAYS
int myArray[5]; // Oh no no 
TArray<int32> myArray; // Unreal has customized dynamic arrays to be used

myArray.Add(10); // Has Add function to append to end of array
myArray.Num(); // Returns 1 - number of elements in the array
myArray.RemoveAt(0); // Remove by index 
myArray.Empty(); // Remove all contents

I’m actually super glad to see this. I’ve stayed away from C++ in the past because how manual everything is.

I’m coming from a world where node/python/ruby just lets you add things to other stuff and let you deal with the consequences of your own lack of skill/clear design/time.

The C++ requirement to manually do the simplest things has been the highest prevention cost for me to learn it.

Anyways, cool I have some substring functions.

And dynamic arrays? Bruh.

Yo Dawg I Heard You Like Enums

Consider the following:

UENUM(BlueprintType)
enum EMusicScaleSteps : uint8 {
	REST = 0, // Only here because compiler complains that it needs a 0th enum option
	HALF = 1,
	WHOLE = 2,
};

UENUM is a macro that does a bunch of fancy-work to reflect an enum into Unreal. Without it we won’t see the enum in Unreal blueprints.

💡
Here’s a great first goal for learning Unreal C++:
Make anything appear in blueprints
image

Compiler Highlander

There can only be one compiler. The true compiler is the one that makes both the IDE and Unreal happy that the thing has been compiled.

Unreal’s Live Coding feature appears to be the one true compiler:

image

When you see this Live Coding thing running, building the project seems to work reliably.

To make Live Coding appear reliably, update Editor PreferencesLive CodingEnable Live Coding

image
💡
BTW, this entire section is brought to you by PAIN I did something to my project and now the Live Coding thing will only appear if I press Ctrl + Alt + F11 in Unreal. Seriously it was like days of just getting IDE and Unreal to agree with each other.

For me, I press Build in Rider, and log starts spewing in the Live Coding window:

image

There’s also log spew in Rider via UnrealLink, but that’s just the Unreal Editor Log.

Yo Theres Already EMusicalNoteName

Now this is the definition of excellent documentation:

That’s sarcasm by the way.

Cool. Cool cool cool.

But it does link to the AudioMixer engine, which is probably going to be important if someone was to be, I dunno, 🎵Designing Sound?

So the next step here is start stepping through the AudioMixer module documentation.

Quick parse through to see what random things get my attention

Like yo there’s a USynthSound :

In it there is OnGeneratePCMAudio

Heres Jippities take:

image

Big brain thought here is to wonder if I can connect Musio directly to Unreal.

Because then we’re cooking with the whole damn orchestra.

Cooking With Quartz: Some Actually Decent Unreal Docs?

Issues with Accurate Timing and Latency in Audio Rendering? Now this is some real shit.

Quartz provides a way of scheduling an audio call mid-buffer instead of having to delay the audio render until the beginning of the next buffer. This has many applications — from creating dynamic music systems, to controlling the playback of rhythmic and timing-dependent sounds such as sub-machine gunfire.

We’ve largely glossed over rhythm so far, but controlling when a note is played is just as important as what note to play.

Probably more important honestly.

Playing it on the grid:

When the game thread calls PlayQuantized(), it requests that the sound be played on a given quantization boundary (such as the next quarter note), as calculated to the nearest audio output sample on the audio render thread.

Coming from a DAW world like Ableton, this makes a ton of sense. The majority of music made today is played “on the grid”- each notes placed precisely on a beat.

“Real music”, played by humans, are rarely ever precisely on the beat- so much so that playing “off-grid” can give your music a more “human feel”.

That we have quantization in Unreal via the Quartz Music System means we can stand on the shoulders of giants here- laying down four-on-the-floor with a kick drum on should be a (relative) walk in the park.

Terms

Quartz Subsystem

  • Create, Get a Clock
  • Check if Clock exists
  • Latency information

Quartz Clock

  • Triggers sounds
  • Created with Quartz Subsystem
  • Exposed in Blueprints via Clock Handles

Clock Handle

  • Contains a Metronome
  • Exposed in Blueprints

Metronome

  • The actual audio render thread object
  • Schedules audio commands
  • Has understanding of BPM, time signatures, etc.

Getting Quartz into LETSGO

  • When a Music Platform is stepped on, schedule the note to play using a Quartz Clock.
  • In theory this will make the sound play on the grid.
  • This means that regardless of when the physical object is hit, it will play in time.
  • I think this will be the next System to build. Buuut that is after we finish the first requirements of Music Theory Engine - Spawn music platforms choosing notes of a real scale.

⌨️Actually Writing Some Damn Code