Gaming Your Way

May contain nuts.

A trip to the hair stylist

More character overhauling. 

I decided to test a short hair look and I found that I really like it (and I don't have to animate the pony tail as an added bonus)



I also finished combining the different maps into a single 2048x2048 one (well one for diffuse, specular, gloss and bump) - thank fuck there's something like UVWxform that allows to offset UVWs via numbers instead of having to move the UVWs by hand. I also fixed the eyelashes and moved them into their own texture (as they are the only part that needs alpha).

-- olli

Overhauled main character - or isn't there something else to do?

When you look at a game character every fucking single day (like during my daily 2h indie dev time) it gets harder to ignore things you don't like every time. First these little things just annoy, then they piss you off.

One of these things was the game's main character's low poly version. I used auto-reduction purely because it saved a few hours of manual polygon reduction. It's quick, but it almost never works well enough. So last week I started to rework the low poly mesh and then added some more time to give the whole model an overhaul. The result not only looks better, but also saves 1k polygons ...

Not that it really matters considering the size the character is shown in the game (or that anyone would notice).

Here are two more comparison images, hands and the jacket:

 

I know I should be working on the code side of the game and finally adding the goon back in (which will get an overhaul as well), but it is good to have that out of the system.

Speaking about systems, I still want to do a post about the minimalistic FSM thing I wrote for the game (to replace the clumsy pseudo FSM like construct I was using so far) - well next time.

-- olli

Light and shadows ...

I'm not sure I mentioned it, but setting up lights (in 3D) is an art form (even with today's "click and done" tools and global illumination). Even more so in "realtime 3D", when you have a very, very specific idea of how things should look.

AgentZero (or AZ for short) isn't different there (did I mention that the prototype finally has a name?).

My original plan was to be able to light each room (as I would do for rendered 3D) to get the light *right*, but of course there is no such a thing as "right" when setting up the lights in Unity. The first bummer was the fact that even with shadows turned on the lights shine "through" the scene, ie. when turning off a light on the first floor the room below it would become darker too.

So I ended up separating rooms with layers and "exclude" lights, so the lobby would be layer "RoomA" with the lights limited to that layer and the first floor would be moved to layer "RoomB", while the second floor would use "RoomA" again (as there was enough distance, so the lights didn't shine through).

This shows the old lights in action, with 3 spots per room there where 12 in there, plus the spots in the elevator and behind the doors (which are turned off when the door is closed).

Due to the nature of the beast there are only so many lights Unity handles well, setting the important ones to "important" helped a bit, but the nail in the coffin was the new "Restroom" room. When opening the door some annoying flicker showed (when the light was turned on behind the door). I may have been able to work my way around that, but I decided to overhaul the light completely and reduce the number of spots a LOT.

The new lights in place, it got a bit brighter and it lost a good deal of depth, but not to a degree where I would have cursed and shouted. Instead of using spots I went for 2 directional lights - one main light and one fill light to light up the edges. On the plus side I still can exclude rooms from that and add individual lights there (think dark passage), I need yet to find out if I can change layers at runtime, but if not I find a way around that.

The lobby with the new lights (not as bad as I feared either).

I'm toying with the idea of adding a light that moves with the player to recreate a bit of atmosphere, but for now the light has to stay the way it is now.

... and with this I'm going to continue coding the handling of the WC stalls.

-- Olli

Slight change of direction ...

During the last couple of month the prototype game changed a lot and I entered a state not unlike "full production mode" (just with less time to actually work on the game).

This is what it looked like the last time I posted about the game (because, let's be honest, the last post was fucking ages ago):

The most obvious thing changed is the map:

As you can see, it moved away from the platformer style to something room based, the elevators were moved into the back (instead of blocking the path) and there are no goons in there (yet).

It started easy enough with the idea of removing the gun from the player and introducing the "hiding" mechanic, I also started to dislike the way the goons moved around "randomly" (the reason why I wrote a  pathfinder based solution). Also some of my early playtesters mentioned that the mechanics weren't quite working as well together as I thought (something that had dawned on me as well).

Once the old map was gone it wasn't that hard to settle on the room based map and add the mechanics that suited the slower pace, just to realize that I made a full circle with the game idea (and a round trip of about a year). Mechanics wise the game is more or less the same as the one I first started over a year ago, just the visuals changed from top-down/iso to fake-2D:


Right now I'm exporting some new rooms in order to add some more features (cameras, laser gates, etc.) and later get the goons back in, but this time with less freedom to move around (for the most time). Mostly they will be used as guards (patrolling a set area), but some may walk off and explore the map on their own.

Last image in this post is the "Elevator Cam", which ended up in there because I needed a new way to control the elevators from the inside:

And with this I'm going to export a restroom.

-- Olli

ps: There are more frequent updates on this on (my) twitter (@nGFX, link on the right) as it is sometimes easier to just write 5 words and post an image.

Unity, Mecanim ... the easy way ... for dummies ... like me.

If you happen to be old enough to know a world without youtube and like the written word (like a tutorial), tough time for you.

So if you want to learn, say about using Unity's main animation tool Mecanim, but also happen to *HATE* tutorial videos (because they waste your precious time) you're in deep shit. I'm not saying that Unity's tutorial videos are shit, but watching 30 minutes of someone talking away for an information that fits on 2 lines of written text (and maybe a screenshot) ... well, you get my point.

Fear not, we have written words (and screenshots)

Let's start by wasting some space with the basic problem: You have a character, animated him (or her) and want to use it in Unity. I might need to point out that I'm NOT using Blender (so things may be a bit different for you, but the basics still apply).


That's Violet and the odd 850 frames needed to animate her.

Let's fast forward the export and import process and jump right to the part you'd do if you haven't watched any tutorial video on setting up anims or re-targeting them in Unity.

After you're done setting up the animation clips you might end up with something like this:

(taken from a character that needs updating)

In a way you're set and can start setting up the animator's state machine, but what if you change the model or need to update / change the animation? Well you end up re-creating all the clips. Joy.
After the second time it becomes some sort of a curse.

Oh my.

If you have at least read the Unity manual on this (which is [again] very much lacking useful examples), you should know that you can re-target animations between models that share the same bone structure. But you may have (like me) overlooked the fact that this also solves the problem of re-doing the clips over and over again when you update your character.

Exporting the character to use with Mecanim

(This headline is just there to ensure google finds this post)

This process might be a bit more work when starting, but it saves a shit load afterwards. Let's start with exporting the "base" (and NOT animated character). In my case I select the skin and bones and hit "export selected" and get this dialog:


I should have exported the base model in T-pose and without animations, though (makes it easier to create a ragdoll).

Anyway, that's done, go to Unity and import and setup the base model:

Note that there are no animations to be imported.

Exporting animations and setting them up in Unity to be used with the base model (and re-target them)

Now it's time to swap the tedious process of setting up the animation clips in Unity with the tedious process of exporting the animation clips from our 3D app (although, this is the by far better choice in the long run).


The trick is, that this time I only select the bones when clicking "export selected" and the important part of this dialog is "bake animations" and the option to give a start and end frame (hint, hint). 
Actually, you could of export the skin again, but there really is no need to do so.

And after (what felt like an hour) I've got my clips exported and in Unity.

Preparing for re-targeting the animations

The tutorial video needs about 17 minutes to explain all that shit, but we can get the important information from a single screenshot:

When importing the animation, we copy the rig from an existing model (the base model) and click apply. Now set up the animation clip by changing to "Animations" and because we only exported the needed frames it's just changing the name from "Take 0001" to something meaningful (and maybe go over the other options of the clip, like looping).


That's it. Now you can just setup the animator state machine as before. Violet's looks like this right now:


Viola! A bit of text, some screenshots and no need to watch 30 minutes of video. Mhm, but then it took me about 2 hours to write this ...
... I think I better start making videos. 

-- Olli

Object pooling without all the ins and outs

I've been meaning to write this up for a while now, so before we start it's going to be a long one ( And I'm not going to make it even longer with a "That's what she said..." comment.. damn it, already ) and could end up being a little dry in places ( "That's..." )


Ok, we all get object pooling, any mention of optimisation includes the term like some sort of crazed mantra, so I know what it is, you know what it is, let's actually start from there.


Until recently I did it like this:

//Fill our pools    
    this.activeParticles=new Array();
    this.particlesPool=new Array();
    var particle;
    var cnt=-1;
    var len=numberOfParticlesWeWant;
    while(++cnt!=len){
        particle=new ParticleInstance();
        this.particlesPool.push(particle);
    }

The pool would be pre-filled to it's max length, I don't understand all this growing pools thing in a game, when you're getting an object from the pool it's because your game is doing tons of stuff anyway, why make it run even slower.
The main loop would then be:
  var particle;
  var cnt=-1;
  var len=this.activeParticles.length;
  while(++cnt<len){
    particle=this.activeParticles[cnt];
    if(particle.mainloop()=="dead"){
      this.activeParticles.splice(cnt,1);
      this.particlesPool.push(particle);
      len--;
      cnt--;
    };
  }

I'm just showing this for the general gist of things, two arrays, an active particle array and the pool array, when a particle stops being active you remove it from the active one and put it back into the pool.

The thing I've changed recently, which I've seen really improve performance, is the whole array access part. Every time you use pretty much any Array method, such as splice, it returns the new array. That's handy, but if you're not doing anything with it's just floating around waiting for the GC to spot it and kill it off for us. This is happening 60 times a second and when the GC kicks in is anyones guess, 1 second, 5 seconds ? Either way it's a lot of junk data just sitting around ready to be cleaned up.
Also you're no longer working with fixed length arrays, which is another strain as they shrink and grow.

The new way I've moved over to is having both a pool of objects as normal, and an offset table.
    var len=48;
    this.bloodParticle_poolOffsetTablelength=len;  
    this.bloodParticle_poolOffsetTablelength4=len/4;
    var buffer=new ArrayBuffer(len);
    this.bloodParticle_poolOffsetTable=new Int8Array(buffer);
    this.bloodParticlePool=new Array(len);
    var cnt=-1;
    while(++cnt!=len){
        this.bloodParticle_poolOffsetTable[cnt]=cnt;
        this.bloodParticlePool[cnt]=new BloodParticle(cnt);
    }

That's code directly lifted from Rot, I may love you but not enough to write new example code for you.
So there we use the len/4 for loop unrolling later on ( So all our pool lengths have to be divisible by 4, but you can go with 2 or 8 or whatever you can face ).
The one "What's that now?" thing may be the Int8Array. Basically it is what is says, an array which can only hold 8bit ints. It's much quicker than a normal array and all we're doing is storing numbers in it anyway, the table is just a list of offsets to our pool array.

When we request an object from the pool we loop through out table offsets, looking for a valid number:
ParticleHandler.prototype._getBloodFromPool = function() {
    var offset=-1;
    var cnt=-1;
    var len=this.bloodParticle_poolOffsetTablelength4;
    var table=this.bloodParticle_poolOffsetTable;
    var pool=this.bloodParticlePool;
    
    while(++cnt!=len){
        offset=table[cnt];
        if(offset!=-1){
            table[cnt]=-1;
            return pool[offset];
        }
        offset=table[cnt+12];
        if(offset!=-1){
            table[cnt+12]=-1;
            return pool[offset];
        }
        offset=table[cnt+24];
        if(offset!=-1){
            table[cnt+24]=-1;
            return pool[offset];
        }
        offset=table[cnt+36];
        if(offset!=-1){
            table[cnt+36]=-1;
            return pool[offset];
        }
    }
    return false;
};

If the offset isn't -1 then it's valid and we can claim it, so then set it to -1 and return the object. That's it, we've got our object ready to init() and no arrays were slapped around for it.
( Also you can see where our loop unrolling comes in to it )

Right, we've created our pools, got an object from them, how to do we run each object ?
    var len=this.bloodParticle_poolOffsetTablelength4;
    var table=this.bloodParticle_poolOffsetTable;
    var pool=this.bloodParticlePool;
//Sorry about the broken indenting here, it bugs me too        
        cnt=-1;
        while(++cnt!=len){
            if(table[cnt]==-1){
                if(pool[cnt].mainloop()=="dead"){
                    table[cnt]=cnt;
                }
            }
            if(table[cnt+12]==-1){
                if(pool[cnt+12].mainloop()=="dead"){
                    table[cnt+12]=cnt+12;
                }
            }
            if(table[cnt+24]==-1){
                if(pool[cnt+24].mainloop()=="dead"){
                    table[cnt+24]=cnt+24;
                }
            }
            if(table[cnt+36]==-1){
                if(pool[cnt+36].mainloop()=="dead"){
                    table[cnt+36]=cnt+36;
                }
            }
        }

Pretty much the same as requests the object from out pool, if the object is dead we just put it's value back in the offset table again.

Break the bad news to me gently doc.

You may have noticed the downside, which is in our main loop. In our original way we took the active particles array length and worked through that, so if there were only 5 objects running then it only looped 5 times. It doesn't really allow for loop unrolling, but it's always just doing the correct number.
In our table offset approach we have to check every object every time. That's less than optimal.

But...

Say your game needs up to 20 explosions running at once. Firstly, cool game. Secondly, that's the worst case scenario and because we're already checking all our objects every frame we pretty much know the game can cope with that worst case.
Also you can set flags to see if certain loops even need testing ( I removed those checks from my pasted code just for ease of reading ). Your explosions aren't going to be happening every frame ( If so, again, cool game ) so you can do a simple test to see if any are running, if not skip the loop entirely, if so run the loop and keep a running total of how many objects are actually running, if it drops back to zero clear your test flag again.

I'm sure all of you reading this have your own ways of pooling, everyone does, and I'm sure some of you will be able to pick holes in this, good, please do so in the comments so that information is shared, but I've found not altering the arrays has had a large performance boost on mobile which more than cancels out the overheads involved.

K, I've got a freeze gun to finish adding to Rot, so that's me spent.

Squize.

New Test Level and Goon AI

Fuck funky headlines. So I said it.

Today's post is all about ... the new test level and new goon AI (mhm, maybe back to funky headlines?).

Let's start with an image:

The old test level with two elevators and some searchable objects (grey boxes).

While this worked well enough the random / percentage based goon AI it didn't look good on the new test level. One reason might have been the way I've dealt with entering/exiting the map. In short the goon wanders around until he reached the number of steps he should do and then takes the next exit he comes across. For the smaller test level this was OK, but with the much wider new level this revealed some problems. Due to the random nature, goons sometimes would just walk back and forth between a door and the elevator until it reached the required steps to exits again.

This made me rethink the way the goon walks around and I settled on the idea that it would (and does, comes to that) look better if the goon has a predefined path to follow. 


The new test level, also shown is the potential path I want the goon to follow and the new elements.

Of course this added some more things to think about, most obvious is that the goon needs a path to follow once an entry and an exit have been assigned.

As Unity comes with a nice built in NavMesh, I tried to get away with that...

... and as soon as that was in, it showed that this won't work "out of the box".

To make that story short: it works just fine as long as you can work with a continuous path, but the different floors and the elevators proved to require a lot more work than I was willing to put into. One of the "easy", but tedious solutions were using Off-Mesh Links, so the NavMesh Agent would know how to reach the different floors. As far as I found out (prove me wrong) there's currently no way to create Off-Mesh Links on the fly via code.
Creating those by hand in the editor would have made a brave man cry (I gave up after a few). For each elevator, one link between the left and the right side and for every floor AND every side, so for a 3 floor elevator: 15 Off-Mesh Links (if I counted right). 

Erm. No.

Time for plan B.

Plan B was easy, just create nodes for my a* graph based pathfinder. 

Well, creating nodes was easy, as I already had a lists of all doors, elevators and the other stuff. 

Connecting these is a different story (in a way that makes sense). Until now the map elements (which the goon could interact with) only stored the current "block" (needed later when blocks will be combined to build a bigger level) and I really didn't want to add a "connected to" list or a "floor".

So the (nasty) solution was to read out the coords and store these in a PointInt3D (my simplified int Vector3 version) by multiplying the position by 10 and reducing the y value to the floor (ie. 0, 1, ...). 

For instance an elevator creates X nodes (yellow dots, one for each floor): like [0,0,0], [0,1,0] and [0,2,0]. While I'm at it, I also connect these (so the floors are connected, too).
Then I looped over all floors and and created a temp list of the elements per floor, this list would then be sorted using the x value and viola ... all nodes per floor in order from left to right. Now simply connect Node[i] and Node[i + 1] and the floor is connected. As I had created the links between floor earlier, creating the complete graph (red lines) was a no-brainer.

Of course it isn't quite as easy as this, just look at the map and notice the green line marked "No! No! No!". I fixed this by .... well let's just say it is a dirty trick...

The path (blue line) is created by a simple "Pathfinder.GetPath(StartNode, EndNode)".

How the goons deal with that is for the next post, as this one is already long enough.

-- Olli


Sibling Rivalry and How to Stop It

Having three goons running around, but only a limited number of elevators is calling for trouble. So in order to make that work ("Only one goon per elevator, please"), we had to come up with something really clever (well, almost).


The first obvious option might have been to make the goons talk to each other and let them decide which of them will enter the elevator. Not the easiest solution and there would have been a lot of back and forth between the goons just to make sure they talk about the same elevator.

The second option was a central piece of code that sorts goons and elevators, group the ones belonging together and then decides which one will enter the elevator (not a piece of cake either).

Luckily, option three is just what we need, it's almost clean, it is simple and if it fails it sorts out itself after a while.
Last post I mentioned that the goons look ahead and "decide" what to do with the target (doors, walls and elevators [and player]), so we use this to lock the elevator as well.
I added a simple flag ("claimedBy") to the elevator code (which makes them move up and down) and that was it (OK, not quite, but mostly).

With this in place, only a few things needed to be added to the goon's AI:
If a goon "sees" the elevator and the elevator is not currently claimed, the goon claims it.
If the goon decides to turn away from the elevator after he claimed it, the elevator is released. If the elevator is already claimed by another goon, ignore it and check again next step. If the goon is killed, check if the elevator needs to be released.
That's it.

Let's code these shiny UI icons and make them work, too.

-- Olli

Google Chrome (v42+) and the Unity Web Player

As much as I like the Chrome browser, google sometimes annoys the crap out of me for playing the web police.

If you're greeted with this:

 
when doing a quick test built for friends (using the unity web player), try this in your url bar:
chrome://flags/#enable-npapi
Activate it and don't forget to click "restart now".

Not a pretty fix, but hey ...

-- Olli

Rot: PixiJS Depth sorting and performance

I thought I'd do a techy post for a change, it's been a while hasn't it ?

If you've played the demo or even just seen screenshots you'll know Rot is an isometric game.

God damn that tilt shift filter is good

Because the game was always destined for mobile performance is a key issue.

Depth sorting is always painful to do, to do it correctly you're looking at doing a topological sort ( See this excellent blog post for more details: https://mazebert.com/2013/04/18/isometric-depth-sorting/ ) which is fine if you're not running too many sprites, but less than great if you're looking at a silly number of particles, and Rot is all about a silly number of particles.

Let's backtrack a little. The display is made up of various play fields ( Layers ), the background is burned into one large sprite, on top of that we have the sprites play field ( i.e. all the zombies, particles, pretty much everything moving ) and then a fore ground play field ( There are more, but let's not make this any more complicated than it needs to be ).

Because of having the background / foreground laid out like that we don't have to depth sort them at all, we only have to worry about the sprites themselves.

I added an extra property to each sprite, isoZ. This is just a simple old school depth sorting formula I'm sure you're familiar with, based on the sprites x/y position ( For more details see the link above, or pretty much any tutorial about iso ) and gives us something to sort by.

Along with that property we also added a new method to the DisplayObjectContainer class, zSort(). This method loops through all the children in our sprite play field and tests if they're visible or not, if they are they get shoved into a new visibleChildren array. This is because we only want to sort sprites we actually care about, visible ones.
We learned a lot about performance working on DN8 for iPad, and one thing was to not add / remove children when they were needed, there's a large overhead for that, so when we start a level we add nearly all the sprites at once so they're there ready and waiting for when we need them ( Things like explosions are added as needed because in the overall scheme of things they're pretty rare, but zombies and blood are always in use ).


So we have over a 1000 sprites just sitting there waiting to do their thing, but by setting the visible property to false our zSort ignores them ( This is why we check for visible rather than just looping through all the children of the sprite play field ).

This improved performance a lot, the max number of sprites we sort is 512 but in testing even with multiple explosions going off it never hits over 350, well within out limits.

The actual sort code is simple as it's possible to be,

    this.visibleChildren.sort(function(a,b) {
        if (a.isoZ > b.isoZ){
            return -1;
        }
       return 1;
    });

That's it, we don't even really care if two sprites have the same z depth, we're using large numbers for the isoZ value so it's a little unlikely and even if it does happen, it'll be for a 60th of a second. I can live with that.

Now if you've played with doing iso games before you'll know this way can lead to clipping, where the depth sort is a fairly cheap and therefore not as good as doing a topological sort.
Yep.
The objective was to make the depth sorting good enough, not perfect. We lose a little accuracy, which hopefully you don't notice when playing ( You will now though ) in return for performance.

So cool, we've pulled out all the visible sprites and sorted them, job done...
( This is my Colombo moment )
... but there's one more thing.

When you look at any sort of display graph, the containers ( Be it a DisplayObjectContainer in pixiJS or the Stage in Flash ) are pretty much just a list of the children. To display them the plotter simply loops through the list plotting one at a time, much like a painter would ( Ah, that's why it's called the painters algorithm, it finally makes sense ).
But we've got a sorted list of only visible sprites, with a little re-writing we can remove some of the checks in pixiJS's plotter loop, we already know all these sprites should be plotted. Further more we can also check to see if the sprite has any children itself, the way the game is set up they usually don't, and if not avoid some extra looping too.

To recap, by doing a simple visibility test before sorting and then using that data we can really improve performance. The zSort method was around the 3rd most expensive function call when profiling the game, that's dropped right down now.

Squize.