My experience with Unity in creating an arcade style game

July 27, 2016
protect

My name is Martino, I run a one-man company called Eendhoorn Games and I have just released my first game SpiritSphere on steam;

<iframe title="SpiritSphere - Early Access trailer" src="//www.youtube.com/embed/zmMRQ9KddMU?enablejsapi=1&amp;origin=https%3A%2F%2Fwww.gamedeveloper.com" height="360px" width="100%" data-testid="iframe" loading="lazy" scrolling="auto" class="optanon-category-C0004 ot-vscat-C0004 " data-gtm-yt-inspected-91172384_163="true" id="265597394" data-gtm-yt-inspected-91172384_165="true" data-gtm-yt-inspected-113="true"></iframe>

http://store.steampowered.com/app/458170

A short description shamelessly pulled from the steam page;

SpiritSphere is a local multiplayer game that draws inspiration from classics like Zelda and Windjammers and mashes it together with the nostalgic feel of playing air hockey at your local arcade.

I am often approached on events regarding the development tools I use, and which hurdles I had to overcome, so I though I'd write it all down here!

About me
Age : 27
Residence: Haarlem, Netherlands
Prior experience: 7 years programming (3 years proffesionally)
3 years hobbiest pixel-art

A side note is that I have problems with my health, and cannot use a mouse. The entire game was created on a Windows Surface Pro 3. I can spend about 5 hours a day behind a pc, sometimes a bit more, sometimes less. 

I will mostly be talking about the tech, since I'm a programmer by trade. But I did do all the art as well so I will talk about how I managed to ship a game with programmer art later. The gameplay still needs to be adjusted after I have received feedback from the community, so I'll keep that part for the release!

Tech stuff
Engine: Unity3D
Language: C#

Why Unity3D?
I chose Unity for several reasons;

  • Prior experience, so no learning curve

  • Multi-platform

  • Fast development cycle

Unity might not be the wisest choice for a game with arcade gameplay, but I wanted to get a game out as fast as possible. I had some savings, but not much, so I simply did not have the luxury to write a game engine. Besides that, my math skills are quite poor so I tend to steer away from writing a custom engine.

The good

  • Getting stuff done

Unity's is great for rapid prototyping, no need to write your own physics engine, sprite animation or state-machines. It's all included!

  • The editor

Setting stuff up in the editor is super convenient, you can change all the values on the fly and generally have a good overview of what's going on. I always created a bunch of custom editors that I will discuss later.

The bad

Yes "the good" was pretty short, here's why;

- Closed sourced
Unity's source code is closed off, and what this is means is that if you want to do something differently than how Unity intended it you're gonna have a problem. I can split this problem up in several sections;

  • The physics

SpiritSphere has pretty arcady gameplay, it's pretty much air-hockey combined with an old action-RPG. Unity's 2D physics are based on box2D, and therefore way too realistic for a game like this.

Physics prediction

There is a singleplayer mode in the game, and the AI needs to know where the ball will end up in order to defend their goal. However, there is no built in way to simulate physics, or to look ahead.

I ended up guestimating where the ball would end up. And while it worked out, it felt very iffy and was all written based on assumptions on the physics, since I cannot take a peek inside how things are working.

Gif of ball trajectory and AI response

(ai is top player)
Overal it just felt like I was fighting against Unity's physics all the time, it's not a pleasant feeling.

Serialization

Unity's editor is generally great, but there is one gripe that is bothering me to no end.

In addition to gameobjects, you can add classes to the editor with the [System.Serializeable] attribute.


[System.Serializable]
public class Loot
{
    public UnityEngine.Object item;
    public Sprite thumbnail;
    public int probabillity = 1;
    public int quanity = 1;
    public int value = 1;
}

[System.Serializable]
public class LootTable
{
    private int maxProbabillity = -1;
    public bool debug = false;

    public List<Loot> possibleDrops;
    public List<int> lootProbabbillities = new List<int>();
}

This is a screenshot of one of the patches of grass in the forest stage, I can specify what kind of items it should drop in the editor, pretty awesome right?

serialization grass loot drops image

Now let's say I create a new class that wants to inherrit from Loot, let's call it SpecialLoot for now.

The grass object has a List<Loot>. As soon as I add a SpecialLoot instance into the array Unity just thinks; "SpecialLoot? What the heck is this, I'll just turn it into a regular Loot instance" and throws away all the data from SpecialLoot. Unity's editor does not support Inherritance, which is a real pain in the butt.

Tilegrid

If I were to go in the direction that Unity is pushing me, a tilegrid would simply be a collection of gameobjects with SpriteRenderers. But we all know this is a big no-no performance wise. I believe Unity is working on a tilegrid system, but until that is done I had to write my own.

The tilegrid is simply a square mesh with a lot of extra vertices to compose the tiles. By setting the UV coordinates on the vertices we can decide which tile to display

My tilesheet is 16 tiles wide, which is the amount of tiles I need to fit in all the corners for a specific tile type.Based on that, I can pick the correct UV coordinate based on the current tile


float indexY = Mathf.Floor( tile.ID / 16 );
float indexX = Mathf.Floor( tile.ID - (indexY * 16 ) ); //using 16x16 tilesheet

//calculate the size of one pixel
Texture2D texture = Application.isPlaying ? (Texture2D)renderer.material.mainTexture : (Texture2D)renderer.sharedMaterial.mainTexture ;

float textureScale = 1 / (texture.width / (float)parent.tileSize);
float pixelSize = 1f / texture.width;

float tileLeft = (indexX * textureScale);
float tileRight = ((indexX * textureScale ) + textureScale) - seamMargin;
float tileTop = (1f - (indexY * textureScale) ) - seamMargin;
float tileBottom = (1f - ( (indexY * textureScale) + textureScale ) );

uv[ (i * 4) + 0 ] = new Vector2(tileLeft, tileTop ); //0,0
uv[ (i * 4) + 1 ] = new Vector2(tileRight, tileTop ); //1, 0
uv[ (i * 4) + 2 ] = new Vector2(tileRight, tileBottom ); //1,1
uv[ (i * 4) + 3 ] = new Vector2(tileLeft, tileBottom ); //0,1

Works pretty well! To create the stages more easily I have added some custom editors to draw the tilegrid straight in the editor

I divided the tilegrid in chunks, so whenever a tile is changed I don't have to adjust the entire tilegrid, but just a small portion.


 

There is one small "but"; At certain camera positions there seams between the tiles become visible. I believe this has something to do with renderering inaccuracy when the camera's position is at a half pixel.

In order to fix this I need at a 1 pixel extrude around each tile. This would mean my tilesheet would no longer be power of 2, which just feels horrible to me. For now I will have to see how many users encounter the seams between the tile, otherwise I will have to re-do a whole lot of tilesheets.


Input

Do I need to mention this? Unity's input system is horrible, no way to customize the controls in-game. I had some reports from users that wanted to play with 1 person on the keyboard, and one on the gamepad. I would have to write up some super hacky fix for this, so I decided just to wait until Unity's new input system is out. In the meanwhile I just mapped player one and player two their keyboard input to seperate keysets.

Pixel-perfect

I managed to get the pixel art to look decent by setting the camera's orthographic size to (screenheight / 2 ) / pixelsToUnit. But when the camera moves it still looks kind of wacky. (camera is mostly static in this game fortunately)

I could use a rendertexture and render the entire screen in it's native resolution, and then scale up the texture. But this came with a whole bunch of other implications and in the end I just kind of gave up.

UI

Unity's UI system is okay, but like everything they do , it just feels half assed. They tried to make this input system where you can automatically scroll through the UI elements.

But it just feels plain horrible. Whenever I accidentally mouse-out from a UI element, the gamepad loses focus on the UI element as well.

Whenever you enable and disable an element, the selection get's a messed up and you end up with 2 ite

JikGuard.com, a high-tech security service provider focusing on game protection and anti-cheat, is committed to helping game companies solve the problem of cheats and hacks, and providing deeply integrated encryption protection solutions for games.

Read More>>