Monday, April 4, 2016

Project Merfight DevLog 01

So as I've hinted in previous posts, I've started a new game!  I still don't have a title, but for now, I'm calling it Project Merfight.  This name is appropriate as it involves merfolk and fighting!  I haven't done a great job logging my games as they progress, so I want to improve upon that.
This first post is about the game itself, but also some of the developments I've made on the 3D front of the game.  To summarize Project Merfight is a tactics RPG with a battle system influenced by fighting games.  I've been working on the game for a while on and off while working on Battle High 2 A+ stuff; however from February till now, I've been trying to get a build ready for Indiecade.
What I have so far:



Essentially, during the month of February, I focused on the tactics aspect, mostly just getting the characters walking around the screen.  Then, I wanted to get the battle system down.  As I work on this, I do wonder, "Why don't I just make a fighting game?"  Well, this game's goal is to fill the void I feel fighting games have been leaving for me lately.
One is story.  I've said numerous times that fighting games are not good at telling stories.  The story ends up getting in the way or is often neglected or ignored.  Though I don't have a super deep story written at the moment, the goal is to attempt to deliver one.  Another void is single player content.  At the launch of Street Fighter 5, I felt myself wanting more.  Playing online crosses this border between fun and frustrating for me rather quickly, and I'd rather just spend my energy in other places, so instead of trying to improve my skill in a fighting game, I decided to try and use my knowledge and see if I could create an RPG experience that takes some of my favorite parts of fighting games and puts them in this space.
I'm using Unity3D, and though I like using the game engine a lot, there are always a few things I encounter when working in it; these items I wanted to document.

 

Using Mecanim with Equippable Attacks

 So right now, the flow of the game is you do the tactics part, moving in range of an enemy, and enter the attack phase, which looks similar to a 2.5D fighting game.  You perform a combo within the time limit to inflict damage.  What I want to do is that every time you use (or land) an attack, you gain experience points for that attack.  Once an attack levels up, that attack either gives you HP, Attack Strength, etc., but also, new attacks OR, similar to Namco X Capcom, the attacks change so you're forced to learn how you attacks connect more.
One technical issue with this, however, is that Unity's new animation system, Mecanim, really feels that it was built to assume that your animation state machine will never change.  There is the Animator Controller Override system -- which I do utilize -- but that feels more for like "Oh, I'm replacing this character's walk cycle with a different one but all the other states are the same."

 

Solution

So, what I'm doing is essentially I'm taking EVERY state in the game -- a lot I'm still missing sadly -- and putting them into one AnimatorController
 
This is only a small section of it too...
 I then have an AnimatorOverrideController that references this:

So happy Unity fills these in automatically...


Finally, before the fight segment of my game begins, I assign various state to animation pairs, instantiate a new AnimatorOverrideController, and replace the animations I need.  The main reason for this is that I'm not sure yet how many animations a single character will have and instead of having possibly 100s, I only reference the ones I need for that battle segment.  I've also created a custom data class that handles transitions -- as well as other info such as when attack spheres should be tracked.  Anyway, I'm happy with this solution for now -- until I test it on Xbox One and it breaks for some reason (which I'm hoping doesn't happen).

 

Swapping Equipment

So once I solved my animation issues, I had another issue related to equipment.  How was I going to equip different items to my characters?  I could do something where the items don't get shown, but I felt this was rather boring.  I want what the player equips to the characters to show up; I think it's important.  This is what I have so far:



Essentially there are several types of equipment I am dealing with:
  • Color swaps
  • Normal Meshes (or GameObjects)
  • Skinned Meshes
Color swapping was easy.  I just make a new material for one of the default items the character is wearing and swap them as needed.  Unskinned meshes and other game objects were simple too.  I have each bone of the character referenced, so I just reparent the item to a designated bone.  In the video, this is how I'm making the sash -- which his also using Dynamic Bone, an asset I recommend -- as well as the "Kelp Juice" attached to her hip.
The hardest part was skinned meshes.  Now, I could put every skinned mesh the character will use into one file, but I don't want to have to keep doing that and having to deal with a giant 3ds max and fbx file with a bunch of different parts.  When working though, I figured, "Oh, I'll just import the other skinned mesh, change the root bone, and it'll just work, right?"  Nope!  The problem is that upon import, the skinned bones and root are assigned to the Transforms included upon import.  Also, you need to make sure that upon import, the bones in the skinning data -- at least from 3DS Max -- go from the root bone and include parents of any bones.  It's almost safer to include the entire skeleton in the skinning data; Unity will remove all those with no influence upon import.  So after fighting with this for almost an hour, I figured that I need had to write something to transfer the bone data from my imported meshes to the current character's rig.  The following script does so:

[ExecuteInEditMode(), RequireComponent(typeof(SkinnedMeshRenderer))]
public class SkinRendererWeightTransfer : MonoBehaviour
{
        [SerializeField()]
        bool initialized = false;

        [SerializeField()]
        SkinnedMeshRenderer smr;

        public Transform newSkeletonRoot;

        [SerializeField()]
        string originalRoot = "";

        [SerializeField()]
        string[] originalBoneNames = null;

        void Awake()
        {
            initialized = false;
        }

        public void Update()
        {
            if (!initialized)
            {
                if (!smr)
                {
                    smr = GetComponent();
                    if (!smr)
                        return;
                }

                if (originalBoneNames == null || originalBoneNames.Length == 0)
                {
                    originalRoot = smr.rootBone.name;
                    originalBoneNames = new string[smr.bones.Length];
                    for (int i = 0; i < smr.bones.Length; i++)
                        originalBoneNames[i] = smr.bones[i].name;
                }

                if (newSkeletonRoot == null)
                    return;

                // Reassign bones
                if (newSkeletonRoot)
                {
                    Transform newRoot;
                    if (!StaticHelpers.FindChildByName(newSkeletonRoot, originalRoot, out newRoot))
                    {
                        Debug.LogError("No bone found for:  " + originalRoot);
                        return;
                    }

                        Transform[] newBones = new Transform[originalBoneNames.Length];
                    for (int i = 0; i < originalBoneNames.Length; i++)
                    {
                        if (!StaticHelpers.FindChildByName(newSkeletonRoot, originalBoneNames[i], out newBones[i]))
                        {
                            Debug.LogError("No bone found for:  " + originalBoneNames[i]);
                            return;
                        }
                    }

                    smr.bones = newBones;
                    smr.rootBone = newRoot;

                    initialized = true;
                    enabled = false;
                }
            }
        }
    }


 Probably not the best formatting for this blog, but essentially, I'm storing the original bone names and order, and then, upon equipping to the character, I get the new bone transforms.  (StaticHelpers is my own class).

Anyway, with this issues solved, I could start making equipment for my characters -- of course, writing details and what aspect of the characters they affect is an entirely different design mess.

Tons to Do!

I still have tons to do and I'm not even close to calling this game done.  I'm submitting a prototype more or less to IndieCade in the hopes that I can get some good feedback and maybe generate some interest.  These are still the biggest issues I'm having:
  • RPG Design.  I feel I have a decent grasp of fighting game design after all of my Battle High 2 A+ work; however, even just the pathing system took me awhile and I ended up finding a solution that was better than what I  had been doing and implementing that!  I'm just nervous that managing all of the data like how much each item cost, the stats they effect, etc., is going to prove not only difficult but boring and make me lose interest in the game.  And don't get me started on UI.
  • Title!  I still don't have an official title for this damn thing.  Project Merfight could work, but it sounds unfinished.  Essentially, the game takes place in a fantasy world that is inhabited by merfolk -- more like Rikuo from Darkstalkers than Ariel from the Little Mermaid.  The original idea was that it was going to be more similar to a World of Warcraft world in terms of aesthetics, but my friend got me thinking to change that a bit, and I thought about bioluminescence and have this 80's / neon yet underwater idea going through my head.
  • Content!  Rpgs -- well all games really -- have a ton of content.  Part of my goal recently was to go through the game and see how quickly I can make the content.  Having an idea of how to swap objects -- whether it's through texture or  meshes themselves -- helps, but still causes a bit of anxiety.
  • Tutorial -- though there are games that have done this similar, I want to try and make the game more about discover and experimentation instead of me telling the player how to do everything.  That being said, I'm still going to need to make a tutorial.  I want to take the Final Fantasy Tactics approach where it's optional, but I'm afraid if I do that I'll just neglect it.
  • Story.  I like writing, but I always lack confidence in my writing.  I also want the story to branch by level objects -- defeat Boss A goes this route versus defeating Boss B for example.  This is a lot of work, and in this first iteration, I will most likely be cutting.
Anyway, my goal is to get at least 2 levels (3 if you count a tutorial) before the late IndieCade deadline of May 15th.  I know the game will be far from what I want, but again, having the deadline is helping me focus and solve problems I'd probably ignore for months before actually tackling.  I'll try and post more about Project Merfight as I continue to work on it.  In the meantime, enjoy some gifs!



No comments:

Post a Comment