Saturday, 15 February 2014

Regarding Meshes in Unity

Maybe it's just my OpenGL (1.1) background but here's a few roadblocks I've hit while doing procedural Mesh generation in Unity, along with a few tips not many people seem to know of. Some of this knowledge has been useful even outside my procedural experiments.

Quick Overview (stuff you really should know)

  • You will read this until your eyes bleed
  • Mesh.vertices contains your vertices. Mesh.triangles contains indexes to the vertices array. 
  • Normals (and UVs) are per Vertice. E.g.: Mesh.normals[i] has the normal for Mesh.vertices[i] (Blender uses normals for each face, which sometimes confuses people)
  • Different materials means different submeshes (or a new Mesh if that's what you're into).

A few pitfalls and tips

  • Mesh.uv1 != Mesh.uv (WHY AREN'T MY TEXTURE COORDINATES DOING ANYTHING?)
  • The backface is determined by the order of the vertices in each triangle, NOT its normal. If your mesh looks like it's inside out this is probably why.
  • Some of Unity's built-in shaders (namely the bump mapped ones) do not calculate their own tangents. Each Mesh has their own tangent array for this specific purpose. Unfortunately they can't be auto-calculated.
    • Blender files do not have these by default but fortunately Unity can calculate them automatically. Sadly, we don't have access to their algorithm for this.
    • Fortunately there's some code floating around that works. 
  • Don't generate a new Mesh() every time. Use the same mesh instance and .Clear() it. New meshes will get fed to the GPU but won't replace the old data there, causing memory leaks.
  • 99% of the time you can just call Mesh.RecalculateNormals() at the end instead of reinventing the wheel and calculating your own normals. As far as I know this calculates the normals based on the order of the vertices.
  • When you add a collider Unity will automatically fit it to the current Meshfilter's bounds.

Monday, 3 February 2014

What a good F2P model looks like

Out of all the F2P games I've tried, Warframe has by far the best microtransactions I've seen. So much so that I've been meaning to write this article so I know what to do if I ever find myself in a similar position. However, let me just say this is not a review, just an overview of their Business Model and why I think it's great:


An Excalibur Warframe proudly proclaims: "I have the poweeeer!"

The paid exclusives

In Warframe there's only 2 things where you need to spend money: Slots and Colours. The free currency you're given at the start can get you quite a few of either and you start out with a decent (but small) selection of colours to give your character a unique look.  Everything else has a chance to show up in random "alerts" or invasions. These events are quite common, however it might take some time until you're lucky and find what you need (I didn't say it was perfect).
You can also purchase boosters but I will get to those later on.

Purchases are permanent

No "renting" costumes or any such bullshit. What you buy is yours forever. When you're purchasing a virtual product you shouldn't have the added insult of having them fade away after some time. The mods system is also amazing and you don't lose anything by trying out new builds.

It's (always) fun

Digital Extremes is an experienced game company. The game looks great and has a lot of "crunchiness". There's a great feeling when your properly modded machine gun is blowing chunks out of the heavily armoured Grineer. Or when your saw-launcher slashes infested into (literal) pieces. All the weapons feel useful in some way (although the community swears some are considered overpowered, as some always are). The game is also based on PvE fights and doesn't have many of the issues of the more competitive games in it's genre. Even so, an experienced game company can turn their amazing game into a grindy, boring mess when trying to get the average free player to give them their money.

Defence missions are basically seeing hundreds of these flying everywhere while a Nova does all the work

No grinding

Sure there's some grinding. Without wanting to go too in-depth into the mechanics, you'll need to level your Suit and your weapons to level 30 to guarantee maximum effectiveness, but a single day's effort is all you'll need to fully level an entire set. You can buy boosters to drastically speed this up if you just want to spend a few hours levelling your gear.

There's always a new reward around the corner. This mission you did just levelled your Pistol. You can now put a slightly better mod on it. How about sticking that multi-shot you got 2 missions ago? Or maybe you now have enough nano-spores to craft that new gun... I rarely find myself looking at the end mission screen and not having anything new to fiddle with. You'll never hit a point where the game will push premium content in order to make it less tedious (I'm looking at you World of Tanks).

Weirdly enough (in the F2P industry), they're also moving AWAY from tedious farming and some extremely rare resources have been made more common or easier to obtain. Eg. : When I started out, Warframe parts used to be rare drops from bosses that you had to pick up once you killed them. You now always get warframe piece every time you kill a boss and you don't have to go around looking for his corpse in case you missed it.

Insignificant timers

Crafting guns takes between 12 and 24 hours and putting together new Warframes (classes/suits) usually takes 3 days. You can rush these for real money but, besides the 3 day wait (along with time to craft each piece that makes up the warframe), it's pretty managable. You'll most likely still be levelling your current gun when the new one's ready at the forge (I currently have around 5 primary weapons ready to be picked up).

Reaching out to the players

Warframe has patches released relatively often (every 2-3 weeks I'd say) which add new content (like new tilesets, weapons or maybe an entire overhaul of the damage system). When there's a need a hotfix will be released ASAP. What does ASAP mean? Literally 3 hours after a patch. There's also the hilarious "red text" that always precedes these releases:



In short, they tell the community what's wrong: when they screw, they work on fixing it and then tell everyone what just happened instead of compiling a changelog and running it through QA for a few weeks (I honestly envy their ability to do this and still have an incredibly bug-free game). They invite everyone in-game to watch their live Twitch livestreams so they can know what's up and there's even a reward for everyone afterwards.


Overview

That being said, here's a rundown along with some bad things:

The good:
  • Levelling/grinding is quick and constantly rewards you
  • You only need to pay if you want to. There's nothing that affects gameplay which you can't craft.
  • Decent aesthetic customization by default
  • Developers that feel like human beings
The meh:
  • I don't get why there's an extremely rare item that doubles your mod points for any object. It ensures that you only use it on weapons you really like but I really don't see why there's a weird item that can double the efficiency of any gun or suit.
  • Market for buying and selling things. Nothing to add here, it's still limited to only a few types of items and the real-money currency.
The bad:
  • That 3 day wait for crafting a Warframe. Ugh. I can take it once I have several to choose but when you're starting out, it just sucks.
  • The weird rare item that can double the efficiency of a weapon is on the "meh" heading because I don't care that much for it. But it is available for purchase with real money. The PvE nature of the game limits the consequences of this. However...
  • They have recently-introduced PvP duels. I would like PvP to remain a side-feature so the P2W threat doesn't ever rear it's ugly head but we shall have to wait and see what they do with it.
  • Getting a particular item that only drops from the Void missions can be a serious pain in the neck.

Phew that was hard to write, I kept having to stop myself from writing a review several times. Nevertheless, Warframe is quite enjoyable and I think anyone that's slightly interested in the shooter genre (or multiplayer game design) should give it a go.

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.