Home

2024

Worklog

LETSGO Game

Unreal Blueprints to C++
➡️

Unreal Blueprints to C++

Tags
UnrealC++BlueprintsDesign
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:

After wasting too much time Suffering: The First Two Weeks Of Zig, I’ve decided to just start working on LETSGOLETSGO again.

My initial goal has been to do some light refactor work, moving some of the more painful-to-look-at blueprint spaghetti into C++ spaghetti.

Here’s an instance of “blueprint spaghetti”:

image

The details don’t really matter, but it basically boils down to adding a bunch of stuff into some arrays before using those arrays.

While I was making this, I felt bad.

It looks bad.

It is bad.

But, it had the lowest mental overhead to get to the goal.

The goal was to make thing work, not make thing beautiful.

But now it is working, and now I’m willing to commit it to code:

image

And now that blueprint looks much better:

image

Least Path of Resistance

Optimizing for the least mental overhead is incredibly effective.

Like most humans, I am easily confused, distracted, and overwhelmed.

Doing something you know is stupid, but will work, is the optimal path during the prototype stage of a project.

Game jams, first time using a set of tools, not having a totally clear idea of how to accomplish a goal- a “stupid but works” approach can give you much more real progress than waiting for an optimal solution.

Of course, the result is garbage. Garbage that works, but garbage.

Which is why moving into a second phase of refactor/cleanup/etc. is necessary as well.

But even in the case of refactoring and clean-up, having a clear goal is important.

I’ve gotten myself into trouble doing some massive refactor that resulted in different, but equally complicated code, that ended up just having me solve the exact same problem over again in a different way.

The goal here is pretty simple though:

  • Get back into the codebase with some light refactor work.
  • Strengthen my Unreal C++ muscle by moving logic from blueprints to code.
  • Lay the groundwork for the next feature.

Specifically the task is to implement Multiple Spawned Music Platforms

Currently in LETSGOLETSGO a AudioPlatform is triggered every X seconds in front of the player. You step on it, it plays the associated sound.

This work was captured in Music Theory Engine

What I want now is to present 3 platforms in a line in front of the player, each with a different note, and wait for the player to step on one of them.

I want to store that note, then build musical scales based off that initial choice.

That requires a bunch of refactor work, starting with the blueprint refactor shown above.

A Thing Called SpawnPool

The AudioPlatform spawner contains a component called SpawnPool

SpawnPool manages which musical Note the AudioPlatform will use.

The initial implementation had this SpawnPool thing generating all the notes of all the scales, then add it to a Notes array- hence the “Generate All Scales” blueprint / code.

The platform spawner would call a Pop Next Note function that will remove/return the first index of the Notes array.

That pop function is used when a new AudioPlatform is spawned. (Hence the name SpawnPool - a collection of notes to use when spawning an AudioPlatform.)

Required Changes

  • Modify “Generate All Notes” functionality just be one way to initialize a SpawnPool.
  • Add a “Select n random notes” functionality
  • The AudioPlatformSpawner needs functionality to spawn multiple platforms as a logical set.

Additionally, I need something to manage the state holding the order of events:

  • Create a set of platforms to set the Tonic (what musical key is this song going to be in?)
  • Create a set of platforms to set the nature of the 3rd ( major/minor - dependent on a Tonic)
  • Create a set of platforms to set the mode of the scale (suspended 2nd/4th/6th/etc - dependent on Tonic/3rd)

This makes me think that SpawnPool has overloaded functionality and is poorly named.

The idea I had was it to be a NoteContainer, and at the time it made sense to put the construction of the Notes in that NoteContainer.

I think what I want is to pull note construction out of the NoteContainer altogether

Tasks

Rename SpawnPoolNoteContainer
Update NoteContainer
  • Should be purely functional- It is set with an array of Notes at init time, it does not set anything itself.
  • It should be only concerned with the functionality of setting and getting Notes at runtime.
Probably want to pull this entire thing into code.

This is all complete as of:

That only took a few hours, which was a nice win from the hours of fruitless Zig development I smashed my head against.

Now I just have to draw the rest of the owl.

🦉
In the next chapter, I take the complete opposite approach from the one described in this article. Here I attempt to do “good” software design for how I want the core gameplay loop to function:

Designing The Core Gameplay LoopDesigning The Core Gameplay Loop