Thursday, December 24, 2015

Battle System Updates (Part Two)

One of the main problems with the previous battle system (henceforth, lovingly referred to as BS-1) was that, while the system itself functioned properly, the presentation was somewhat lacking. In this post, I'm going to talk a little about the specific issues with it as well as the steps we went through to correct those issues. Afterwards, there will be a few screenshots showing the improvements. If this sounds boring, that's because it actually is. Anyhow, ze issues, in order of severity:


  1. Character panels were arranged horizontally, rather than vertically. Since each panel requires roughly 200 pixels to display all of the information, this effectively locks out people with certain screen resolutions. Granted, the panels did scale based on the chosen resolution, but this still works out to allowing something like six total combatants on screen for lower screen widths. This is why, during the demo, there were no situations in which enemy groups greater than three would be encountered. This would obviously cause issues, too, if (or when) we decide to bump the minimum party up to four.
  2. Vertical space was wasted by needing to show the actual charge counters of any currently charging skills. To recap, skills in Bevontule require a certain number of 'turns' (or charges) before they can execute. This was shown, in battle, with small...uh.. orbs that gradually filled as combat turns proceeded. This, of course, is a necessary thing to show, but surely, there is a more intuitive way to depict this... (spoiler: there is)
  3. The order of turns was completely fixed and determined at the beginning of battle based on each character's speed attribute. This meant that any skills that modified a character's speed attribute in combat would have no effect. This is an obvious problem since it would exclude any haste-type buffs or slowing debuffs.
  4. It was extremely difficult to follow the flow of battle--even though there were rules for which character would act next (for instance, if two characters reach full charge on the same turn, the character that entered the skill first would act, aka, in a left-to-right order). From the perspective of the player though, the currently acting character would seem to shift around without any explicit reasoning to it. 
  5. Minor complaint, but if a character performed an action other than a skill (such as moving or attacking), this was not reflected anywhere in the status panel. This was a surprisingly difficult thing to fix with the old system.
  6. Another minor complaint, is that the code was too tightly coupled with the battle system itself. I mean, yeah, it only is visible during battle, but that's no real excuse. 
  7. Shifting the status panels relied on Unity's animation system. I have learned to never again trust this son of a bitch. I could write an entire blog post about how incredibly flawed some aspects of this are, but that would be extremely boring (but very therapeutic.) Going forward, ideally, we would not rely on this system to handle the rearranging of combatant panels.

While this doesn't really seem like a large number of problems, fixing each of them required a pretty stupid amount of work. So, here is another list of the fixes that were applied:

  1. Rearrange character panels vertically on the right side of the screen, while reducing the overall vertical size of an individual panel. The horizontal size, ideally, would remain the same, but we could get away with increasing this if necessary.
  2. Remove the orbs and rely instead on a more intuitive method to show the currently charging skills as well as the turn(s) at which they would execute. This was the truly major overhaul and required rewriting massive portions of the battle system. Essentially, the idea is to actually slot in characters based on the total charge required by any particular skill. Each turn, every character is shifted upwards, thus replacing the system of updating the orb graphics. When a character reaches the top of the turn order, they would act. Contrast this with every character remaining in a fixed location and shifting the entire character bar, as was done previously. In practice, this sounds extremely straightforward, but like everything, the devil is in the details. This system would also need to account for skills that require zero charge (instants, much like attacking or using an item) and would also need to account for skills that require a charge higher than the number of currently displayed character panels, which is dependent on the number of currently 'alive' combatants. Furthermore, it would need to preserve the relative turn order for non-skill-charging characters. One way to think of it is that characters that are not charging skills are actually sorted based on their accumulated speed (more on that later), but characters that are charging skills are slotted in at very specific indices within the turn order list. To add a little more confusion, it also needs to account for character speeds. For example, what I said earlier about every character shifting up by one slot every turn is actually wrong and I am a lying bastard. It turns out that, if a character has sufficiently high speed, it can slot in ahead of 'slower' characters. Still, all of this must still happen without the turn order of actual charging skills being affected. Thus, if a skill has a charge of 1 turn, it cannot possibly take more than one turn to act (the exception being, if a 1 turn skill is already slotted ahead of it). Add all this together and you have a pretty big mess, which unfortunately, despite repeated attempts (and other blasphemous statements), took quite a while to untangle.
  3. To elaborate further on this, speed now correctly factors into the turn order. Ignoring any character skill charging, the idea is pretty basic. Every character has a speed stat (a persistent character attribute) and an accumulated speed stat (only used during battle). At the beginning of battle, every character's accumulated speed is set to its actual speed stat, which is then sorted in descending order to generate the initial turn ordering. When a character completes his turn, the accumulated speed is reset to zero, which essentially forces them to the end of the turn order when it is resorted. Otherwise, the accumulated speed attribute is incremented by the character's speed attribute. With this system in place, characters can then overtake other characters if their speed is sufficiently high. An issue arises naturally from this... since it is no longer guaranteed that a character will only move one slot, it becomes necessary to somehow communicate the next turn ordering to the player, ideally, without using additional space. Which leads into...
  4. The next turn ordering is actually shown when a character attempts to perform an action that would end his or her turn, but before the character has actually confirmed the action. To recap, certain actions can end turns, whereas other ones allow still other actions to be performed in the same turn. Here is a list of actions that a character could take in a single turn:
    1. Moving, then attacking
    2. Attacking, then moving
    3. Moving, then using an item
    4. Using an item, then moving
    5. Moving, then using a skill of any charge
    6. Using a skill with a charge of zero (an instant), then moving
    7. Ending the turn explicitly (now requires a confirmation press to allow the next turn order to be displayed. Also, this is probably a good thing anyhow to prevent a player from making a mistake)
  5. Fixed. Moving on... 
  6. Also fixed (for the most part). Just to elaborate, previously, the character bar ran its own update loop independent of the BattleManager (main class for handling battle-related tasks, go figure). This was a gd nightmare. Never again. This also means that the character bar is not updated each frame as it was before (ew), but now is only updated when specific conditions are met.
  7. I won't lie, I tried to implement the shifting (actual physical positioning of panels) via Animations, despite being burned by it in the past. This time, I vowed, it would be different and I would tame this stupid bastard. I didn't. First issue: you CANNOT animate integer values. Why the shit not. Second issue: animation updates do not seem to occur in tandem with any reasonable update loop (wtf?) Third issue: animations did not seem to honor the ending keyframe whatsoever. For instance, I want a value to go from 100 to 0 over the course of 1 second. Lo and behold, at the end of that second, the value would be 3 or some such stupid shit. Why, god, why. So yeah... this has all been fixed. 
So, if you were somehow able to get through that massive wall of text, here are a few (by few, I mean 12) images that show off the new and improved battle system (I am calling this iteration BS-2-Fast-2-Furious.) 


First picture: Moroch is the currently acting character. The new turn order bar is displayed on the right.


Second picture: Moroch chooses to use Siphon (for whatever reason). Note that the turn bar updates to show Moroch's new position in the list before the action is confirmed. Since it has a charge of 3, he gets slotted in at, you guessed it, position 3. Keep in mind that these are 0-based indices, which is necessary because a skill with a charge of 1 would then be slotted in at the very top, which is something we want to avoid. (Also ignore the obscenely and unnecessarily long information bar)


Third picture: Apolith is the currently acting character. Note that the new turn order was 'locked in' once Moroch confirmed the command. Currently charging skills are indicated with a blueish tint. Additionally, the name of the skill appears below his panel.


Fourth picture: Since Apolith's judgment is somewhat clouded due to all of the steroids he uses, he contemplates using Resolve for a moment. Again, the next turn order is shown, and Apolith is slotted in an index 1, whereas Moroch has moved up to index 2.


Fifth picture: ...But since he's all roided out and shit, he decides that violence is the only acceptable course of action, so he chooses to Bludgeon the nice little plant instead. Charge time of 3, index 3. Checks out. Something interesting to note: If he had a skill that had a charge time of 2, he would still be slotted in at the same spot as if he had chosen Bludgeon. This is because characters cannot 'interrupt' other characters if they are slotted in at the same position. Thus, the person who selects a skill first still gets to act first. In this case, then, a charge time of 2 and a charge time of 3 have the same result. 


Sixth picture: Not to be outdone by Apolith's blatant disregard for the sanctity of life, Bodom chooses Backstab. It has a charge of 3, and gets slotted in at the end. Note that in this particular case, a skill with a charge of 1, 2 AND 3 would produce the same result. Interestingly, this opens up the possibility that a system could be added where skills can be 'overcharged'. 


Seventh picture: Skipping ahead a little, plant bro lashes out at Apolith and breaks his neck, by the looks of it, but still only does a small amount of damage, so he's fine. You can't tell from the picture really, but Apolith's character panel is flashing red to indicate that he is currently taking damage. Also note that since an attack without movement doesn't end a character's turn, the 'next' turn order is not yet shown. 


Eighth picture: Plant bro decides to end his turn because he's a plant and can't move. JK, he can totally move, but it would screw everything up. Note that he has been shifted to the end of the turn order upon selecting End Turn.


Ninth picture: Moroch uses Siphon. Even though it is not explicitly shown, any character who performs a skill is automatically slotted at the end of the turn order after the skill executes (aka, his accumulated speed is set to zero)


Tenth picture: Apolith uses Bludgeon. 


Eleventh picture: Bodom uses Backstab. Don't look at Apolith's face. He uh... had an accident.



Twelfth picture: Just like World War I, everyone decides to stop fighting for a bit and put aside their differences. It is a magical time indeed, when Humans, Onichians, Rootsouls, birds and plants can all come together to appreciate the joy of Christmas.



Sunday, November 29, 2015

What the hell we are doing




CLEANUP

Just wanted to give a quick update as to what we have been doing for the past few weeks and what our plans are going forward. In the weeks leading up to OGDE, we cut more than our fair share of corners and despite having immediately recognized some of these problems, we did not have time to properly address them. Now that the conference is out of the way, we can look at the bigger picture and more firmly establish exactly what still needs to be done. Spoiler: It's a lot.

The first thing we needed to do was get rid of our old repository, which is really just a fancy term for storing your project in such a way that two people can easily work on it at the same time. OK, that's not all it's for, but still, that's the basic idea. We've been struggling against a 2GB file size limit for a long time (seriously though, how is that a thing) and it was time to finally make the jump to something a bit more meaty. To put this into perspective, the repository's total size was just barely bigger than the actual installer for our demo. Yeah.

We spent a few days migrating everything from the old system to the new system, which also spurned a massive cleanup of our entire project folder structure, which is also something that has been needed for a very long time. The largest part of this was cleaning up unused assets. Seriously. We had about 7 gigs tied up in assets that we didn't even use, scripts we didn't need and a whole plethora of other 'goodies' that otherwise sit there gathering dust. Our small recycle bin grew three sizes that day.

We also took this opportunity to upgrade from Unity 5.1 to 5.2, which I can't even talk about without getting irrationally angry. But I will try. While I do not fault anyone in particular for this, any person that has ever used Unity will attest to the fact that something WILL break when you upgrade. Flat out. Doesn't matter if you aren't even using Unity or never had it on your computer to begin with--it will find something to break. Crisp, clean graphics, you say? 60 FPS? Not anymore, your graphics card is now a baked potato. Seriously, I encourage everyone to try to upgrade from Unity 5.1 to 5.2... I hear there is a large reward if you are able to do this without issue.

Anyhow, after hunting down the sources of these weird peculiarities (or so we hope), the project is back to its former glory. Whole, intact; weary and injured, but functional. The next thing to do was actually dig into the code itself.

  THE CODE ITSELF 

It takes an alarmingly small amount of time to write enough code to majorly confuse yourself. In our case, it took us about two months--then we ran with it for another three or four. Point being, maintaining and refactoring is honestly probably more important than writing the code itself. Any idiot can write it, but it takes at least two idiots to go through and clean it up. So that was the first thing on our agenda, stepping through line-by-line. This is a very boring, but amazingly satisfying part of programming which usually involves the following steps:

  1. Find something of interest: what does this variable/function/class/structure/file/prefab/block/etc. do?
  2. "I don't know"
  3. "I don't either."
  4. Find all references: No results found
  5. Delete it
  6. Program breaks next time you run it
  7. Put variable/function/class/structure/file/prefab/block back where you found it
  8. Go to step 1
After you go through that list of steps about fifty times, your code is production-ready. In all seriousness though, we have essentially firebombed the shit out of everything and salted the earth as a precaution, so that even if we wanted to rebuild it, we couldn't, which is for our own protection.

Seriously though (double serious), we tidied it up a lot. There are a lot of reasons for doing this, but the biggest one, by far, is so that the intervals at which we have to do this kind of cleanup are ideally reduced. Programming is like evolution: shit stacked upon shit. The key difference is that evolution has no real guidance, whereas programming does. This makes programming about a million times more dangerous and unwieldy. But it also means that your programming mistakes can be fixed if you go back far enough. Go too far ahead, however, and you have no chance of fixing it. 

Without any more analogies: we fixed shit. 


TRANSITIONS

We have also majorly revamped our transition system, which is responsible for removing the active character from one scene and placing him or her in another. This system, in a nutshell, handles questions like this:

  1. How does the character progress from one scene or area to the next? Is it trigger-based? Does it require an interaction on the part of the player? (Both cases are handled).
  2. What kind of graphical transition will occur? (Fading/swirling/etc.)
  3. Will this transition actually load a new scene or will it just put me somewhere else in the same scene?
  4. If it does load a new scene, what types of things do we need to preserve between scenes?
  5. If it loads the same scene, but in a different position, what changes do we need to make? Say, if we're going into a battle scene.
We have gone back and forth many times on the question of whether battles would actually take you to a different scene or not. Ideally, you would only want to load a new scene in the case that it is absolutely required, but for whatever reason, we decided early on that battles would actually place you in a completely different scene. What I mean by completely different scene is that a function call is necessary to force Unity to load the new scene. Loading a new scene takes time and as such, we would like to do it as rarely as possible.

The entire combat system was predicated on the idea that the scene you were loaded into (in battle) would have specific objects in it that were necessary for battle and that these objects would be destroyed (or cleaned up) automatically once you left the battle. A large motivation, too, for having all battles take place in a separate scene was that we could have a scaled-down version of the scene in question. Unfortunately, we never really did this and opted instead to make direct copies of each scene for use in battle. This is a terrible idea and requires not only maintaining the original scene, but also keeping those changes up to date with the battle scene itself. The only real case in which this makes sense is for world map battles, where the battle scene HAS to be a different scene.

Instead, we now have it set up so that a battle can take you to any scene, including the same scene. This requires massive changes in too many things to list, but many of them have already been implemented. This gives us a crazy amount of flexibility in how battles happen in the first place, but the main takeaway is that loading into battle now takes a fraction of a second, whereas, previously, it took several seconds. This is huge, especially when it happens as frequently as battles do.

BATTLE UI CHANGES

Not much to say here except that some experimentation will be required in order to figure out the best way to display the information available. The main issue is that character information runs horizontally across the top of the screen. For battles of eight or less combatants, this is not a problem. However, if the number exceeds this (which it will), a different approach is needed.

The idea is that we would have all of this information run vertically along the right side of the screen instead. Sounds like a small change, but it has some pretty huge implications. In this case, vertical space is much more valuable, but we can also get away with 'sandwiching' each panel, or compressing it, rather, to a much smaller height. 

The other main change is that these panels will need to be entirely revamped (regardless of how they are oriented). This change will probably happen concurrently with some major battle changes anyhow (for instance, order of turns is still confusing and we need an actual queueing system, instead of whatever the hell it is we're trying to pass for one). Additionally, characters need to display their charging skills AND the expected targets. This will require some thought and effort. 

Finally, as learned from the conference, there is no actual visual indication that a combo is occurring and no real indication that they even exist in the first place. This will be easier to display once the necessary UI changes have been made, but the hope is that battles will be more intuitive and obvious.

NEXT STEPS

While there are still many, many things to do, our long-term plan is to actually make the game now. Despite how ridiculous that sentence sounds, I mean, actually start from the beginning and work our way forward, plot and all. We are highly satisfied with the way Molsha turned out, but it too, will require a few changes going forward. At the same time, we need to flesh out the inventory and skills system, and specifically, allow players access to menus that allow them to customize their characters (and by allow access, I mean, actually make the damn things).


The overall idea is to focus on actually completing the first 'part' of Bevontule (now that much of the underlying framework is stable). The first 'part' of Bevontule, by our estimates, would comprise anywhere from 10 - 20 hours of gameplay and includes the following areas, in order:


  1. Intro scene/waking up near Atonia
  2. Atonia interior and associated cutscenes
  3. Cephaline (Medium-sized town)
  4. Cephaline area world map (Encompasses areas between Cephaline, Auvane, Molsha and Atonian Steppes to the south)
  5. Auvane entrance (and associated cut scenes)
  6. Cutscenes outside Cephaline (including refugees from Molsha)
  7. Molsha (first large-scale 'dungeon' and associated cutscenes)
  8. Atonian Steppes (second large-scale 'dungeon')
  9. More Cephaline/Atonia cutscenes
  10. The cutscene where Apolith kills everyone 
  11. More cutscenes around Atonia
  12. World map south of Cephaline that connects Cephaline, Yelev and Sarcosa 
  13. Optional dungeon?
  14. Yelev (Small village) and associated cutscenes
  15. Sarcosa (third large-scale dungeon)

So yeah, lots to do... the good thing is that we have bits and pieces of several of these locations designed already. The other bit of good news is that, as said before, much of the framework is in-place already, and ideally, it will take us considerably less time to design many of those places than it took us to design a single place when we were just starting out.

Once again, thanks for reading and keep in mind that the demo can be downloaded and played here.

Sunday, October 25, 2015

More rambling

Just a quick update to give an idea of where we are with the demo (aka, how much we've procrastinated.) Also, this blog itself is a form of procrastination in that I can avoid programming for a little bit. Despite how fun it is, it can get tiring. Anyhow, here are some of the tasks that we have been working on during the last few weeks (look, I even gave each task a header... gettin' fancy):


MOLSHA SCENE REFINEMENTS

As is often the case with uh... well, everything, a lot of refinements/visual updates are completely serendipitous. Andy and I get to looking at something in this particular scene, decide that we don't like the way something looks and then two hours later, somehow the entire scene is improved. In this particular instance (one of many), something as simple as changing the skybox (a skybox is exactly what it sounds like... a big set of pictures that wrap around the sky in a scene in a particular way) can drastically change the entire mood of a scene.

I would say something really nice about some of the 'terrain' used in Molsha (for the park areas, as well as some of the areas around the mines), but Andy somehow managed to delete a large portion of it. Then again, if I came across an asset named "New Terrain 9", I probably would've deleted the shit out of it too. So it goes.

We were wanting to have three connected 'scenes' for Molsha, but decided on settling for two after realizing that the demo will already be quite long (assuming the player is interested in fighting the different enemies scattered throughout... and finding the various things that we have hidden). This also gives us more time to focus on the way two specific scenes look/play without spending a bunch of time trying to tune three scenes. Still a two-man team, after all.

FOOTSTEPS

When people walk, sounds happen. Since our game is a 100% accurate representation of reality (with giant roots and shit), we decided that we'd need some footsteps too. There are a bunch of ways of going about adding footsteps, but really, all one needs to know are the particular moments when a given foot hits the ground.

Since this is such a small, but important task, we figured we'd spend a few bucks on a Unity asset to basically do this for us. Literally, thing cost two bucks. Anyhow, it didn't really work: couldn't handle variable speed characters (which is completely worthless), nor could it handle blend trees (again, completely worthless). For two bucks, I'm not sure what I expected.

Anyhow, we ended up doing this ourselves. For anyone interested, here is how we did it:


This graph represents the xyz coordinates of Bodom's right foot as he runs. The blue line represents the vertical position of his foot and as such, is the only thing we're really interested in here. As you can see, there is a low point and a high point. Basically, Unity (being the little darling that it is) allows you to add 'Animation Events' at particular points in an animation. What this means is that you can trigger a function to be called whenever a desired event occurs. In this case, every time the blue line is at its lowest point, we know that his right foot should be hitting the ground. We then call a 'Footstep' function that we implemented, and we can additionally pass it the foot that 'stepped on the ground'. This function then casts a ray downwards to determine what it actually hit--from there, it can play the appropriate sound depending on the surface. We do the same thing with the other foot. The best part about this method is that the graph above will effectively be scaled depending on the speed that the character is moving, ie, it doesn't matter whether he walks or runs.

The only real downsides to this method are that a.) it requires manually setting up each animation and b.) it only works for bipedal characters at the moment. Both of these can be dealt with by automatically determining the lowest points in code (contrast with having to do this by hand) and altering the function to handle an arbitrary number of feet/contact points, respectively. For now though, it works well enough.


SOUND EFFECTS

Since we're on the topic of footsteps, we additionally added a few mechanisms to allow skills/attacks/other interactable objects to trigger sound effects. This was not difficult by any means... however, finding appropriate sound effects was a different story altogether. As it turns out, there are a lot of free sounds out there. Like... a mind-boggling amount. And 99% of them are utter shit. Seriously, pretty sure people put sounds on there specifically to troll indie game developers. Then you have to wade through the licenses... and trim the songs... and change the volume... and add fade ins/outs... and sync the sounds with the animations... very tedious.

Somehow though, after searching for a few days, I managed to find decent sound effects for literally every action in the game. Admittedly, some of them are weaker than others (who knew that sound quality consistency would matter so much?) But by god, they are in there and they already add a huge amount to the overall game.


MUSIC

For the demo, we have decided on two (possibly three songs) songs that are an absolute necessity. Battle music, boss battle music, and possibly a battle victory song. For the actual background music of Molsha, we found a nice ambient loop that works insanely well without needing dedicated music, per se. Which leaves these battle themes as the sole remaining musical... uh... issues. If you know anything about me, I am one picky motherfucker when it comes to music. Unfortunately, with only a few weeks left, it's not like we have the time/money/expertise to develop/acquire the kind of music that I would want... thus, to the Unity asset store we go. Don't expect any miracles here... after a cursory glance, it looks like the offerings are brass, brass and more brass. And some percussion. Then brass. So yeah...

DEMO AVAILABILITY

After a bit of dicking around (technical term), we figured out how to build a (WINDOWS!) installer for the game. This was not exactly as easy as I expected it to be (long story short, it seems that Unity does not put assets contained in the "Resources" folder into the "sharedassets" file it generates. The solution was to manually place these ourselves... are... are you asleep?)

Since we obviously have to have the demo finished for the conference (or not, might just get drunk instead), we plan on releasing this to any who are interested as well... at some point. We'll probably have more information on this later, but if you are someone who wants to try the game out (and provide feedback, of course), please let us know via a comment/direct message. We'll try to have this available ASAP (if not before the conference, then shortly thereafter). Presently, we have only tried this demo on exactly two computers... I expect that we'll find a lot of fun shit out whenever multiple people attempt to install this thing on their various desktops/laptops/lawnmowers.


LINGERING ISSUES/BUGS

"None. Zero. No lingering issues or bugs. Application runs flawlessly and at 60 frames per second. Always."
-Said no programmer ever

There are a few notable issues--we still need to add a way to essentially 'reset' the game once a particular person has played through the demo. (ALT+F4, then re-running the application is not an acceptable solution) This will not be difficult--just tedious.

AI issues: occasionally, an enemy character will walk directly up to an ally and then proceed to do absolutely nothing. Not sure what this is about...

Interactable objects do not currently persist throughout scene loads--what this means is that if you open a chest, unlock a gate, trigger a cutscene, and then go to another scene, you can then return to the previous scene and re-trigger all of those things again. We already have this working for enemies--ie, if you kill an enemy then go to another scene, then return, that particular enemy will continue to be gone until its spawn timer resets. Thus, we have the framework in place--we just haven't implemented it for interactable objects.

Dialogue: need to spice up some of the exchanges between characters so that the player has some idea of what they are actually doing in the demo. Currently, they just look at each other and grunt. In the original game, the overt purpose of going to Molsha is to essentially survey the damage and look for survivors. (Spoiler: there aren't any) In the demo, however, the goal is to find and defeat the boss of that particular area. While this won't vary dramatically from the overall game, it would be nice to have the dialogue/cutscenes/exposition set up as similarly to the real game as possible.

UI: Multiple revisions have inevitably broken the main menu. Andy is currently whipping it back into shape, but it'll still be pretty bare-bones; the character will have access to the "Status" and "Items" subpanels but we are not sure if we'll have equipment switching implemented by the time the demo rolls around.

Framerate: Honestly, this deserves its own blog post. Maintaining a consistent framerate is probably the most fundamentally important thing that tends to get overlooked. Until it's too late. This is for good reason: because it's a bitch to figure out.

As an example, that song that one dude wrote about having 99 problems (but a bitch ain't one) is actually about maintaining a consistent frame rate for the games he develops in his spare time. If you pay close enough attention to the lyrics, it's obvious that he's talking about overclocking/vertical syncing/different shader profiles and so on. I can relate.

Saturday, October 10, 2015

Ramblings

With OGDE just a few weeks away, I am disappointed to say that we have had to resort to various amphetamines and (game) designer drugs to keep up with the cruel and unusual deadlines set by our boss, Kitler. Yes, our boss is a cat. And let's be honest here, everyone's boss is a cat, even if you do not own a cat.

That is what the update would say, anyhow, if we weren't massively ahead of schedule on pretty much everything. Seriously. Send me the cat a check for $99 and you can have a copy of the completed game. It will crash probably within the first five or so minutes, but Windows charges much more than that to crash for you, so I'd say it's a good deal overall.

All right, maybe we're not THAT close to being finished overall, but the demo is pretty solid at this point. To recap, here are the tasks we mentioned in the previous update:

-Tie up any loose ends regarding UI stuff (DONE)
-Add "Battle Finished" screen displaying EXP, benefits, et cetera (DONE)
-Fine tune Molsha cutscenes (MOSTLY DONE)
-Add final Molsha area (MOSTLY DONE)
-Populate Molsha scenes with enemy spawns/loot drops (YES)
-Add some kind of rudimentary enemy AI (OH BABY--more on this later)
-Sound effects/music (uh... hey, what's that over there??! *points and runs away*)
-Fix lingering issues with character animations/riggings/timings/et cetera (MOSTLY DONE)

And who can forget the most important task of all? (per our master task list):

-??? (DONE)

And really, there are a bunch of other things that got added and completed, but I am far too lazy to list them all out. And it would be boring as hell: "Added code to enable NavMesh agents for acting battle characters while enabling NavMesh obstacles for" See? Boring. So boring that I couldn't even finish the sentence.

Of the tasks listed above, many of them do not need any further clarification. In fact, for the first time ever, I think we can say we are confident enough in some of that shit to not even need to re-do it in the future (or so we say).

If you have read these updates consistently, you'll notice that we refer to AI quite often. For those who do not know, AI stands for artificial intelligence. In this case, it relates specifically to the artificial intelligence of enemies during battle. Up until very recently, the game was setup in such a way that the player controlled both the allies and enemies. While this is kinda cool (and EXTREMELY useful for debugging/testing/et cetera) it does not make for very compelling gameplay.

At some point, we knew that we would need to add AI for the enemies so that they would act independently in battle and ideally, one day, actually present a challenge to the player by acting intelligently. We also decided (correctly, it seems) that AI would be the most difficult task, by far, if for no other reason than the fact that there is no real metric for determining when we have finished that specific task. In other words, there are probably an infinite number of things we could do to increase the 'intelligence' of enemies. OK, it's probably not infinite, but the more mathematical term 'shitload' definitely applies here.

So, the first question is, "what do the enemies even need to do to act intelligently?" Seriously, someone help us. This is not a rhetorical question.

I guess the keyword in all of this this is 'rudimentary' and boy is it ever! The current AI system took just a few days to implement, which is all the proof one needs of its rudimentaritynessosity. It's pretty simple:

-Enemy has a turn
-Enemy finds all allies in range that it could attack
-Game assigns equal probability to all characters (except Apolith, who can modify his probability by taunting enemies)
-Enemy randomly chooses ally within range to attack
-Game assigns equal probability to all enemy skills that could be used (barring range limitations, SP costs, et cetera)
-Enemy randomly chooses skill to use on ally
-If enemy has no allies in range that it could attack, it moves somewhere towards a random ally and repeats the above steps. If there are still no targets, the enemy's turn ends.

That's pretty much it. Nice and easy. The main thing is that it does present somewhat of a challenge to the player. But it's also really bad when it comes down to it, because the challenge in this case is not because the enemies are intelligent, but because their attributes are overtuned. Seriously, there are so many improvements that could be made, it's sickening.

So why even do it this way if it's going to eventually be scrapped? Well, for starters, we don't have a whole lot of time. It would be very easy to go down a rabbit hole that results in the AI being improved in some ways and broken in others, which is not the kind of situation we would want to be in for a live demo. The last thing we want is an enemy launching itself into the ionosphere in lieu of choosing an ability (yes, this happened once. No, I don't know why. Some folks say dude is still up there...)

Another reason is that this is kind of a test drive, if you will. Some programmers (although none of the ones I know) like to intricately plan out the details of what they are about to code. And then they get in there and realize that most of the things they had assumed are not true at all and that there are all sorts of interesting things that they did not account for.

Personally, I like to just run full force at the problem until I get a concussion. After I sleep it off, I like to run at it again and again until both the problem and brain tissue disappear entirely. In this case, the problem is pretty big, but it's easy enough to tear off a chunk (which is the rudimentary part) and just beat the ever-loving shit out of it.

Mainly, it's a learning process. We figure out very quickly which things will work and which things are not worth the time. Again, it's one thing to spend a bunch of time planning out how/where to move an enemy, but if I can't even get the pathfinding to work properly, I just wasted a bunch of time for no reason. No amount of planning is going to tell me that I need to call certain functions in a certain order, only experimentation.

But this does not mean that we have not thought about the AI extensively and it doesn't mean that planning is bad. The better approach, when we get around to it, would actually be to exhaustively simulate and test all possible enemy moves and actions, which is sort of how a chess AI works, but not really at all.

This should not be hard to compute really, since there are only so many combatants in a battle and so many actions that each combatant can take. Essentially, an enemy would put all of these actions in a list and then evaluate them according to some metric. The tricky part would be figuring out these so-called metrics, or, in other words, how 'good' a particular course of action is.

As an example, one metric could be damage maximization. Another could be target vicinity. Another could be whether the ability hits multiple targets. Any of these things, if fulfilled, would add a small weighting to that particular action. Some actions would probably just be complete shit and would be able to be pruned and discarded immediately. Certain ones, however, would have higher scores than others. These scores could be probabilities themselves or they could be absolute values, ie, always perform the action with the highest score.

The truly complicated part of this would be considering the actions of other combatants as well as well as future actions. For instance, suppose an enemy moved to a particular area and decided that there were no targets there at that spot. However, in two turns, imagine that another enemy kicks the ally into range of that particular enemy. Even better if the particular ally were critically injured at that point and would only require a single attack from the acting enemy--except that the acting enemy would actually need to plan out his action based on what will happen in the next few turns. And there are a million potential situations like this.

The main takeaway though is that

a.) basic AI was much easier to implement than I thought, but is implemented nonetheless
b.) better AI is much harder to implement but will have to be put on the back-burner
c.) Kitler is a bitch

Oh yeah, those other tasks... we did manage to improve Bodom's rigging and animations quite a bit. If there is one mistake we made, it was forking over the money for Bodom's character model (we're not going to talk about how much it cost, but just know that I will require a dialysis machine for the rest of my life).

Basically, we got a little impulsive. The character model itself has a few uh... imperfections (and a face only a mother could love... if the mother was blind) and was not actually rigged. We figured, hey, we can rig this ourselves or use an online utility... but we were wrong. (Rigging is the act of actually adding a 'skeleton' to the character so that it can be animated).

Thanks to some alterations to the model, we were able to get a decent rigging as well as find animations that don't look absolutely ridiculous on this character. (I swear the dude's knees and ankles are in the same place, but hey... what can ya do).

Many new particle effects have been added as well and there are only a few skills that are still lacking them. This is pretty low-priority as there are no real 'catches' when it comes to particle systems. Just gotta sit down and randomly change shit until something good pops out.

As for the sound/music... we don't talk about that. Just know that the Bevontule soundtrack will be the first release ever in the genre of "Ethnic Ambient Beatboxing/Whistling"

Bye bye.

Sunday, September 20, 2015

Things

Since it has been an appallingly long time since we have posted any kind of update and I am likewise appallingly hungover, I figured it'd be a good time to write a bunch of stupid shit.

At the time of the last update, we were agonizing over the battle user interface. This might not come as a surprise to anyone, but we are still agonizing over it--however, the level of agony, profanity and sacrificial shit, I'm glad to say, has been reduced by approximately 73%. Which is pretty close to baseline levels.

What this means basically is that the UI is in a pretty good spot at this point, but getting there was not easy. In fact, I would say that the UI has been the most difficult part of this entire project, next to the part of the day where we both realize we have drank too much coffee and cannot have any more until the next day.

So, why has this thing been so difficult? Lots of reasons. First off, everything was rewritten from scratch, and I mean everything. That is, everything relating to the UI. The battle mechanics themselves were not rewritten, however, which means that all of this new UI has to work with some already wonky shit. Ideally, a lot of the battle logic would be rewritten too, but ain't nobody got time for dat.

Right off the bat, rewriting something that previously worked is kind of a depressing, but necessary prospect. This was done solely because our old UI looked like ass and could only be interacted with via the mouse. The new UI, in comparison, still looks like ass (but a good ass) and can be interacted with using multiple input methods simultaneously, including mouse, keyboard, XBox controller and Ouija boards. (Fun fact: the name of this post was originally going to be "Putting the UI in Ouija")

We also wanted to remove any of the 'fluff' of the previous battle UI--for instance, why have a confirm/cancel button after every option? Canceling and confirmation are now based on controller or keyboard button presses (for the mouse, simply moving the mouse back to the previous 'panel' will cancel the current option.)

The idea was to group all battle options into four-panels or layers. The initial UI layer contains all of the main options: "Move", "Attack", "Skills", "Items", and "End Turn". This layer is always shown when a character is acting. The second layer is simply a "Confirm" button and is only used while a character is moving. (Not entirely sure how I feel about this.)

The third layer represents actions that the character could take. When the character selects "Skills" or "Items", this layer is shown and populated with the respective choice's actions. The fourth layer is something that was not present before and represents the targets that the action can affect. This layer is shown whenever the character selects "Attack" or any option from the third layer. We felt that the inclusion of this layer was necessary to further clarify just who the character can affect with a specific action.

Much of the difficulty came from figuring out how to get Unity to manually select or deselect options for you. For instance, anything that you mouse over is 'selected' automatically by Unity. This means that, at first glance, it is not feasible to use the mouse and/or keyboard simultaneously, since Unity will effectively select two things: the thing you actually have selected, and the thing you have the mouse over, which is pretty shitty. We got around this by temporarily disabling mouse input if the character had previously used another input method. This isn't the best solution, but it seems to be the only available one at this point.

The entire look and feel of the menu system is DRASTICALLY different. It's honestly pretty ridiculous how much can be achieved with a few simple textures and different effects. A lot of time was spent on figuring out exactly how to display this (how do we handle menu options that can't be used?). I'm not going to bore you with this, but know that it was deceptively difficult to get certain 'simple' things to happen properly. For example (I lied, I'm going to bore you), any action that gets mouse over'ed (highlighted, for future reference) will display a target radius--even if this action cannot be used (lack of SP, lack of targets, et cetera).

This means that options that cannot be used can still be highlighted, but cannot be clicked on. Essentially, any button is in one of three states: Idle (the button is doing nothing), Active (the button is currently highlighted) and Disabled (the button is shown, but has a gray tint to it). For the purposes of highlighting something that is disabled, you would essentially need to make it active as well. For whatever reason, I could never get the animator to behave properly (Transition from 'disabled' to 'active', but keep the gray tint.). The solution was to have a 'Selected-Disabled' state, which I thoroughly hate. And that's the price you pay for trying to do things the way they should actually be done--spent about a day and a half trying to get something 'elegant' to work, when the real solution was there the entire time (and took about thirty minutes to implement.)

And this is just focusing on the actual 'menu' part, which is just a half (or a third, really) of the overall UI. The second part refers to the actual character info, rather, the panels that are displayed in the top portion of the screen. Previously, these were the assiest (this is an adjective now) looking parts of the entire battle screen. (Even in the previous update's picture) They have been drastically updated and are moreover, completely animated.

For instance, previously, a character would choose an ability and that would be about it. You would get a shitty little text area in that respective character's panel showing something like "Lunge 1/3 hurr durrrrr". Not anymore, though. Instead of describing what it looks like now (which I really should have done with everything), refer to the picture at the bottom. Granted, an image won't show the animations, but we'll save that for another video and/or playable demo. :)

I'd feel bad if I didn't at least mention the third part of the UI, which refers to the elements shown on the actual battlefield. The most important part of this area is the displayed effect radius, which I feel deserves an explanation for as much shit has been involved with it.

This is created by taking a mesh (usually a disc, sphere or box), placing it at a certain height above the character's location, then having a projector object project a shadow onto the ground based on that mesh. This mesh is then scaled depending on the character's selected action's effect radius. A neat effect, but also very expensive. Much time was spent trying to figure out the best combination of visual quality, while still preserving the frame rate (which deserves its own post entirely).

The biggest improvement is that this mesh is now animated, meaning that it can rotate, fade/blur its edges and smoothly expand or contract. The overall effect is pretty impressive and adds more visual clarity, which is always a good thing. We also revamped both the target selection icon as well as the target highlight glow:

Shameless FPS plug in corner

Anyhow, as you all know, we are preparing for our first (and possibly last) conference in November. There is still a metric shit bushel of work to be done, so here are some of the tasks ahead of us as we prepare for our public shaming (and/or public intoxication charge):

-Tie up any loose ends regarding UI stuff (should take about 2-3 days)
-Add 'Battle Finished' screen displaying EXP, benefits, et cetera (1-2 days)
-Fine tune Molsha cutscenes (1-2 weeks)
-Add final Molsha area (1 week)
-Populate Molsha scenes with enemy spawns/loot drops (1 week)
-Add some kind of rudimentary enemy AI (who the fuck knows)
-Sound effects/music (???)
-Fix lingering issues with character animations/riggings/timings/et cetera (1 week)
-???

That being said, blog posts and FB updates will probably be even sparser (which I'm sure no one is upset about),

Good night, and good luck.













Thursday, September 3, 2015

Putting the UI in unintuitive

Hi. Still alive. Andy and I have both been a bit busy with what some of you may lovingly refer to as 'real life'. I recently moved and Andy had a baby. (One of those is much more profound than the other, but I'll let you decide.) As such, development has been somewhat lacking for the past week or so. However, now that things have settled down, we can get back to business.

There were essentially two different development paths to go down after finishing up saving/loading, inventory management, attributes, et cetera. One is easier than the other, but they are both pretty terrible. It's like that poem written by that one unimportant dude about those paths in the woods. Yeah, you know the one.

The two paths were UI or AI. Since I really detest alphabetical order, I went with UI first. The relative difficulty of the two tasks does not play into it one bit at all...

Since we already have a pretty nice main menu, I decided to focus on the battle UI. As is the case with everything I've done, the original implementation sucked ass. (Perhaps you are sensing the pattern here...)  To defend myself a little, it's not necessarily that it sucked ass. It was just bloated, redundant, inefficient, unnecessary and additionally sucked ass.

All right, idiocy aside, there are a few different ways of going about user interfaces in Unity. The original way was to not actually lay out any of the elements using the Unity editor and instead create them all from scratch programatically. Creating the elements from scratch and handling them in code was very quick and allowed us to have a functional interface for testing purposes, while sacrificing some other important functionality.

Obviously some programming is required in order to actually have a UI that does something (other than sit there and look pretty.) The original implementation, however, was entirely contained in code and a good, maintainable, understandable user interface (from the programming side) needs to be a blend of both visually laid-out elements and minimal amounts of code. (In my opinion, of course)
Again, it's much easier to go to the Unity editor and change a particular rectangle's coordinates as opposed to opening up the source code and trying to find it yourself.

It turns out that Unity actually does have a fairly nice UI system. Well, maybe. From certain perspectives. I'm thoroughly convinced that no one can visualize how they want their interface to look (the easy part) and then immediately translate that to a functional, working system (the hard part) WHILE also understanding everything they did and why they did it. At least on their first try working with a particular system, especially one that is as poorly documented and confusing as Unity's.

Sure, there are some simple UI libraries out there where something like the above might be possible. Unity, however, is not one of them. I can't even count the number of times the result given by a particular combination of layouts, padding rectangles, anchor/pivot positions, et cetera actually made sense. Probably because it never actually happened. Seriously, I challenge anyone to sit down and try to understand what the hell is actually happening behind the scenes with Unity's UI system.

I thought we were making an RPG, but it turns out we're actually making Madden 16

So, really, in this case, we're choosing the lesser of two evils when it comes to UI: rely on Unity wholly or rely on Unity somewhat. Wait, which one is which actually?

I would still say though that the largest motivation for rewriting the UI system is to support multiple resolutions. Many people would say that this is the most difficult/annoying part of UI development and I will agree with them and then we will get drunk as ass.

Thankfully, we don't intend this to be a mobile game, so we are saved from having to really support the low end of the spectrum. However, just supporting a few resolutions in a way that makes sense and doesn't obscure or hide information is a very difficult task. Not to mention, we are still trying to finalize exactly what and how to display the information itself since there is a lot of it. Here is what we have for the character turn bar (terribly cropped, click on image for larger view):


Granted, this doesn't really show some of the cool additions such as active character highlighting, turn order shifting and others (these are controlled by Unity animations, which is a really cool/neat concept once you accept jesus as your lord and savior that you can use animators in conjunction with UI elements.)

Furthermore, the current action is not yet displayed, but will be soon in the small gap beneath the character portrait. Let me say also that we have new models for Bodom and Moroch, but we are going to keep the old thumbnails just to fuck with people.
 
Anyhow, there is a lot more to talk about as the UI rewrite will be an ongoing process, but I told myself that this would be a short update. Besides, it would be much easier to show this off in a video, which we may do at some point.
  

Thursday, August 20, 2015

Inspectors

Finally decided to get down to something that I had been putting off for awhile: custom inspector editors. This has no bearing on the actual game itself, and in fact, will not even be accessible by anyone playing the game. However, for us, these are invaluable tools as they allow us to 'visually edit' different parameters belonging to different game components, which will reduce the amount of time we are editing scripts directly.

So, what the hell does this mean? I don't know, I just like to throw around buzzwords. To explain how useful these custom inspectors are, I'll talk about how we were previously doing things, which is somewhat shameful. So, each character has a set of attributes, as is standard in RPGs. The old way literally used a gigantic statically allocated array that stored these parameters. So, if I wanted to change Bodom's maximum HP, I'd have to dig out ole' AttributeStruct.cs, find the particular character array, find the particular attribute I wanted to modify, change it, then save and recompile.

Unfortunately, I wasn't just satisfied with starting down the wrong path for attributes, solely. This was also the case for skills and items. A lot of this can be summed up by saying that these classes (Item, Skill, et cetera) were not extended from actual Unity MonoBehaviors. This means that they could not be added to scripts as components. This means that their parameters could not be edited via a Unity inspector. There were good and bad reasons for doing this:

 The bad:

-Wastes a bunch of time searching for the things I want to edit
-Is error-prone--oh, I edited his HP when I meant to edit his SP?
-Can't be changed while the game is running
-Adding a new character/enemy was a huge pain. Imagine you had to copy and paste about 100 lines of code every time you wanted to make a new character. Then you had to individually change each entry. In a sense, this is like having a bunch of spreadsheets for each character, item, skill, etc. except that the spreadsheets are buried in a giant file. And the spreadsheets aren't formatted into proper rows and columns. And you can't actually save your spreadsheets because you accidentally put a comma somewhere it shouldn't have gone.

The good:

- Quick and dirty--allowed us to test whether the basic functionality (damage formulas, equipment assignments, skill usage) actually worked.
-Certain parameters were not able to be well-represented (enumeration types, dictionaries, etc) in an inspector without having to write custom inspector code. Since I didn't want to jump into that just yet, this way seemed preferable.
-Uh... that's about it. (But if you didn't actually read this, it would appear as if there were three good reasons, no?)

The ugly:

-Me

So, anyhow, what the hell is an inspector? Here is a picture of one from the Unity editor:

Who needs nostrils?
Er... that's not right. While we're on the subject though, Inspector Gadget was a real dumbass. OK, moving on...



This is a custom inspector designed for skills. Contrast this with the previous method of doing things:



The previous two pictures are essentially equivalent in functionality, but keep in mind, the second picture only shows TWO of Bodom's skills. And that's not even all of the code required to actually register the skills with Bodom. For some reason, I insisted on having skills be placed in a Dictionary. That was dumb. I am dumb.

But yeah, clearly, one is better than the other. Also, that is a 16-parameter constructor. I should honestly have my degree revoked for even having thought about doing that in the first place.

But why stop there? After re-hauling one thing, you might as well keep going. Items were pretty trivial, so I won't even show that. Attributes, on the other hand, were the true target here.

To recap, enemies scale with character level. We plan on having all characters max out at level 100, (easily changed if necessary). Each character currently has 17 different attributes, which are floats. So, to further illustrate how painful this would have been had we continued with the original method, we would have had something like 1700 values to change for every character for every level. To be fair, that's still the case, but you no longer have to edit them in a file (like the previous picture).

The idea was that we needed to be able to edit the current attributes of the character, edit ALL potential attributes of the character for every level and have a way to save and load these from files,

So, this is what we came up with:



This will essentially allow us to modify any character's attributes, whether the game is actively playing or not. This is insanely valuable. You could almost say it's invaluable. Essentially, I can test any set of attributes at any level for any character and then save them  back into the attribute map once they are correctly tuned.

The attribute map then is basically a file that exists for every character that contains the attribute information for that character. "Load to Attribute Map" will take the current character's attributes and save them to file so that they are not lost.

The attribute map inspector, then, looks something like this:


For the most part, these are extremely similar. The key difference being is that we can set up the attributes for any level. Additionally, different level attributes can be specified in a relative manner, meaning that you simply supply the difference in attributes from one level to the next, which is also a huge deal in terms of productivity and not having to remember what the previous level's attributes were.

Just for completeness, here is the enemy attribute map, which has a few extra parameters that are enemy-specific, such as EXP, AP and MONEY awarded by the enemy upon defeat:


Anyhow, just wanted to give a more behind-the-scenes look at our own processes for adding and editing different game components. Now that I've gotten this (mostly) out of the way, I can begin to focus on the next big target: Enemy AI. Thanks for reading!

'Murica.

Friday, August 14, 2015

Enemy spawns / Game data persistence

Since the last update, there has been a substantial amount of progress made on two different, but related fronts. Specifically, the enemy spawning system has been more or less finished (that's programmer parlance for "I finished 80% of it, but I don't know what the hell to do with the other 20%" - also known as the Pareto Principle.. or a modified version of it, anyhow). Additionally, we have the framework in place to save/load game data, which actually turned out to be quite simple once one gets past the initial fear of having to implement something so crucial to the overall game. Rather, the fear of badly messing it up.

So, first, I want to explain enemy spawning mechanics, starting with the old method. Previously, we would literally drag the enemy prefabs into the scene. Then, one (or both of us) would prepare an arrangement of five or six scented candles in a crude pentagram-like fashion with its centerpoint being my laptop. Depending on how we lit the candles, sometimes the scene would work. Other times, Lucifer himself would appear in the corner of the room for a brief moment, and we'd be like, 'clean rebuild and try again'.

Now I know you're all like, "this didn't happen, it's clearly embellished. There is no way they made a pentagram with six candles." And you would be so, so wrong.

The new method is much better and does not, at the moment, rely on any kind of ritual. The first step was to break up all scene elements into two categories: those that were scene-dependent and those that would persist through scene loading. We already had something like this, but it was highly unorganized. We began shuffling around objects that clearly did not need to be duplicated--characters, for instance, never need to be duplicated. Previously, we had each playable character present in each scene within the Unity editor itself, but this was not the best idea, and was mainly to avoid issues that we didn't quite understand at the time. Also, we were really coked out in June/July, but we've cut (get it?) back a lot.

A similar fate befell the cameras that we are using--no need to duplicate these in every scene. Additionally, each enemy object contained its own battle scene transition, which is completely needless, considering that every transition would essentially take you to the same place. Much better to have a single transition object and activate it once battle collisions occur.

As for enemy spawns, these were previously non-existent. What I mean by this, is that we would simply add the enemy prefab to the scene (as stated before prior to the bullshit segue about incantations and whatnot). This enemy prefab contained, among other things, its own spawn parameters and its own waypoint collection. This would be fine and dandy, but we elected ultimately to have a random enemy spawn system. You can see the issue there, when you want to spawn a spider that only chases you for 10 meters, or doesn't chase you at all, et cetera. This meant that we would have to modify the actual object within the scene itself and pray to god that we never applied the prefab. To explain, this would have overwritten every other spider's parameter. The point being, it was a bad idea.

If you recall the update regarding the world map battle zone spawning (you don't and neither do I, so it's fine), the idea was to randomly spawn an encounter once a certain number of steps had elapsed. The great thing about this is that we could pretty much reuse this same framework--instead of spawning a battle group randomly (the term for the collection of enemies that you actually engage when the battle transition occurs), we could spawn a bunch of them within the scene itself, with an extra layer of logic sitting on top that actually just instantiates the enemy prefab at the location. World map battle encounters do not need to bother with this step since enemies are not visible.

Essentially, the relevant parameters were then copied outside of the enemy prefab itself and into the battle spawn object. Much cleaner, and much more flexible (like my fourth wife). The next goal was to actually persist the list of enemy spawns through battles. This means that they would retain their previous locations and spawn status upon leaving a battle (were they defeated in battle? did you flee from them?). Additionally, they would not need to be re-instantiated each time (this is really the big one). For a scene with a few enemies, sure, this is trivial, but for more involved scenes, this will save a lot of time.

We then realized that it isn't just enemies that would benefit from this, but treasure chests/resource nodes as well. Not sure if we want to handle NPCs like this yet, but we'll find out soon enough. What happens then is that these nodes are actually placed under a special node within the scene called LevelManager. The nice thing about this is that we can actually inherit from this class if we want to add level-specific callbacks. For instance, when you first enter Cephaline, it's dark, but it never is again after that. Currently we are handling this in an... uh... hacky way. But no longer, damn it.

Then when you enter a new scene (not the world map or battle scenes, they's special) we graft the nodes from the non-persistent root (LevelManager) to the persistent root (GameManager) and instantiate the enemies accordingly. This has the added benefit of allowing the scene objects to be specified within the level itself. This also has the benefit of putting these persistent objects in a nice centralized location, which is useful for serialization.

As for the enemy spawn mechanics themselves, these are still being finalized, but the basic idea is this: every scene has a number of potential spawn points. When the scene is loaded for the first time, we iterate through these spawn points and check whether or not an enemy should be created at this location. This is mostly time-based, but can be conditional-based as well. Imagine ole' mama spider only popping up after gettin' pissed that our intrepid adventurers decapitated ten of her children.

Now, I know you're thinking, "spiders have millions of babies. Who gives a shit about ten dead spiders?" You be quiet with that type of logic.

Once an enemy is defeated, depending on whether it is a one-time spawn (like mama spider up there, although you could have grandma spider show her ass once ten mama spiders get killed, ad infinitum, all the way back to amoeba), it will be marked as inactive until its spawn timer comes up again. This should be pretty familiar to anyone who has played (MMO)RPGs with similar systems.

The big question then, is how to persist this across multiple reloads. As it turns out, C# makes it fairly easy and straightforward to serialize and encrypt any object. As it also turns out, Unity doesn't and is like, "hell naw, whatchu tryna do here boy?" Unity asks us this multiple times per day, which is why we both wear headphones.

So, even though it's overkill, it would have been extremely nice to have just taken the entire GameManager (the persistent node) and serialized it once a scene was exited and deserialized it once a scene was entered. But again, that would have meant that we would have saved off every attribute (even the ones we did't want saved). Also, it wasn't possible without paying some amount of money for an extension script. I wish I were kidding.

The problem is that C#'s serializer can only serialize primitive types... which is to be expected. Furthermore, it requires you to wrap any attributes that you want to serialize under a special tag. Generally, the idea is to wrap an entire class or structure within this. Unfortunately, all game objects (including GameManager) inherits from Monobehaviour which cannot be serialized.

Thus, the solution, as much as I hate it, is to serialize a nested structure within the class itself. Normally, this would involve duplicating all of your variables. For instance, you would have the forward-facing variables that are exposed to the rest of the game (and most importantly, the Unity inspector). and then you would have a separate 'chunk' that are able to be serialized. Whenever you serialize or deserialize, these would be copied back and forth each time in an explicit step that individually sets/gets variables. Puke.

The trick to get around this was to use properties, including setters and getters that redirect to the internal serializable data structure. The only real issue with this is that you lose access to these variables within the Unity inspector. Thankfully, since they are not meant to be modified, you shouldn't really see them there anyhow. Furthermore, we plan on having custom inspector scripts at some point (any volunteers out there?) that could optionally expose them anyhow.

You know what, talk is cheap. Let me show you what a directory looks like before we save data and afterwards. Put your sunglasses on.



Looks like a pretty normal, empty directory, huh?

I know it's hard to believe, but that is that very same directory AFTER saving game data. Pretty sweet, huh?

All joking (and badly cropped pictures of nothing) aside, we do have a functioning saving/loading system, which is a pretty big f'ing deal. (I get one f word per blog post, right?) I could go on and on about this, but all that matters is that it works.

Next up: revamping the skill/inventory system. *shudder*











Saturday, August 8, 2015

Tearin' down the house

OK, yes, it has been a long time. As our good friend Conway Twitty would say, "It's beeeeen aaaa looonnngg timmmme." Sorry about that. He is not my friend.

So, let's see.. when the hell did we last update this thing? 2013? Good god, it has been awhile. Let me look back at that post and see what we were even doing at that point... (brief interlude) OK, that was quite a long time ago.

For the last few weeks, we have focused our efforts solely on Molsha. If you have not watched this short, short video, you can check it out here: https://www.youtube.com/watch?v=w7OU7TY4qR8. Molsha, besides being a weirdass name, in many ways, is the culmination of many of the different pieces of the Bevontule development effort, and I'm not gonna lie: setting it up was a bitch.

But, through that particular struggle, we learned a lot. Basically, if nothing else, Molsha taught us that we literally have to start the project over again under a different title. OK, not really, but we did learn a lot. Here is a brief list:

-You literally almost need a dedicated machine in order to bake lightmaps. Briefly, lightmaps are, in a sense, a huge runtime optimization applied at the cost of many, many hours of preprocessing. Lightmaps are often used in lieu of having a dedicated, dynamic light. Essentially, dynamic lighting has to look at every object (actually, the vertices and pixels themselves) in the scene and decide, what is the overall amount of light received by this object? Without going too deep into the calculations, this is a somewhat costly process. Since the position of the Sun in Molsha does not actually change, you could say that the lighting applied to each and every object does not actually change either unless something is obscuring it (aka, the player, but we use something else to handle that). A lightmap, then, is basically a giant texture applied to the entire scene that encodes all of the light contributions without having to compute them every frame. Pretty cool, huh...

-...But this didn't mean shit ultimately, as building the .exe itself caused the lightmap to not be applied at all. This is the reason we had to run the demo within the Unity editor itself. Shameful.

-Recording the actual video was a huge pain, not because we suck at talking, but because FRAPS (video-recording software) hiccuped a lot. Granted, we took precautions to reduce this, but ultimately, all we needed to do (somehow) was restart Andy's computer. Seriously. His computer sucks. I should have suspected that this would be a problem when, one day, we were just programming away, and a piece of fresh toast popped out of what I had previously assumed was his disk drive. We ate the toast; it was good.

-Particle systems use a LOT of computational power. I mean, yeah, this is obvious, rendering thousands of tiny objects is going to reduce the framerate. Fortunately, many of the particle system prefabs were ridiculously overtuned (using 5000 particles over the life cycle of the system, instead of 500 or so.) Reducing these particle emitter counts helped the framerate considerably.

 -We implemented a hack to remove the enemy from the scene after you had defeated it in combat. The hack was simple--store the enemy's name before battle, and call SetActive on the enemy with that name once battle has concluded. What could possibly go wrong with this?? I'll tell ya! We were even careful not to have multiple enemies with the same name (that's why each enemy encounter is with a differently named enemy). But, unfortunately, the actual Mesh object parented under the GameObject itself shared the same name. (Why did I do that). In essence, after battle, this disabled the actual mesh and not the gameobect. Hilarity ensued as we wondered why we were able to re-engage with what should've been a non-existent enemy. We suck. We fixed it.

But more than anything, this has taught us that we need to refactor. Imagine that the Bevontule code is a house and we are both the architects AND the people that are building the house. Typically, this is not the case, which sucks in its own way.

So, we started with this:


And then it turned into this:



But, ultimately, we want it to look like this:


Basically, that's programming summed up in a few images. Actually, you don't even need the last image except to display an excessively idealized version of what you want your code to one day look like. (That's what the architect shows you)

The point being, we are going to be quite busy (moreso than before) as we rewrite large portions of our code to better handle the kinds of situations that we are going to encounter. In a nutshell, here is a basic roadmap:

-Rewrite the enemy spawning/saving/loading code to be more efficient, and to anticipate the other problems that will inevitably arise when we get into actual save file writing/reading. Much of this has already been started.

-Rewrite our scene loading code to be more efficient. This will likely involve investigation of other Unity concepts such as asynchronous and additive loading.

-Investigate new lighting/rendering/modeling/batching techniques to get the most mileage out of the scenes we have created. For instance, Cephaline, as it stands, runs at a pathetic 30 frames per second. There are a lot of different reasons for this, most of falling under the category of "trying to walk before you learn how to be zygote" Molsha, on the other hand, ran at around 100 FPS, and is honestly, a much more complicated scene. So, we're learnin. But there is a lot more to be done.

-Vote for Donald Trump

Friday, July 24, 2015

Hi

Yes, it's been awhile since we posted. We are not dead... completely. Much has happened in the past week or so. Here is a brief overview:

-NASA announced the discovery of an Earth-like planet only 1400 light-years away
-Bruce/Caitlyn Jenner said some shit
-Miranda Lambert and Blake Shelton are getting divorced

Now, on the Bevontule development front:

-Several days were spent downloading a new Unity demo (and Unity 5.1.2 grooooan), which provided us with a few new character models/terrains/ideas. This was a truly painful experience for a number of reasons, but without getting into too much detail, we have a pretty kick-ass model for Apolith, which we will show at some point... maybe. One day.

-Random battle transitions are now working properly (mostly), including the BattleZone framework (discussed in a previous post). This allows us to assign 'areas' within the world map, which describe the type of enemies to be encountered there as well as their probabilities of being encountered. Additionally, the encounter rate can be set as well. Once battle is completed, the character is returned to the original position in the world map. However, if only one character survives the battle, the game goes into an infinite loop for some reason. I maintain that this is a feature.

-A new animator framework has been implemented using the override controllers discussed in a previous post as well. This is a pretty huge deal. Without going too much into it, we can use the same controller for literally every character. Huge savings on memory, runtime performance, complexity, et cetera, which are things we all like.

-The combat turn bar has been completely reworked. Characters now execute their abilities correctly and this is reflected in the turn bar. There will definitely be a battle video in the upcoming week or so showing this.

-Targetable enemies/allies now glow/highlight when they can be targeted. Previously, there was no indication of which enemies you could target aside from looking inside the target area itself. Now there is.

-We have greatly expanded our list of assets/animations/materials et cetera. Yes, money was spent. We are not happy about it. But it was necessary. I mean, really, having a roof above your head isn't uh... that important, is it?

-Much research has been done in terms of scene optimization, including object batching, light map/light probe creation and utilization. This will probably cause us to redo some of our scenes from the ground up, but it will be well worth it (we've noticed framerates tanking pretty hard in certain situations).

-The scene for Molsha (our first real 'dungeon') has been created and we're both working through what that should look like. It's pretty sweet. I'm not biased though.

Talk to ya'll in a month or so!