Archives

All posts for the month October, 2012

Unity Script Reference has some good info on making a custom editor, but all the examples use JavaScript.

I couldn’t find a decent C# example, so I’m writing one. I’ll show how to make use of custom editors to do away with those pesky public fields, and to constrain an input value using a slider.

UPDATE: The method below does not work in the latest releases of Unity 3.5, since Unity 3.5.5f3 or earlier. I have added an updated version that works for the current release of Unity 3.5, so I suggest referring to that after getting an overview from this post.

So let’s say I have a simple script that has a single customizable integral value:

// MyScript.cs
using UnityEngine;

public class MyScript : MonoBehaviour {
    public int MyValue;

    void Update () {
        // MyValue should be between 1 and 10 inclusive
        MyValue = Mathf.Clamp(MyValue, 1, 10);

        // do something with MyValue
    }
}

The main thing to note here is that we’re directly exposing MyValue as a field. This is generally considered bad coding practice because it means we have no control over how the value is set. This means that any time we want to use the value, we must first make sure it is valid, which adds extra code to distract from the core behaviour we’re writing.
Update: Here I am using Mathf.Clamp(…) to force myValue between 1 and 10 inclusive, but keep in mind that this one of the simplest checks we’ll ever need, and we could easily have something more complex. Since it is used in update, the check will also be run dozens of times per second regardless whether MyValue has been changed.

Setting an invalid value is easy with public fields.

I’ll come back to the public field issue later in this post, but for now I’ll put it aside and show how to at least make sure a valid value is entered through Unity’s inspector. You can get an overview of what custom editors are all about using the link at the top of this page. Suffice to say they are a means of taking control of the value input for a script in Unity’s Inspector.

To add a custom editor, you must add a script in Assets/Editor. The location is important, this will not work if the script is in the wrong place.

// MyScriptEditor.cs
using UnityEditor;

[CustomEditor(typeof(MyScript))] 
public class MyScriptEditor : Editor {

    public override void OnInspectorGUI() {
        MyScript myTarget = (MyScript) target;
        myTarget.MyValue = EditorGUILayout.IntSlider(
                "Val-you", myTarget.MyValue, 1, 10);
    }
}

There are a few things to note here:

  • We’re using UnityEditor rather than the usual UnityEngine, and the script is extending Editor, not MonoBehaviour.
  • We tell Unity which script to use this for with the annotation [CustomEditor(typeof(MyScript))].
  • We override the OnInspectorGUI() method to hook into the generation of the section in the inspector for our script.
  • The script instance that is being edited is available as target. Due to C#’s strict typing, we must cast it to the appropriate type before calling any type-specific methods on it.
  • I’ve used an intSlider to allow setting of MyValue to values only from 1 to 10. Check out the EditorGUILayout documentation for others.
  • I’m using “Val-you” as the display name just to illustrate that you can use any name you want, although I would recommend sticking with the property name to avoid confusion down the track.
A slider can constrain the input value to the desired range.

Note: I had some issues when I initially added the editor script – an error message in the console claiming that the script didn’t exist. It turned out this was just because it hadn’t refreshed properly for the currently selected GameObject. All I had to do was select something else, then re-focus the selection, and the error went away. If you get errors but can’t figure out the cause, I would advise first saving the scene and re-starting Unity to make sure everything refreshes properly.

Update: to keep the default inputs for any public fields in your script, insert the line base.OnInspectorGUI(); at the beginning or end of your overridden OnInspectorGUI() method.
This comes a long way to solving the invalid value problem, but leaving MyValue public means that another script could easily set the value outside our desired range and mess everything up, so we still need to check for a valid value. Update: we also still have the efficiency issue of running the check far more often than we need.
So what are the alternatives? In general the approach is to make the field private, and provide “getter” and “setter” methods to read and write the field. In this case they would be called something like getMyValue() and setMyValue(int newValue). The setter method would  be the only way to change the value from outside, so we can perform the validity checks in this one place and be confident the value is always correct, which lets us keep the rest of the code much cleaner.

I won’t demonstrate getter and setter methods, because C# provides an even nicer solution: properties. Properties are essentially syntactic sugar that let us define and use getters and setters without as much extra typing.

// MyScript.cs
using UnityEngine;

public class MyScript : MonoBehaviour {

    private int myValue;

    public int MyValue {
        get { return myValue; }
        set {
            // MyValue should be between 1 and 10
            myValue = Mathf.Clamp(value, 1, 10);
        }
    }

    void Update () {
        // do something with MyValue
    }
}
I’ve replaced the public MyValue with a property of the same name. I’m now storing the value privately in myValue (note the lowercase ‘m’ for the private field, C# identifiers are case sensitive). The getter simply returns the value of the private variable. The setter performs the necessary checks and sets the private field to a valid value. Note that in the setter, “value” always represents the value that someone is trying to set the property to.
Because the property has the same name as the public field used to, the editor script is now referring to the property, and no changes are required. The property can be accessed by other scripts, but can no longer set the value to an invalid one, Update: and we no longer have to waste CPU cycles checking for validity every Update().

Happy coding 🙂

Wrap-up

Total development time: 1340 minutes (22 hours, 20 minutes).
The game-in-a-week challenge has come to a close. It has been an exhausting experience, adding a half-time workload to my full-time work week, but also a lot of fun and very rewarding. I haven’t tracked the extra time spent on the write-ups, but it would have to be at least a couple of extra hours on top of it all. Since I’m completely drained, I’ll structure this wrap-up in self-interview format to keep my fatigued mind on track.

Science Crowbar

Does the final product fit what you had envisaged at the beginning?

In broad terms, the game now has all the major elements I expected it to have by the end of the week, but there are some significant differences from the original picture in my head. Most of the differences are simplifications, but a few are due to a combination of rushing and contingency, and one is due to a limitation of the free version of Unity that I didn’t have time to work around.

Simplifications are mainly around visuals, movement and animation: I used only a single scientist model and didn’t use a variety of textures or scales, which would have helped them look less like clones; the scientists aren’t animated in any way when producing science, whereas given more time I would have like them to perform various science-y actions that would be visually linked to changes in the science bar using a ‘flow’ of animated particles to the science bar; enemies have restricted rotation, whereas I would prefer to allow them to rotate freely so they can be knocked over by a well-aimed strike and have to right themselves; enemies teleport to scientist heads rather than being animated climbing up and latching on, which would add the ability to carefully knock or pry the enemy off before it is fully attached, while trying not to hit the scientist; zombified scientists don’t attack their neighbours, which would add an extra dimension to the game and make things more hectic.

Rushing-related changes were mainly the environment textures. I had originally pictured a more metallic grated flooring with some embedded lights and other features, and metallic paneled walls with plenty of consoles, lights and other features, but in the late-stage rush I grabbed some of the first textures I found that looked alright. The room is also quite bare; given time I would have added features such as broken areas of flooring, exposed wiring, miscellaneous fixtures, blood smears, dripping/pooling water, and so on. Mixing up such features as well as room textures and dimensions would give more of a feeling of progressing through different areas.

The difference that I think has the biggest effect on the feel of the game environment is the lack of shadows. The free version of Unity has some significant limitations on out-of-the-box dynamic shadow support, and the limited timeframe left me no opportunity to look into alternatives. Without the time constraint I would have spent the necessary time to get something akin to the shadows in Alien Swarm.

How does development with Unity and C# compare to development with SDL and C++?

I won’t make a direct comparison between SDL and Unity, that would be pointless since SDL is a simple wrapper around low level APIs and Unity is a fully functional game engine – it’s an apples and oranges comparison. I could compare the languages but I’d be writing all night – suffice to say that C++ is a lot easier to get wrong and a lot slower to develop.

The more relevant comparison to make is the overall experience. Working with C++ and SDL is all about building up from nothing and putting together something over which you have complete control. The control is nice, but it comes at an enormous cost in time. Unity does a lot for you, primarily with asset importing and management, and with object interaction, but also in numerous other areas too extensive to list here. This makes a huge difference to the development process: it lets me be thinking about what elements I want in my game and how I want them to interact with each other, without being dragged down into the minute detail of exactly how everything will be rendered. In short, Unity gives you the wheels so you don’t have to invent them, and throws in the chassis, engine, drive train and diff for good measure. They leave the steering, body-work and paint job up to you.

What aspects of development were easy under severe time pressure?

As a software developer, I’m most comfortable with the coding side of things – in a small project like this I didn’t hit anything that really challenged me in that area. Some other parts were made easy by Unity, such as getting the basic level put together, positioning elements, attaching scripts and dealing with collisions and basic physics interactions.

Scoping was also easy, which sounds a little counter-intuitive  with such limited time, scope-creep was basically impossible. There wasn’t an opportunity to incorporate any new ideas other than the most trivial tweaks and corner-cutting. Since I knew I didn’t have time to add anything, I didn’t waste any time entertaining the idea of major new features.There were also some elements that were made easier simply because I had a good excuse to cut corners. I went for simple movement in a simple environment, so there was no need to start pulling out A* or even greedy search – I’m interested to see what kind of path finding is baked into Unity or available as libraries or extensions – I’ve been directed at A* Pathfinding Project and iTween so I’ll give them a try, probably in my next project.

What aspects of development didn’t hold up well under time pressure?

The major group of activities that didn’t hold up well was anything new. Typically I’ll spend a while reading up on and trying out technologies or techniques with which I am unfamiliar before I start using them in a project, but with less than 24 hours of development time I could only afford to do quick research on things as they came up.

Model manipulation and positioning gave me some strife when combined with parenting. This feels like another inexperience thing, but it gets a special mention because it looks like something with several moving parts, all of which I need to understand to use it properly.

Creating atmosphere gets an honorable mention here too, basically because there wasn’t time for it. Once I have all the major elements in place, I would ideally spend some time playing with lighting, shadows, models, textures, audio and animation to get the game feeling the way I want. I was only really ready for this as I made the last changes to this project, so it was something I just couldn’t fit in. I ended up with a much brighter and more sterile-feeling scene than I would have liked.

Has this challenge highlighted any major gaps in your knowledge?

Definitely, particularly around Unity. This was definitely expected, in fact it was one of the desired outcomes of this challenge. The areas I’m most acutely aware of my lack of knowledge are lighting, exactly how scale is calculated with parenting and instantiation, and an in-depth understanding of Unity’s component model, particularly around object access through parental relationships. By focusing my learning in these areas I can ensure that I maximize my practical skills faster than just trying to learn absolutely everything, which is extra-important when game dev isn’t my day job.

Would you do this or a similar challenge again?

The challenge has been an exhausting experience, but also a very fun and rewarding one. I’ll definitely look at similar challenges in future, after I’ve had some time to recuperate, and with some appropriate changes to help maintain a bit more balance.

What would you do differently in similar future challenges?

I think next time I would prefer to allocate a little more time and a more ambitious project, e.g. Friday to Sunday spanning 2 weekends. This project was fun, and about right for my limited experience with Unity, but next time I should be a lot more on top of the fundamentals so I’ll want to aim for a more polished product with a bit more depth. I could even look at using some leave and taking on something even more ambitious, like getting Grey Out to market in 10 days.

Assuming I was taking a challenge during a work week, I would also be looking at ways to prevent the challenge distracting me too much from other aspects of my life – it isn’t the end of the world to have dishes pile up for a week, but it is something I should be able to avoid. Ideas for this include more specific time constraints during the week (e.g. hard maximum of 2h on work days), and a change to morning-only development (i.e. get it done before work).

Finally, I would encourage others to follow along with their own challenges – the same or different doesn’t really matter as long as they’re happening at about the same time. This challenge was a bit of a spur-of-the-moment thing, but with a little more foresight I’m sure there are plenty of people keen to challenge themselves.

Will you do any more development on Science Crowbar?

Definitely. I’ll keep a copy of the one-week version of it, and make that available soon, but there is plenty to learn as I take the project beyond the working-prototype stage and flesh it out into a complete and polished game.

Update: play Science Crowbar online now! Big thanks to Blocky Pixel for hosting.

Day 7 – Audio Antics

Development time: 20 minutes (running total: 1340 minutes).

Four simple audio samples make a big difference to the feel of the game.
Just a quick addition this morning to round things out. I used my chest, a role of tape and my own voice to sample a few sound effects. The audio isn’t very clean, but it’s certainly good enough for a last second addition before wrapping up the project. I attached the spark noise to the particle emitter prefab that does the spark effect, letting it play when instantiated; for the enemy I added two audio sources for when they’re hit and access them as an array, playing a more crackly sound when they die or if they’re already dead; for the scientists I have a single sound play when an enemy attaches to them.

Goal for the next week: deploy somewhere

With sound, I’m now happy enough to call the project complete, but there is still some work to be done. What good is jamming together a game in a very short space if I don’t share its hurried glory with the world? Stay tuned for a playable web version as soon as I can sort out some hosting, and a wrap-up post with some final thoughts on the project.

Day 6 – Model Mayhem

Development time: 200 minutes (running total: 1320 minutes).

I was so pleased with my crowbar experience yesterday that I set out with the same approach to find models for the enemy and scientist. I hit a few more snags than expected, but managed to put out the inevitable last-minute fires and finish with a working, not-too ugly but very quiet game.
Initially, I looked for a nice tick model to use for the enemies, but decent tick models can be pretty expensive, definitely outside my budget of $0 for this project, so I tried some alternatives and found a nice classic headcrab model by 3dregenerator that’s perfect for my purpose and falls under the Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License, which suits my purpose for now since this is not a commercial project, but is important to keep in mind: if I ever turn this into something I want to sell I’ll have to find an alternative model or seek permission from the creator to use it.
Not quite the size I was aiming for.
Despite an initial scaling issue, importing and applying the headcrab model to my enemies was straightforward. Unity’s prefabs helped a lot here, as I was able to apply the drag a new copy of the enemy prefab, apply the new model to it, make necessary adjustments to related components, then drag the modified prefab copy back into the prefab.
I also ended up locking rotation completely as the most time-efficient way to stop them hopping sideways or backwards – a down side to using a model other than a nondescript blob. A preferred solution would be to allow the enemies to turn and fall over, and have them spend some time righting themselves. While this would look better, there simply wasn’t time for something that falls in the category of extra polish.
New models.
Next was the scientists. With the clock ticking I grabbed the first reasonable scientist model one I found, from the same site and under the same license as the crowbar I found yesterday. These guys just hang around at the bottom of the screen, so I didn’t spend the time to get them posed or animated, nor even to get their textures applied properly, since it would make minimal difference to the final effect.
Out with the old, in with the new.
Things were still looking pretty plain, so I had a quick look around for some textures for the environment. I found a suitable tile pattern for the floor, and a different tile pattern for the walls. The license for these textures is worth noting, since there is a specific limitation on use for Open Source projects. If I decide to distribute my project files I’ll probably have to find alternatives.
These still give a fairly sterile feel, but once again time constraints mean that good-enough will do, and it’s definitely an improvement on the grey. How the scientist got into this room with no doors or windows is a mystery I leave players to puzzle over.
Applying textures to the environment.
I hit some issues with rotation of the scientist model, which I solved by having the scientist GameObject parented to a GameObject with the model that had appropriate rotation applied. This solved the rotation issue but led to a nasty situation where the child object could be moved away from its parent, leading to major problems with enemy attachment as they appeared to ignore the scientists, then start floating in the air at what appeared to be random positions.
Debugging position issues. The box collider was temporarily added to better show the position of the parent GameObject.
I chose the simplest solution to the positioning issue: turned off physics for the scientists. If they don’t move they can’t move away from the parent object. It isn’t a real solution, and some interesting effects such as falling over are lost, but it does make the game work right now, which is basically all the matters with the deadline so close.
Problems with parent-child positioning. Both green wireframes should be centered on the same point.
Almost out of time, there were still 3 issues I wouldn’t want to have in when shipping. The first was enemies occasionally falling through the floor or get knocked over a wall, which made a level impossible to win as the enemy accelerated away to safety. Rather than mess with complicated collision issues, I took a used a simple hack to solve the problem: enemies that find themselves more than a small distance below the floor will immediately report that they have died, then become inactive. Problem solved.
The second remaining issue was that enemies didn’t actually move toward scientists, the would just hop straight ahead and hope they end up close enough to attach, which would often leave them jumping repeatedly into the back wall with a scientist not far away. I solved this one properly, detecting the nearest surviving scientist and leaping in an appropriate direction. It makes for a much more hectic experience as you see the enemies closing in on your final scientist.
Approaching scientists properly.
The final issue was that dead or zombified scientists were only identifiable by the enemy on their head, which was fine until you kill it, then they look fine again even though they aren’t. Ideally the zombified scientists would start attacking their neighbours and need to be put down, but there simply wasn’t time to get that done today, so I’ve gone with a simple texture change to keep them identifiable as standing corpses. Rather than search around for or create a new texture, I tried the enemy texture – with a bit of adjustment to the tiling it was good enough so I stuck with it.
A more distinctive look for zombified scientists.
And that’s it. Bed time on a work night and all the elements are in place, almost; I didn’t get around to adding sound, which would make a big difference at this stage.

Goal for day 7: add sounds, ship it

I noted in yesterday’s post that I could make an argument for sneaking in a little more development on Monday morning. I am now making that argument. The game really needs some sound, but rather than stay up late and feel exhausted at work tomorrow, I’m leaving it until tomorrow morning. It is still within a week since I started on Monday afternoon 🙂
I still need to get to work at a reasonable time, so all I aim to do is sample a few sounds and add them to the major game events.

Day 5 (afternoon) – Surviving with Crowbars

Development time: 90 minutes (running total: 1120 minutes).
Saturday afternoon presented very little additional development time due to an impending social engagement, but I managed to get survival mode working well again, and started the search for better models for the main game elements. I would have liked to do more, but I console myself with the knowledge that I found a decent free crowbar model with very little time investment.
Shiny new crowbar model.
To get survival mode fully functional again, I added a class to keep track of a survival game and had it implement the enemy spawn controller interface mentioned in part 4. Using the same interface made the code in the main controller for starting a survival game very simple. With a few modifications to the UI, I had survival mode fully operational again, with a more modular structure that will be easier to understand and maintain later.
I had considered trying to quickly throw together some basic models of my own, at least for the crowbar and the enemy, but a quick search turned up a nice free crowbar model with an appropriate licence for my use. A quick look through the license FAQ shows that I’m free to use the model as long as I don’t distribute it in a format that someone else could extract and use it, which is something I’ll have to keep in mind when it comes to distribution.
Crowbar scale tweaked to look good from the current game perspective.
Unity made importing of the new model dead easy, so all I really needed to do was tweak the scale to look right and make a few code changes to get the movement correct. Using stock models is a very effective time-saver under such extreme time constraints, particularly for someone like myself with little 3D modeling experience, so it is definitely an option I would look at for future projects, and for the remainder of this project. I’m sticking with free models for now since I haven’t allocated any budget for this project, but while looking around I noticed plenty of decent stock models in the sub-$10 price range, which is definitely worth the several hours I would take to make something equivalent.
New crowbar in action

Goal for day 6: polishing it all off

I haven’t mentioned it yet, but you may have noticed a missing day. Tuesday I had martial arts training, so although Monday was day 1, day 2 wasn’t until Wednesday. That means that day 6 is really the end of my development week, although I could make an argument for sneaking in a little more on Monday morning since I started on Monday afternoon.
The goal for the final day is obviously to get the project finished, but the specifics aren’t as straightforward as just getting everything done; there simply isn’t time for that. Any team that ever wants to ship a product will generally have to make some hard decisions about what they don’t have time to do, and this project takes that to the extreme. There are easily several weeks of work in polishing even such a simple game to make it perfect, but I only have half a day (with those pesky social engagements chewing up more of my weekend).

In some ways the extreme constraint makes the decision a lot easier, as it changes the question from “What can I afford to leave out?” to “What do I absolutely need?” – a far less ambiguous question. I have a basically working game, so really all that’s absolutely missing is visuals and audio. Leaving a little time for last-minute tweaking, that’s all I have time for anyway, so I’ll do that: find models for enemies and scientists, textures for the floor and walls, and sample a few basic sound effects.

Day 5 (Morning) – Sparks Fly

Development time: 270 minutes (running total: 1030 minutes).

This morning was one of those rare occasions when I had just enough time to finish everything I intended. I won’t pretend it was anything beyond luck, but it still feels nice. There is now a visible science stat generated by surviving scientists, gets used up in a burst of sparks when hitting enemies, and gives a nice boost to damage.
Science stat at work.
I used a scrollbar to mimic a progress bar for the science meter, which was very quick and close enough to what I want. The game controller keeps track of the amount, and the code for scientists to generate it and the damage amplification is trivial. I added sparks using a particle emitter – ideally I would use a single emitter, perhaps attached to the crowbar, and have it emit bursts of particles, but I had some trouble accessing the emitter programatically so decided to cut my losses and use the less efficient option of instantiating emitters from a prefab and destroying them after a few seconds.
Death by science.
Not the prettiest sparks in the world, but good enough without spending long on them.

With the science stat working close to the way it was originally envisaged, I tackled the final major problem with gameplay. Up to this point the crowbar’s movement has been limited to a plane a few units above the ground, and had to be waved through the enemies like a magic wand to make them die. That isn’t the sort of feel I’m going for, and meant that mindlessly flailing back and forth was a winning strategy. To get more of a bludgeoning feel, I moved the basic plane of movement up to about the scientists’ head height, well above the hopping height of enemies, and added a bashing animation activated by a keypress.

A jaunty angle
The movement uses a coroutine that activates over several physics update frames. It moves down and rotates forward for 4 frames, then does the reverse. The rotation uses local coordinate space, whereas the movement uses world space – the default local space movement would cause a net forward movement due to tilting of the y axis, which isn’t desired here.

At last, some proper bludgeoning…

With these changes I’m just about ready to try for some sort of difficulty balance, but I’ll be leaving that to the last minute since it’s a task that can balloon out to any number of hours, and I can make up lies about the target audience if people start claiming it is too easy or difficult.

…to death!

Goal for day 5 (afternoon/evening): survival and special effects.

Survival mode isn’t properly functional after the spawner changes made for campaign mode, so I’ll spend a little while getting that back up and running. Tutorial mode can wait until tomorrow or later, but I’ll add some basic instructions to the main menu as a stopgap. I’ll spend any remaining time today on adding some textures, models and audio.

Day 4 – totally playable

Development time: 240 minutes (running total: 760 minutes).

Like day 2, progress was slower today than I had hoped. I spent longer than I meant to and didn’t get get everything done. Unlike day 2, however, I am quite pleased with my progress. The difference? Today’s extra time was all spent making things more awesome!

“And just what is so awesome about it?” I hear you ask. Well, First off I added a class to keep track of a campaign game: things like current level, surviving scientists, and some variables related to enemy spawning rate. The campaign class made implementing campaign mode in the main controller as simple as creating a campaign object and hooking it up to the enemy spawner. The main controller still choreographs level transitions and handles all the menus.

Main Menu – I’ve been ambitious and presumed I’ll manage to get a tutorial level made this week.

On the topic of level transitions and menus, I spent a while beefing up the UI. There is now a proper menu with a few game modes, pre- and post-level overlays, and a game over overlay. Using overlays with a simple button to proceed saves a little development time compared with choreographing the peri-level events with coroutines, and is fine for my purposes. Even so, messing with fiddly GUI code often takes longer than it seems it should, but that’s not where all the time went.

Start your engines!

Level complete!

I also spent a while messing with the spawners, particularly the enemy spawner, to make the game flow for campaign mode simpler. Both spawners can now remove all the objects they’ve spawned ready for the next level. Enemies had a tendency to pile up when they were spawning individually in random locations, so I changed the enemy spawner to spawn waves, with enemies distributed more evenly along the top of the play area. I also added an interface to the enemy spawner that describes some values related to spawn rate. By implementing this interface in the campaign class, the game controller can link the current campaign object to the spawner and they can sort things out among themselves, but I keep the flexibility to hook the spawner up to other implementations for a different spawning experience (e.g. for controlled spawning in a tutorial level).

HUD, and spawn waves

Finally, I messed with enemy activation so that their corpses hang around for a sensible time before disappearing. This was necessary since they appeared to be teleporting when they were recycled, and they could be recycled almost instantly, which was somewhat jarring. This will not be such an issue when spawning is moved off-screen, but who knows when I’ll get around to that?

Game Over!

Goal for day 5 (morning): kill them with science!

With game modes basically working, all that’s left of the fundamental game concept is the science stat and associated damage modification, so that is the task for Saturday morning. I’ll also tackle the bash-on-click functionality to get things feeling nicer and bring the difficulty up somewhat. I’ll evaluate my progress and set new goals around lunch – that should help avoid getting too caught up in minor tasks and losing the second half of the day to useless fiddling.

Day 3 – Lose!

Development time: 200 minutes (running total: 520 minutes).

Don’t worry! It isn’t lose as in development-failure, just that the loss condition is now implemented so it is possible to lose the game. Today’s development was steady and I covered most what I wanted again, with a lot less problems than yesterday. I even made a quick fix to my collision issue before work thanks to a tip from Doolwind.

I spent a while cleaning up the enemy spawning script, and fixing a bug in which enemy transform and rigidbody properties weren’t properly reset during recycling, causing them to spawn in unintended locations. Once cleaned up, the enemy spawning script made a decent starting point for the scientist spawning script, I just had to remove some unnecessary timing elements and make a few adjustments.

Scientist spawning.

I added some extra walls to keep the enemies in, and added inert box colliders to the spawners to make their scale visible, since I’m using it determine the area in which to spawn things.

With the scientist spawner able to determine when all the scientists have been attacked, it was time to add some higher-level choreography to the scene. I created a basic game control script that keeps track of game state and game mode, with a few methods the spawners can hook into to report important events (enemy and scientist deaths). I added a display for score (just the number of enemies killed at this stage), and a simple label to indicate game over state.

Game Over!

Finally, I had the game controller hook into the enemy spawner and start turning things up as the score increases, for basic difficulty scaling in survival mode. This only works up to a point, as the enemies have a lot of trouble once they start to pile up, but it’ll do for now.

Increasing difficulty (still needs some work).

Goal for day 4: Campaign Mode and Science!

I didn’t get to the win condition or campaign mode today, so those are first on the agenda for tomorrow. Campaign mode will be made up of levels that have an increasing number of enemies to defeat, gaining an extra scientist between levels. I don’t anticipate a lot of complications, just a bit of rearrangement in the spawners and a bit of extra state for the controller, so I should also have time to add the science stat, and possibly move the crowbar up and have it swing down on mouse clicks (for a more satisfying bludgeoning experience).

Day 2 – Stumbling Time

Development time: 180 minutes (running total 320 minutes).

After such smooth sailing on day 1 I was hopeful and naive. I sat down this afternoon enthusiastic and ready to dive into development and get a lot done. I started out well and managed to complete most of what I had planned, but my inexperience with Unity tripped me up somewhat along the way, and overall I spent longer than expected and didn’t feel like my progress was very good.

Issues

The first stumbling block came in the form of colliders and triggers. If there’s an easy way to have both a trigger collider and a physical collider I haven’t found it yet. I was loath to give up my ability to shove the enemies around, so I ended up spending a bit longer than I should messing with parenting and other things. Eventually I went with the simple option that I should have started with – just set the crowbar collider as a trigger and let it pass through things. While cool, the physical interactions aren’t essential to core gameplay so they can wait until I’ve done a bit more reading.

I hit several issues adding enemy spawning, none severe but the extra minutes add up under severe time pressure. First my script wouldn’t run, which appears to have been caused by a naming mismatch. Once it was running I wasted a bit of time trying to invoke a coroutine incorrectly. Finally, I messed around too long trying to add spawned enemies to a list and as children, basically because I wasn’t sure of the type of a returned object and didn’t check the example or documentation as soon as I should have. I wasn’t trying to do anything too unusual here, and I can put all of these issues down to simple inexperience.

Lessons

I know that with a bit of practice, all these problems will start to look very naive. They already seem at least a little silly as I’d already seen some of the solutions in the tutorials at least once, so some of the wasted time was unnecessary. Since wasted minutes are such an issue in this project, I’ll put the lessons here to ensure that for the remainder of the project I don’t waste more than a few seconds on issues I’ve already encountered:

Progress

Despite hitting some snags, I managed to get through most of what I intended: enemies now spawn at the top of the play area and head towards the bottom; enemies lose health when colliding with the crowbar, proportional to its speed; enemies stop moving and change colour when their health falls to (or below) 0; dead enemies are recycled to spawn new enemies.

Enemiy spawning.

I didn’t have time to get scientists spawning, but that should be trivial after working out all the issues with the enemy spawning script. I wasn’t planning to remove the physical effects of enemies colliding with the crowbar, so I want to get that back at some point – either with extra colliders or just by manually changing velocity in the collision event – but other things are higher priority at the moment. The important thing for now is that I can now bludgeon head ticks to death to take out the frustrations of development snags!

Enemy death (red == dead).
Spawning enemies with the spawner as parent.

Goal for day 3: win or lose

Scientist spawning will be easy, and with it I’ll be able to keep track of the scientists and decide when they all have a blob latched onto their heads, so I’ll get the lose condition implemented in the next session. Winning should be simple as well – count spawned enemies and win when enough have been defeated. With winning and loss, this will be a good time to get some basic menus and HUD done. By the end of day 3 I should be able to have a survival mode and a simplified ‘campaign’ mode working. I won’t commit to more than that, since it’s a lot more satisfying to do more than I planned than to do less.

Day 1 – An Excellent Beginning

Development time: 140 minutes.

I have to say this project is off to an excellent start. Unity makes throwing together a basic environment with some simple objects very easy, so I was able to get a play area with a crowbar, a couple of enemies and some scientists put together in very short order, and had enough time to make a reasonable start on the coding.

The crowbar moves around with mouse movement, the enemies make their way down the play area in hops and leaps until they get in range of a scientist, then they leap at him and spend the rest of their life attached to (i.e. hovering above) his head. The crowbar can be used to shove the enemies around too, which was not directly intended yet but does make the game basically playable.

Everything in the scene is pretty basic for now: the play area is a grey plane with a rectangular prism wall at the back (added to stop the scientists tumbling off the edge when the enemies run into them); the crowbar is a skinny rectangular prism in an attractive red; the enemies are squashed spheres, with a box collider as the sphere collider was making them roll; the scientists are simple cylinders.

If I’ve made good progress with the core gameplay by the weekend, I may have time to mess around in Blender and make some simple models, but that’s a whole 4 days away so I’d best not get ahead of myself – I certainly don’t need fancy models to make it work.

Goal for day 2: clobbering time!

I’ll aim to give the enemies health, give the crowbar the ability to take it away, and have the enemies spawning rather than just having a few at the top from the start. There should also be time enough to have the scientists spawn programatically, and have the game end when they’ve all been attacked. If I get through all that with time to spare, I’ll get some basic menu together, but that’s getting ahead of myself again.