Posted January 07, 2025 by Lochraleon
#rpgmaker #Unite #Unity
I am thrilled to announce that I came in 1st place in the RPG Maker Themed Game Jam #6: Journey to the Underworld - itch.io!
To start Devlog Part 2, I want to congratulate everyone who participated in the game jam. A huge thank you to the Theme Jam community. Playing your fantastic games and seeing your progress was both inspiring and motivating. Lastly, I want to give a big shoutout to everyone who checked out Northsong Rift, thank you!
It is recommended that you read Part 1 first: Making The Northsong Rift in RPG Maker Unite - Part 1 - The Northsong Rift by Lochraleon
Let’s revisit the Player and NPC setup I touched on in Part 1.
To control the player, I parented a camera to the Player GameObject. I used Unity’s Character Controller component and a custom Player Controller component for movement. Additionally, I added a child GameObject called Visuals, which included:
Overview of the Player GameObject with all components:
The Visuals GameObject showing the SpriteRenderer, Animator, SpriteLibrary, and SpriteResolver components:
You might notice that I am not just using Unity’s SpriteRenderer and Animator components. Adding the SpriteLibrary and SpriteResolver, lets me create multiple unique characters by simply dragging and dropping a new sprite sheet into a library. This setup allows me to reuse animations and configurations efficiently, somewhat similar to RPG Maker’s traditional approach but utilizing Unity’s built-in tools.
What’s even better? These libraries can be swapped at runtime, enabling dynamic sprite changes!
For more details on sprite swapping, check out Unity’s Sprite Swap | 2D Animation | 10.1.4 documentation.
The Animator uses Unity’s Animator Controller, which I configured for movement and in-battle animations.
Animator setup with blend trees and states for character movement and battles:
The “move” state (see in orange above) actually contains 2 blend trees, one for walking and one for idle animations. The blend trees automatically handle the animations for all 4 directions based on the player’s input. The “idleb” state contains the in-battle idle animation which branches off into in-battle attacks and casting states.
The PlayerAnimate script updates the Animator’s parameters based on player input.
This organized approach of using multiple blend trees within a single state prevents the Animator from becoming a tangled mess of individual animations and transitions.
Close-up of the “move” state, showing walk and idle blend trees:
Don’t forget I made this game for a jam, I needed a quick way to implement 3D battles. So don’t expect anything too elegant here lol!
The RMU handles all battle logic in an additive scene (Unity - Scripting API: SceneManagement.LoadSceneMode.Additive) called Battle, which runs on top of the SceneMap scene when a battle is activated. That means to integrate battles in 3D I really just needed to hide the 2D RMU character battle visuals in the Battle scene and add my own visuals in the existing 3D scene I initiated in Part 1. The Battle scene will continue to work as expected to display the battle UI and handle all the battle logic based on all the RMU spells, enemy stats, etc which was set up in the RMU editor.
The quick and easy way to hide the 2D battle visuals was to hide the RMU’s 2D battle visuals by setting the Battle Camera’s viewports to 0 and disabling the Canvas component on the Canvas GameObject (Yes, for some reason RMU uses a Canvas for battlers). DO NOT disable the Canvas UI GameObject’s Canvas (seen in the screenshot below), you need it for the built-in Battle UI which will still work without issue.
Unity editor showing quick and easy way to hide the 2D battlers:
I created a static C# class called CodeEvents, which serves as a mini event system. This allows any part of my game to react to specific triggers by subscribing to Actions like my onBattleAction C# Action.
In Part 1, I explained how my CodeEvents class also works as an RMU addon so I can leverage RMU commands from the RMU eventing system to send notifications and information to all of my unity scripts. Here’s an example of how I used onBattleAction action to bridge the RMU battle system with my 3D world:
PlayerController script showing the OnEnable and OnDisable methods.
This ensures that only active components listen to events, preventing null references or unexpected behavior. The += OnBattleAction above in the PlayerController line 64 means that when the OnBattleAction is invoked the PlayerController will call the OnBattleAction method its line 190 seen below.
Here’s how the PlayerController script reacts to battle messages from OnBattleAction :
You can customize this further. For example:
To add the enemy HP bar, I simply included it as part of the 3D model by adding a child Canvas GameObject with Render Mode set to World Space in the Canvas component. This ensures the health bar follows the enemy in the scene.
Enemy health bar setup with a world-space Canvas:
During battles, I dynamically update the health bar’s fill amount and text using the enemy’s current HP.