Wednesday, 9 October 2013

Easy Paralax scrolling on a 2.5D game

Classic 2D sidescrollers used a technique called parallax scrolling to make their backgrounds more realistic. Classically it was done by making background sprites move at different speeds, thus creating the illusion that some of them were closer to our eyes. While making Slinki we've done some experiments on this and developed a simple way to replicate this technique that will work in any (most?) 3D engines without too much work.

This article may also be useful if you want to make some part of your game "purely" 2D and have other bits be more realistic 3D meshes.

Sonic 4 paralax
Unfortunately you'll still have a lot of work ahead of you to make backgrounds this gorgeous *sigh*


First we need 2 cameras:
  •     A main camera (the orthogonal one) - This one will render nearly all the game
  •     A second camera, a perspective one - This will render just our backgrounds
Setup your background items, and put them on a special layer (we call ours "Backgrounds". Here's an example, the large panels are all part of this layer and they're ordered according to distance:




Make the second camera follow the main camera. In Unity3D you can simply make it a child GameObject to save yourself a small amount of coding. Also make sure the main camera is drawn first. In Unity this is done by adjusting their depths (0 for the main camera, -1 for the background).

Now the fun part: The main camera should NOT draw the background. This may vary depending on the engine you're using. In Unity you can simply put the backgrounds on a different layer and tell the main camera not to draw it using an occlusion mask. Make sure any empty space rendered by the gameplay camera will fail the depth-test (on Unity this means setting the Clear flag to "Don't Clear").




Make the second camera draw nothing EXCEPT objects in the background layer.


How this works

The first camera will be set to draw all the foreground items and will leave empty space for the second camera to draw on. The second camera will draw the backgrounds in that empty space, using perspective, doing precisely what a parallax scrolling effect tries to replicate.


Here's a couple of animations showing the game in pure orthogonal mode and with our "paralax scrolling".
Entire game in orthogonal projection

Backgrounds using perspective camera


Monday, 9 September 2013

Simple AI in Unity3D

Here's a short writeup on how we're doing the enemy AI for our most recent game, Slinki. I recommend you read up on C# delegates and Unity coroutines if you're not familiar with either.

We decided early on that the enemies should have really simple behaviours. For instance, here's an example of how the Shorg works on the newest version:
  1. Wait until Slinki comes close
  2. Appear and jump out once he's close enough
  3. Wait for 2 seconds
  4. Jump towards slinki a certain small distance
  5. Go to 3
Things like these are really easy to implement using easy AI techniques such as state machines.

The method

Create a new MonoBehaviour for your AI. It should look like this:
//this is like a template for all our states
public delegate IEnumerator State();

//the current state
private State stateFunc; 

//seconds between AI updates
public float AIupdateFrequency = 0.1f; 

void OnEnable() {
 //Sets the first State
 stateFunc = StateWait;
 StartCoroutine (Action());
}

public IEnumerator Action() {
    while (true) {
        //Waits untill stateFunc is done before proceeding
        yield return StartCoroutine(stateFunc());
    
        //Waits for AIupdateFrequency so we don't busy-run our AI logic
        yield return new WaitForSeconds(AIupdateFrequency);
    }
}

Here's an example of a possible state method. This one just makes Shorg stand still for 2 seconds before changing to the "Hop" state.
IEnumerator StateWait() {
    yield return new WaitForSeconds(2);
    
    //next state
    stateFunc = StateHop; 
    yield return null;
}

Here's another state method, this one applies gravity while Shorg is airborne. Once he lands he goes back to waiting.
IEnumerator StateAirborne() {
    kinController.jumpSpeed = -kinController.gravity * AIupdateFrequency;

    if (kinController.isGrounded) {
        stateFunc = StateWait;
    }
    
    yield return null;
}

Guidelines

The "rules" for writting new states are simple: Following the delegate - they should be functions that return IEnumerator , they should end in yield return null,  and they need to have one or more conditions for changing the stateFunc variable (i.e. change to another state).

 

Summary

Advantages of this method:
  • Simple
  • Easy to create new states
  • Very easy to debug just using prints
  • Self destructs cleanly if the GameObject is destroyed or disabled
Disadvantages
  • Can get complicated as the AI gets more complex
  • No way to enforce the guidelines due to the way Unity and C# work
  • Coroutines can get a bit funky to use for an inexperienced programmer
  • State is lost if the gameObject is temporarily disabled

Special thanks to David Craft for this amazing hack that allows code syntax highlighting on blogger


Note: If you need to temporarily run the AI logic more often than AIupdateFrequency will allow, all you need to do is yield inside a cycle. This probably sounds confusing so here's another version of the Wait state. In this one Shorg turns towards the player before waiting:

IEnumerator StateWait() {
 
    //Facing wrong way?
    while (Vector3.Dot(transform.forward, slinkiDirection.x * Vector3.right) < 0) {
        transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(dir), Time.deltaTime * 100);
        Debug.Log("Turning around");
        yield return null;
    }
 
    //Debug.Log("Waiting for 1 second");
    yield return new WaitForSeconds(1);
    stateFunc = StateHop;
}

That while cycle will make the coroutine run every frame update. Without it, Shorg would only try to face the player once every 0.1 seconds, producing a very jerky animation.

Monday, 22 July 2013

Poultron: Bonus

Since a new version of unity came out today with realtime shadows I figured I might as well make a new version with them on.

Shadows!

EDIT: Now actually with shadows as of the 22nd of August

Sunday, 21 July 2013

Poultron: Final day


And to think it looks so small from up here...

The main problem with making a game that's designed to be frustrating to play is that playtesting is hell. In the end I think I made it too easy and removed most of the ramps as I couldn't figure out if they were actually climbable. Oh well...

The credits sequence ended up taking up most of my spare time. It was basically just my name and a list of assets used but a neat little thing to figure out nonetheless.

In the end I think this was a neat little experiment and I might do a post-mortem soonish. I might even compile a list of issues I had with Unity (like the fact prefabs are not clearly marked, which might result in you changing a lot more things than you'd hope when tweaking certain values).

Here's hoping you'll enjoy it.

Saturday, 20 July 2013

Poultron: Day 6

  Been very busy, can't remember most of the things I've done today.


Features:
  • More slight graphical tweaks
  • New flying enemy! (took up most of my time)
  • Landscape is slightly more interesting
  • Keep walking and you'll find new enemies (eventually)

Current issues:
  • Still no endgame :(
  • Enemies pop up in front of you. The level will be tweaked tomorrow.

Tomorrow:
  • Ending and credits
  • Finish the level
 Abandon all hope ye who enter here.

Poultron: Day 5


I just noticed my pilot looks eerily similar to the default minecraft dude

Time's starting to run out! I still have no flying enemies and the level's still mostly empty! That being said, the game now has a menu of sorts and a second robot to choose from.

 Features:

  • An interactive menu and intro sequence
  • A new robot to fall in love with (not recommended for people with low self-esteem)
  • LASERS!
  • Slight graphical tweaks here and there
  • Wobbly feet
  • I'm starting to lose track to be honest

Current issues:
  • Footstep detection is a bit wonky
  • We need an endgame 
  • You can hear the tank trying to shoot outside the hangar (will be fixed tomorrow)

Tomorrow:
  • Make the level!
  • Hopefully put in the flying enemy

Embark on an adventure of a lifetime by clicking this link

Thursday, 18 July 2013

Poultron: Day 4



The closest you'll ever be to his pretty face

I tried to go with no health system and I like the results. However, this made me spend most of the day rewriting the projectile system into something a lot more physics-based. I also spent some time polishing up the robot and some other features.

 Features:

  • Enemy bullets can now hit you and will make it harder for you to keep walking
  • Footstep sounds!
  • Rate of fire limitations on your own mech (the huge cannon is no longer semi-automatic)
  • The robot looks 20% cooler and features a tiny pilot (which I might animate if I feel like it)
  • Dings!

Current issues:
  • Footstep detection is a bit wonky

Tomorrow:
  • I might make the "shoot" button a keyboard key if it doesn't make the game too easy. I intended to keep it on the screen as an added challenge.
  • Maybe make the feet separate parts to make walking seem smoother and more realistic (also should help polish the footstep sounds)
  • Begginings of robot number 2 (aka hard mode)
  • Make the menu.
  • Put flying enemy into the game if we're very lucky

This link over here should take you on today's adventure.



Wednesday, 17 July 2013

Poultron: Day 3


My gun is slightly bigger


Spent most of the day doing other non-game related things like going to the dentist and such. Despite this I think I made quite a bit of progress. Most of it can be summed up as "cleaning up" the messy code and fixing lesser issues.

Features:

  • Cool special effects for the bullets!
  • Graphical tweaks, sort of... Well at least everything should look shinier now .
  • The tank now runs away from you!
  • It also shoots back (bullets hitting the robot may not actually do anything yet. Batteries sold separately.)
  • Made the gun mount more "rigid" (it now doesn't wobble every time you shoot). This means it's now harder to use the recoil as an improvised jetpack (sorry)
  • Did you know the tank had moving tracks? Well now you'll notice they exist.

Current issues:
  • THE BULLETS, THEY DO NOTHING. Should I make the mech have a health bar or just make the shots move it back a bit and make it harder to move?
  • The tank dies in one shot
  • The tank explosion's effect disappears suddenly. This won't be trivial to fix unfortunately.
  • Bullets still do nothing when they hit the ground
  • As you can see from the screenshot, that shell might be slightly bigger than it should
Tomorrow:
  • Consider implementing a health system or not.
  • Make a menu?
  • Tweak the interface?
  • More graphical tweaks?
  • Model a flying enemy.
 As usual, amazing fun awaits thee here.

Tuesday, 16 July 2013

Poultron: Day 2

Added a decent sky (from the awesome SkyBox valume 2 found on the Unity store), made a geodesic dome for scenery and decided on going for a WE'RE IN SPAAAACE theme.

I spent most of my day implementing the ballistics system. What I currently have is probably not the best solution but it works. There's bullets, that can collide with level geometry (like the ground, buildings, etc) and there's Hitboxes, that can only collide with bullets. Once a bullet touches anything it checks to see if that object has a hitbox. If it does, it triggers a death effect.

Features:
  • A small tank that walks up to you and says "Hi" (ok, it doesn't really say "Hi" but you get the idea)
  • Longer legs for the mech (it was hard aiming down and it made the controls a bit easier but not too much)
  • Bullets that do things
  • Explosions!
  • SKY! (the moon was my own personal addition, boy do I feel proud)

Current issues:
  • The effects should be tweaked to make them more coherent (and cooler)
  • Bullets impacting the ground just disappear. This simply cannot do
  • The poor little tank doesn't fight back
  • The tank was programmed to keep his distance but that doesn't seem to work
  • In related news, you can walk right over the tank and nothing happens
Tomorrow:
  • Fix all the tank issues
  • Maybe make the tank shoot back
  • Improve the explosion effects (graphics and sound)
  • More things to prettify the scenery (maybe a small corridor uniting several domes, that would be nice)
You may make fun of my accomplishments for the day here.

I modelled it after a Panther and a Leopard 2.
Yes I'm aware only tank geeks will know what those are.

Monday, 15 July 2013

Poultron: Day 1

I expected to have more done in the first day but all thing's considered it wasn't that bad.

You can move the little robot around and shoot. It's still a bit glitchy and I'm not sure if I'll be able to iron out all the kinks without churning out my own physics system.

Features:
  • Walking!
  • Shooting with animations and recoil
  • Screen shakes if you hit the ground going too fast

Current issues:
  • Sometimes the foot gets stuck in an awkward position and we have to lift it up again. (should be fixed now)
  • Nothing to do besides walking
Tomorrow:
  •  Stuff to shoot! (can't promise any AI)
  • More things to prettify the scenery
  • A decent sky I hope
Click here if you're feeling brave and want to see how it plays out.

Poultron: Intro

To unwind a bit from working on Brian Storm for almost a year, the guys at Titan Forged Games decided to do a small one-week (starting today) game jam with the least busy members of the team. It was originally meant to be one artist and one programmer but due to the intricacies of fate I now find myself alone working on a small prototype I call Poultron.

But what is Poultron?

Let's start with where the idea came from. For some reason I was thinking of Power Rangers and realized it must have been hard to have each person in the team control a different part of the robot. I imagined it would be something like multiplayer qwop.
Obviously such an idea can't go to waste. I quickly wrote up a small story (I'm weird like that):

The peaceful people of the planet Pa'inis realized the universe was eventually going to be attacked by an evil empire of anthropomorphic aliens (and by anthropomorphic I mean humans with a slightly blueish skin, but that's beside the point here). In order to defeat them they did what an ancient people focused on saving the universe usually do: build a huge modular robot which has to be assembled by different parts, each driven by a different teenager.

Soon, the rest of the universe followed suit and built there own robots just in case.

Eventually the evil guys came (they were pink) and the defence robots were activated. However by this point no one was entirely sure which parts belonged to which robot. Not to mention teenagers are not famous for their driving skills...

 Eventually I found myself with no artist and had to lower my expectations: instead of a friendship crushing game I would have to settle for single player one (as I had no one to play with for every iteration I made).

The art style (or lack thereof)

While the decision to make this single-player (for now) fixed some of my immediate concerns, this still left me with another problem: the art style. I'm a programmer guy that writes code, not an artist.

As you can see, this proves I'm indeed a programmer

I started doing some sketches (slightly better than the one above) when it hit me: I could try going for an intentionally bad "made of paper" look for the whole game. I mean the whole idea was to make goofy looking robots doing goofy things. It took me around 5 entire seconds to sketch the parts of a robot and a couple of hours to crop the pieces, build some 2D shaders and put it together.
OH GOD KILL ME NOW
This led to some other problem: if the mech was made of paper this would lead to some expectations that the universe would be entirely made of paper: soon I had a grid paper sky, with paper menus that floated away softly when you clicked on them and... That was it. I had no idea where to keep going with the paper motif. How could I make firing a projectile interesting without non-papery particle effects? When I was testing out hit sounds nothing felt natural - I couldn't just pretend the robot was a huge construction made of steel when the player could clearly see it was made out of pieces of paper.


So I went back to the drawing board and settled on another approach: I am fairly decent at making 3D models and animation but I suck at texturing. Maybe I can get by with a plastic-y/cartoonish look without too much effort.
Hopefully by the end of the day this thing will be doing things already
Despite looking like the least practical design ever, it will probably the easiest robot you'll be able to pilot in Poultron :)

Saturday, 6 April 2013

Unity3D Version control with Dropbox and Mercurial



After a few months I think we're ready to share our Unity3D (free) version control setup. Keep in mind this is not ideal and it was designed to hack some sort of code tracking into the free version of Unity. We are using mercurial but there isn't (shouldn't be) any reason it wouldn't work with any other type of version control system. Always be aware you shouldn't have more than one person editing the files that are not on your VCS.

I'll assume everyone reading this has a basic knowledge on Mercurial and Aliasing/Symlinking and go straight to the point. If you need anything more specific feel free to comment and I'll consider adding it.


The concept:

There's 2 types of files in our project: binaries which we don't/can't synchronize (Unity Pro and the asset server solves this somewhat) and code (text) files. We don't want to do version control for binary files. Let's begin by putting all our binary files into a separate folder. This is what our project's hierarchy looks like:


 

Setup:

First thing's first, launch your project and go to Edit->Project Settings-> Editor. In the inspector change the version control mode to meta files and Asset Serialization to Mixed mode. This means from now on all the data on your Prefabs, materials, scripts, etc will be store in .meta files in their respective folder instead of clumped up in the Library folder.




Basically we just shove everything that's not a text file into the Binaries folder. Close unity, take this folder and put it's contents into a Dropbox folder (we'll be using "\Titan Forged Games\Brian Storm\Unity Project\Assets\Binaries").

Create the repository. This is the contents our .hgignore file (aka the files and folders our repository should ignore):

syntax: glob
     Library/
     Temp/
     Assets/Binaries

     *.userprefs 
     *.pidb
     *.unityproj
     *.csproj
     *.asset
     *.cache

    Assembly-CSharp-vs.csproj 

    Assembly-CSharp.csproj
    ourProjectNameGoesHere.userprefs

    *.orig

    *.orig.meta



The Library folder should never be synced. Doing so is a recipe for disaster. It has local data regarding the project and will always be regenerated based on the .meta files. The library folder will ALWAYS be unique for every person so DON'T even try to sync it and always make sure it's not being shared (we almost lost an entire project due to a silly mistake with the Library folder being corrupted on a single machine).

The rest of the list exists mostly to keep useless binary data or personal preferences from our repository. The .orig are files generated by mercurial if you wish to store backups of files before a merge operation - feel free to ignore that line (it's just personal preference).

 

How to use it:

Clone the repository.
Create a symlink (or shortcut) for the binary files in the Dropbox folder.

In our most current project we're using the dropbox folder "Titan Forged Games\Brian Storm\Unity Project\Assets\Binaries" to "place" binaries into our repo's "Assets\Binaries"

On windows 7 (and 8) you can launch the command console and type: mklink /J "YOUR REPO PATH\Assets\Binaries" "C:\Users\YOUR NAME\Dropbox\Titan Forged Games\Brian Storm\Unity Project\Assets\Binaries"

From now on, everything that is on "C:\Users\YOUR NAME\Dropbox\Titan Forged Games\Brian Storm\Unity Project\Assets\Binaries" will be identical to
"YOUR REPO PATH\Assets\Binaries"


Notes:

  • Don't ignore the newly created .meta files when commiting a new code file. They are what allows Unity to know if your GameObjects use a certain script (otherwise you'll just get missing script Errors on GameObjects that use them).
  • When testing things out and doing drastic changes it's best to avoid people tweaking an editor scene (besides not being able to work on the same scene at the same time, it's also likely he's messing with inspector attributes that will no longer exist once you commit your code).
  • The silly mistake I mentioned earlier deleted all our binaries on the dropbox folder. Don't be silly and do regular backups of the Binaries - in fact, just backup your entire project once in a while, you'll be thankful for it some day.