Brian Allanson’s Y2K DevLog:So this is the second log I have done for this project.
It is week four of our full time work on Y2K now.
Before I begin here is a random art render(not in engine):This week I have mostly closed myself off from the others in an attempt to finish the battle mode. I started re-programming the Battle system after we last showed it off at Pax East to allow it it be more expandable.
The demo we showed off at Pax was only a prototype, so I was able to cut corners in a few places but for a long term game project I wanted a more reliable system to build upon.
I have had three goals in mind when working on this system:(among several other goals…)
1. Do not rely on animation data to trigger battle events.
2. Make it easy to add enemies and player characters to the battle.
3. Make it awesome.
Goal #1.We are using unity’s mecanim system for the animations in this game.
In the prototype we used triggers at the end of animations to figure out if a character had finished animating and needed to end their turn.
Apart from being difficult/time consuming to setup, this method also required that I have animation for the characters before programming something. if I wanted a special animation for a certain skill, I needed to make that animation before I was able to begin programming the skill. Or if I wanted to make a new enemy, I had to set up all of the triggers on each of the imported animations. it wasn’t exactly fun.
This was annoying to set up for just the few characters that we had in the prototype, and I did not want to do it for every new enemy needed in the full game, so I came up with another plan…
After much thought on the matter I came up with my current setup:
GameObject Component: «(in this case, a character/enemy 3D model)
-Actor Class « component added to object
-AnimationFromAction Class « component added to object
The Actor Class holds the character stats and other important information. it also calls a function on the start of battle that registers the Actor to the Battle System Manager as an Actor on either the Hero or Enemy party.
The actor component in combination with the Animation from action component is all that is need to make an object work in battle.
AnimationFromAction lets me add one of two type of animations, and let’s me assign a variety of cameras to view that action from at random.
The animation style options are as follows:
-Mecanim
-StopMotion.
The first one being the unity animation system,
the second being a custom system of my own used for getting a more anime/hand animated look in my animations.(more on that topic another time perhaps)
Each animation also has info to enter under a settings pane in the editor for entering in custom animation timing info. it is this info that replaced the old method of adding a trigger to a models animation in mecanim.
I just need to enter the animation time length, and the Actor class uses that information to determine how long to wait between attacking, and showing an enemy being hurt/dodging.
If I wanted to I could add a completely static model and still have it attack and be attacked. I would just add the timing info and ignore the animation input field.
This is very nice for testing out new enemies.
Goal #2.The easiest thing in unity is also the hardest: getting a reference to an object.
Due to the nature of the Unity component system, you don’t create objects such as enemies or player characters through scripting. You attach components to Game Objects that make them behave in a certain way.
You cannot do :
Actor myActor= new Actor();
in c# if it inherits from Monobehavior( unity components mostly need to inherit from this class).
If you could you would already have a reference to that object, because you just made an instance of that class.
In Unity there is already an object of this class the moment you add the component to the Game Object.
These Monobehaviors allow a reference to be made by manually dragging and dropping a the Game Object into a public variable slot the editor creates for every serializable public field.
This is tempting, but it requires too much manual work to be useful for a game like this.
The battle needs to be able to call in enemies that are not in the battle on the start.
What I do for the battle mode is have these objects “register” themselves to the Battle System Manager as either Hero or Enemy types.
from there, I can get a list of any object that has been registered.
I can sort them by stats, such as speed, hp, or anything else I may need to use when scripting.
Goal #3.Making it awesome is the plan.
A lot of what makes a battle feel good in a turn based RPG is the timing.
Although many may feel that they wish some battles were faster, I have found that if something happens too fast, the player will miss something and feel confused.
If a message pops up that says that the player has taken 100 damage, and before the player can even read it, another show up saying that they have died, it results in confusion.
That little bit of delay is essential to a good battle feel.
I always found Golden Sun on the Game Boy Advance had great timing. The speed of the battle is left to the player to control by having them press the A button to advance through the text prompt.
Y2K uses over 300 lines of code in the attack function alone.
The speed is driven by an enumerator function which yields for a bit of time after each action takes place.
The general flow is like this:
(pseudo code)
Send Attack request (Current Actor, Target Actor)
Begin Attack.
Request for Current Player Attack animation to play.
Check if target is asleep:
if not
Roll random number for a dodge(insert stats of Current Actor and Target Actor):
if sleeping do not.
Check dodge result:
Dodge happened:
>Show missed target message.
Request for Target Actor dodge animation to play.
wait for a bit of time.
Dodge Failed:
Do damage Calculation(insert stats of Current Actor and Target Actor).
Random Chance to defend against the attack using QTE:
if failed to defend
target gets full blast of the attack.
if succeeds
Target cuts attack down by X% (depends on certain stats/Items)
>Show message indicating block/defence increase.
wait for a bit of time.
>Show message detailing damage.
if another target was selected( if the attack can be used on all enemies for example)
wait for a bit of time.
do attack on the target until all have been attempted.
——
It’s a bit more complex than that, but that is sort of how it goes.
Additional note of interest:Not wanting to hardcode text strings into the battle mode, and absolutely hating XML,
I made a simple data format for strings in battle.
It allows for custom reactions for specific characters in specific situations, as well as a generic fallback response if no specific response was written.
Some test strings screen captured for some reason:
note that alex is in first person in all of my current tests.
the @ symbol is where the name of the Actor is inserted.
The format is super easy:
[ThisIsAGroup]
This is a string;
this is another;
[Empty groups can serve as comments];
[Another.Group]
Yet another string is here…
and it won’t end without a semicolon;
Well the battle mode is not quite done yet, but I’ll come out hiding next week and check up on everyone else more closely.
Plus it’s sort of hard to hide from people that work in the same room as me
Until Next time,