Skip to content
Programming Updates

icon picker
#2 The Magical Journey

6/24/2023
zToday’s update focuses on the main coding challenge the past few months or so: the magic system.
image.png
Concept of CD Swap
(created and provided by )

The hardest part for me with this aspect was deciding on the user flow in which the player was able to call upon their magic.
After my concept artist came back with a very simple sketched-out idea of having the player being able to swap between different CDs, I endeavored to find a way to make this an impressionable part of the user flow.

Screenshot 2023-06-25 at 5.47.34 PM.png
For now, I’m pursuing a similar “magic” flow used in Persona 5 Strikers. In this fast-paced hack-n-slash game, players effectively freeze time and swap between the different “personas” they’ve tamed to use their unique abilities. I liked the idea of freezing time in these moments so that the player doesn’t feel too much pressure in reading through spell names and their descriptions.

The flow works as follows:
Player presses the “prime magic” button, which I’ve allocated to the “Q” key for now. This will do the following:
Freeze time.
Refocus the camera to be exactly centered on the player.
Change the player’s animation state to the “CD select” pose.
Pull up the list of spells for the currently hovered CD, known as the “Select UI”.
In the “Select UI”, the player can use do the following:
Use up and down inputs (”W” and “S” keys accordingly) to hover different spell “tracks” within a CD.
Use the left and right inputs (”A” and “D” keys accordingly) to swap between different CDs. Once they’ve selected a track, they are moved to the “Spell Aim UI”.
In “Spell Aim UI”, the player is dealing with aiming the spell they selected previously and confirming their spell placement. After confirming their spell placement, the player will move to the “Cast Spell” animation state and the game will resume.

Overall Implementation

The way I’ve mapped out the implementation isn’t anything amazing. There is a general SpellClass that holds properties of the spell. These properties include:
Name
Description
Type (AOE within range, Single-Target, Anchored AOE)
Damage/Heal amounts
Range
Buffs/Debuffs to apply
Duration
Essence Cost
There are more, but these are the most essential ones.
I plan to create libraries of SpellClass instances that will be packaged into a “CD”. These CDs will be attached to the player as a library script.
When a player calls upon the magic menus, the magic handler will freeze time and display menus that will show a list of the SpellClass instances it finds in the CDs.
When the player selects a spell, the magic system will have the player aim the spell according to its type. For instance, if the type is AOE within range, the player will aim a hitbox within a range and confirm the spell cast location. If it’s an anchored AOE, on the other hand, the player will aim a hitbox that swivels relative to the player’s location.
After the player confirms the spell placement, the magic system will create the spell on screen according to the SpellClass properties and unfreeze time.

ezgif-2-64827fb9ab.gif

Brain Freeze

One of the aspects of the magic system that was unexpectedly difficult was the time freeze feature. As some of the more Unity-savvy people may be aware, time can typically be frozen by using Time.timescale = 0. The problem was that while timescale was set to 0, the player’s animation state was unable to change to the proper “CD select” pose, since the animator operated with timescale. So I had to somehow make it such that when the player’s animation state was set to the “CD select pose”, it would ignore timescale and play the animation on its own time. Then, after the player returns to normal gameplay, make it so that the animator operated on timescale again.
So how did I solve this?
Thankfully, ChatGPT-4 came to the rescue by providing me with a script that it called UnscaledTimeAnimator. Essentially, from what I understood, this script forced the animator to continue progressing in time regardless of whether Time.timescale is set to 0 or not. This is what it looks like:
using UnityEngine;
[RequireComponent(typeof(Animator))]
public class UnscaledTimeAnimator : MonoBehaviour
{
private Animator animator;
private float previousTime;

private void Awake()
{
animator = GetComponent<Animator>();
}

private void Update()
{
var deltaTime = Time.realtimeSinceStartup - previousTime;
animator.Update(deltaTime);
previousTime = Time.realtimeSinceStartup;
}
}

By default, this script is disabled on the player character. When the player presses “Q” to activate the magic menus, however, the MagicHandler script attached to my player character will freeze time and also enable UnscaledTimeAnimator, making player animations immune to the time freeze.


Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.