AA Battery - Week 38
Week 38 could best be described as slow… Kind of like the middle movie in a trilogy - more about setting up for what’s coming next, than being a highlight itself. The first part of the week involved getting my pull request with the seaside level prototype merged in, which I’ll go into a bit later as I definitely learnt a couple of new Unity tricks thanks to Sas’s review feedback. Getting that merged was the only real accomplishment for the week - the rest were all new starts or resumptions of other tasks, with nothing quite done yet.
23 July - 29 July, 2018
After getting the seaside prototype level merged in I looked at the backlog and saw two possible next tasks: 1. writing the new crew system or 2. walk / run animations for the enemy soldiers.
I already have a walk animation that is about 70% done, but I know it’s not very good - so I decided to continue reading The Animator’s Survival Kit and finally got to the bit about walking and running animations. I’ll need to a practice a bit first, so I decided to make that the next task I’ll tackle.
Instead for this week I started on writing the new crew system - there’s not much news there… the new system is a lot simpler than the last, which is making the code fairly nice and simple. I suspect I may also have gained some new insights into how to structure code on my latest work project, which is helping me structure this 4th attempt (maybe 5th, I don’t know, who’s counting?) a bit more cleanly than the last one. It’ll probably take most of week 39 to get this into a playable state though, so expect much more about this next week.
I came down with a cold / flu on Wednesday afternoon and so ended up spending Thursday at home alternating between sleeping and laying in front of the TV trying to recuperate. I got through about 3 episodes of that Vietnam documentary I was watching for inspiration (just 2 episodes left now). That documentary is probably one of the most graphically violent pieces of television I’ve ever watched with no punches pulled. I’m not quite sure how to work it into the game yet, but I’m beginning to realise that we will need walk a very fine line between the comedy we are planning and doing justice to the horrors of the cold war.
Since I wasn’t feeling up to coding the latter half of the week, I also spent a few minutes digging around on the Free Music Archive looking for some suitable music for the title screen. The first 20 seconds of this track I linked below is damn near perfect, just a pity it’s released under a non-commercial license:
Unity Learnings: GameObject Constructor & LayerMask
The first thing Sas told me about that I didn’t know is that the GameObject constructor lets you specify Components to initialise and add to the GameObject for you, so I changed from something like this:
this.colliders[i] = new GameObject();
this.colliders[i].Name = "The Thing";
this.colliders[i].AddComponent(new Thing());
this.colliders[i].GetComponent<Thing>().setSomething(500);
this.colliders[i].GetComponent<Thing>().setSomethingElse(300);
To something more like this:
this.colliders[i] = new GameObject("The Thing", typeof(Thing));
var theThing = this.colliders[i].GetComponent<Thing>();
theThing.setSomething(500);
theThing.setSomethingElse(300);
Getting the component once instead of multiple times is something I should’ve done from the start, but you can’t deny that the constructor is much nicer than a whole bunch of manual newing up of components (in the real code there were 2-3 components per GameObject, so the improvement is much more pronounced).
The second bit of code that needed an interesting change, was how I was checking which layers a troop was touching in the Movement script, to decide if he should be able to move at the moment. I had the following clunky bit of code with some hard-coded layer names:
if(other.gameObject.layer != LayerMask.NameToLayer("Ground") &&
other.gameObject.layer != LayerMask.NameToLayer("Boat"))
Sas suggested exposing a LayerMask in the component to allow editing which layers would let the soldier move from the Unity Editor. Defining the layer mask was quite simple:
[SerializeField]
private LayerMask movementLayers;
I was not very impressed with the code needed to check whether a contacting layer matched one of the ones in our layer mask… who knew we’d still be doing bitwise logic in our game engines in 2018 - in a C++ engine maybe, but in a high level language like C#?! In this case I’m skipping the rest of the movement method that applies a force to the soldier if layer of the object we are in contact with is not in our layer mask:
if(this.movementLayers != (this.movementLayers | (1 << other.gameObject.layer)))
{
return;
}
Basically the layer mask is a bit mask of 32 bits, shortening it to 8 bits for the example it might look like this if we have two layers that we can move on: 01001000
.
For the first example let’s say it’s a supported layer, so other.gameObject.layer == 3
. The rightmost bit of code ((1 << other.gameObject.layer)
) bit shifts 00000001
left by 3 bits, to become 00001000
. Then the bitwise OR (|
) toggles each bit in the resulting number on if at least one of the two sides are 1:
mask: 01001000
| layer: 00001000
= 01001000
Since that value is equal to the original mask, that means the touching object’s layer is in our mask, so we proceed with the movement logic.
For the second example let’s say we have other.gameObject.layer == 2
, which is not in our mask. So this time the bit shift yields 00000100
and the bitwise OR works out as follows:
mask: 01001000
| layer: 00000100
= 01001100
Since this result is not equal to our mask, that means the bit fell outside of the masked area and we do not proceed with the movement logic.
That’s it for this week’s update - hope the bits of code here at the end are useful - if you do find a better way to do any of that please drop me a comment below.