Jul 142020
 

Last year, before I started working on my Frozen game, I started with something a bit simpler for my then-3 year old – a 2D Little Mermaid game. I wanted to make something very simple to teach basic 2D pad controls with minimal buttons required. On the plus side, no UI or text was required as she can’t read. Ariel is my daughter’s original favourite character, and some kind of swimming game sounded like a good idea. Also I hadn’t tried tilemaps in Unity before, and this was a good excuse to investigate. Here’s the end result:

The initial idea was to help a mermaid find her children who were hiding in a little maze, and bring them back to her. I’d picked up one of the Humble Bundles for creators that had some basic tile sets in, so I thought this would be easy. Unfortunately when I actually looked at the tileset it was completely useless – most of the tiles weren’t even square! Long story short, I eventually hopped into GIMP and drew my own, hence they don’t look very good!

But after making a simple maze, chucking in a parallax underwater background and adding a few simple fish sprites that moved back and forwards, it actually looked OK and I excitedly showed my daughter.

She takes the pad, goes straight up to the roof of the cave and says “Daddy, I want to go to the surface and see Prince Eric”. Except there isn’t a surface, or Prince Eric. But she does have a bit of fun swimming around looking for mermaids.

A couple of days later I’ve added some scrolling waves, some sky, and Prince Eric standing on the shore. “Daddy, I want Ariel to turn into a human and go into Eric’s castle.”

This game is going to be a little more involved that I’d anticipated. Oh well, it give me some direction, and it’s not like I’m not used to the whims of demanding designers.

Soon it had escalated. “Daddy, put in a giant penguin that goes up and down and has water spraying out of its head. And some monsters.” But finally I called it a day – after rescuing the mermaids you retrieve Eric’s castle key, do a little bit of platforming inside to grab your luggage, find the keys to chests containing other vital supplies, and then you sail off with Eric on a boat. Phew.

It’s not a technically great game by any stretch, I was just hacking stuff in quick. But it was pretty fun to make, and it was great for my daughter to see it being made (we mostly played it together in the editor, chucking sprites in and moving things around – she was obsessed with making the seagulls huge and green at one point). The only thing I’ve changed since is the music it originally had – after hearing the same jingly song from the musical on loop for hours on end, I just had to replace it with some generic background music.

Feb 272020
 

I’ve published my first asset on the Unity Asset Store! Find it for free here: https://assetstore.unity.com/packages/slug/162856

Or get the code directly from GitHub: https://github.com/AndyFenwick/FenceLayout

[EDIT: If anyone is interested, it’s had 142 downloads in the first five weeks after release. 29 in the first three days but it’s steadily getting a few each day since. That’s actually more than I was expecting.]

Fences

While making the Frozen game I wanted to put some fences down and assumed there would be a simple script on the asset store for this. There were a few fence tools available but they were all paid for. I’ve bought a bunch of art assets and tools (modelling definitely isn’t my strong point), but writing a simple tool to put a few objects in a line seemed like a perfect learning opportunity!

Here’s the tutorial video if you want to see what it does:

Writing the actual layout script was mostly simple. Add the prefabs, set up spacing, scaling and offsets, sample the terrain height and plop the prefabs down between the waypoints.

The only non-trivial part was dealing with uneven ground. On mostly flat ground the fences all line up nicely and look good. However on sloped terrain their disjointed and partially underground. The solution is to shear the fence model in Y so that both ends are on the ground. The only problem here is that Unity transforms don’t directly support shear. However there is a workaround by using two parent transforms and a series of rotations and non-linear scales. See this: https://answers.unity.com/questions/961330/shear-transformation-using-gameobject-transformati.html

I implemented that and it works well, with nice curving fences:

I’m not sure what happens to the colliders – the debug rendering becomes detached somewhat from the geometry, but it’s close enough that it works in my game so I’ve not investigated further.

Custom editor

The most fiddly bit was getting the custom editor and inspector working nicely in Unity. The input handling / selection handling stuff is pretty confusing – controls either wouldn’t consume input events, or they’d consume too many events and it would be impossible to select anything else. After some experimentation, this setup seems to work:

void InputUpdate(SceneView sceneview)
{
	Event e = Event.current;
	int controlID = GUIUtility.GetControlID(GetHashCode(), FocusType.Passive);

	if (e.control)
	{
		HandleUtility.AddDefaultControl(controlID);
	}

	if (e.type != EventType.Repaint && e.type != EventType.Layout)
	{
		GameObject fenceObj = Selection.activeObject as GameObject;
		if (fenceObj)
		{
			FenceLayout fence = fenceObj.GetComponent<FenceLayout>();

			// Do things with the fence...
		}
	}
}

public void OnEnable()
{
	SceneView.duringSceneGui += InputUpdate;
}

public void OnDisable()
{
	SceneView.duringSceneGui -= InputUpdate;
}

I also had various bugs with things not saving until I found out you have to manually set the object as dirty:

EditorUtility.SetDirty(m_fenceLayout);

And then found that editing a prefab still wasn’t saving. The fix for that was to mark the whole scene dirty if anything has changed:

if (EditorGUI.EndChangeCheck())
{
	EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
}

Have a look at the full code on GitHub to see the specifics.

Admin

I hadn’t quite realised the amount of admin that’s required to get something on the asset store. We publish enough apps in my day-job, but when you just want to publish a simple script it’s a bit of work to make (and work out what to put on) the required thumbnails, screenshots, social media banners etc. Plus write the documentation, record a tutorial video, write descriptions and all that. Good learning experience though.

Feb 162020
 

I bought a bunch of the popular Unity landscape tools recently, namely Gaia Pro, Vegetation Studio Pro, Complete Terrain Shader and River Auto Material. I also picked up a couple of the Nature Manufacture asset packs.

Here’s a little video of using the tools to quickly create a landscape. Note that I have spent a decent amount of time setting up the biomes and rules first so there’s work to be done after acquiring the tools, but once that’s done it’s super quick to create landscapes!

Gaia Pro

Gaia Pro from Procedural Worlds is primarily a tool for creating terrain heightmaps. It includes a wide range of ‘stamps’ (predefined heightmaps) which you can move, scale and rotate, and then apply to your terrain. There are loads of modes for applying stamps – add, subtract, blend, or apply effects like erosion, steps or peak enhancement. Stamps can be further combined with distance masks or other heightmaps for plenty of control. There’s a nice preview visualiser so you can see more or less what it’s going to do to your terrain before you apply.

Gaia Pro has loads of other features bundled in. You can set up texturing rules based on angle and height to automatically texture your terrain, as well as add rule-based spawners to add trees, rocks and buildings. Also bundled in are other asset sample, such as water, environmental audio, post-processing control, and a selection of trees, rocks and building assets.

This was the first tool I bought, and it’s a good all-in-one package to get started with. The terrain editing bit is great, but personally I don’t used the texturing and spawning controls – I find that Vegetation Studio Pro does that better.

Vegetation Studio Pro

Vegetation Studio Pro from Awesome Technologies is a must-have if you’re making large outdoor terrains. It takes a bit of setup, but afterwards you can author whole terrains in minutes.

You set up a series of biomes, each of which consists of terrain texturing rules and vegetation placement rules. The terrain texturing is similar to Gaia. You defines rules for each texture based on height and slope, convex or concave terrain, and Perlin noise, and they’re all combined to get the final texture. Vegetation follows similar rules – drop in your prefabs and set up similar rules for each based on height and slope, underlying texture, and density.

One massive bonus of the Pro version is that it supports multiple biomes types simultaneously. You define a default biome and can then drop other biomes into the scene and define their extents. The highest priority biome at each point is the one used, and there are cross-fade rules and curves to blend textures and reduce vegetation density or scale across the border.

In my game I have a default grass biome. I’ve defined a couple of different forest biomes so I can drop them into the level, mark the borders and you’ve got instant forests. And it uses its own batching and rending system so everything draws super fast! It’s the most expensive tool I’ve bought but definitely worth it.

Complete Terrain Shader (CTS)

Complete Terrain Shader is also from Procedural Worlds. It replaces the default Unity terrain shader with a more advanced one with more options. I think it has two main uses – the simple one is to add interest to distant terrain and break up the tiling, and the second is to use height maps for each terrain textures to completely change how textures are blended together.

The standard shader variant adds ambient occlusion, low frequency detail normal maps, height-based geological banding and snow, lower frequency tiling on distant terrain, and a few other features. These tweaks will make your distant terrain more visually interesting and less flat. Whether it’s worth it probably depends how much stuff you have in your world – if there’s a lot of detail and objects over your distant terrain it might not be so noticeable.

There’s an advanced shader variant that uses per-texture heightmaps, combined with the standard texture blending, to determine which texture to use per-pixel. I’ve not looked into this too far, but done well it can give far higher resolution, sharper texture blending.

River Auto Material (R.A.M.)

River Auto Material is a tool for creating river, lake and road geometry. You just click to add river spline nodes, set the scale and rotation of each node, apply a material preset, and paint transparency for blending. Fast and slow water effects are applied automatically based on the river gradient, or you can paint them yourself.

You can also simulate river flow, which I use a lot. Drop in the start point, hit the Simulate button and it’ll generate a river that flows downhill. Then there’s a terrain carving tool – draw the river bed profile in the graph editor, hit the Carve button and it’ll reshape the terrain around the river and blend it in to the existing terrain.

The other great feature is Vegetation Studio Pro integration. For each river preset you can define an associate biome type. Simply set the desired biome width, press a button and it’ll automatically generate a matching biome mask around your river. This makes it really easy to blend your rivers into your scene – the sand and rocks in the screenshot above were added like this.

I’ve not dived too far into the possibilities yet, but it’s a fun tool to use and I like the results a lot.

Feb 092020
 

It’s been a while. Turns out that having a child takes up a lot of your free time. Who knew.

It’s a tricky balancing act with children and technology. Too much screen time is bad, but they need to learn to use technology and feel comfortable with it. Being from a tech background, I often wonder if we were more conscious of this and a bit too strict (somewhat hypocritically, thinking back to my own youth…).

Everything is touch screens these days. Direct control is so much easier than indirect control, so I wanted to make sure that my daughter had some practice with a controller. Time to get back to Unity and make something!

I did a couple of simple 2D games early on (I’ll share them later), but I wanted to try something in 3D. My daughter loves Disney and Frozen, and after a quick Google I found some passable Elsa and Anna models (3D modelling is definitely not in my skill-set). After a quick proof of concept and a bit of research, the Unity Black Friday sale was upon me and I went all-in with a bunch of the popular tools. I may follow up with a technical post later.

The only slight hiccup is that we have another child due any time now, and nothing is going to get done for a few months afterwards. So this is what I’ve come up with so far:

There’s no real gameplay there, but my daughter always prefers to play in a sandbox than be told what to do, so running around and exploring is fine. You can summon snowmen, push them around, throw snowballs at things and cast magic at wolves to scare them off. I could spend hours more detailing the world and adding areas things (there’s loads of black areas), but I think it looks pretty cool so far.

Obviously the game will never be finished or distributed as they’re not my characters, but it also has the advantage that it only has to run well on my own beefy gaming PC so I don’t have to waste limited time on performance and optimisation!

Games for kids

Thinking about games for children in general, every child is so different that it’s really hard to find anything ideal off-the-shelf. They’re either too complex, or too simple, or require reading skills, or the theme isn’t interesting. Which is why I just make my own games, which can become more complex as my daughter grows up. And most importantly she can see how things are made and give ideas and suggestions about what to add, and see me make changes in real-time. Much better than games being some mysterious black box (I realise I’m lucky in being able to do this). If my kids are going to be gamers, they might as well start with early-access, moddable PC gaming! Much closer to the Spectrum scene I grew up with.

Co-op modes

Co-op mode is the best thing ever in gaming. It’s the ideal way to share a game with your family, and done well it can let an adult handle the complicated bits while the child does what they can.

This fit really naturally with a Frozen game, with two main characters. It’s not really in the video (because I recorded it myself and using two pads at once is hard) but one pad controls Elsa, and one controls Anna. Both pads can control the camera, so the child doesn’t have to. If there’s no input on a pad for five seconds, that player drops back to AI mode (they just follow you around for now) and the camera focuses on the active player. Any input will put them back under player control and the camera will keep them both in view. No rules around this, no complicated explicit join/drop-out mechanics, it ‘just works’. I’ll definitely be keeping this concept for future games.

Oct 302015
 

It’s been a slow year on the blog. This is mainly due to taking up a few new hobbies (learning Norwegian, and getting into astronomy and astrophotography) and preparing for a new child. I may write about some of these in future. But in the meantime I’ve done a little bit of work on my previously-untitled “spaceship game”, and figured I should put it up for download on the off-chance that anyone wants to play it.

I’ve mainly improved the frontend and UI, as it used to use the terrible looking built-in UI system in Unity pre-4.6. However, as my day job is making nice UIs for mobile apps, it’s not really the sort of thing I want to spend all my spare time on as well, so it’s pretty minimal (but not as embarrassing as before). The graphics are also terrible, because I’m not an artist. You may have heard the term “programmer art” before. If not, you have now.

At least the game now has a title. Using the time-honoured method of picking pairs of vaguely relevant words at random and putting them in Google until no existing game comes up, it is called Galaxy Arena. Download it here:

PC: GalaxyArena_PC.zip (13.1MB)

Mac: GalaxyArena_Mac.zip (15.1MB)

shipgame1

The Game

Galaxy Arena is a multiplayer-only game where you competitively build a spaceship out of square parts against the clock, and then fight everyone else with your creation. It’s pretty obviously heavily inspired by the board game Galaxy Trucker if you’ve played that (and if not, you should).

You can play free-for-all or with teams, and it supports 2-12 players. Team support is flexible but rudimentary – simply type a team number into the Team box by your name in the lobby, and the game will form teams accordingly.

I’ve only actually tested it on a LAN with up to eight players, but I presume it works over the internet. It uses the Unity development server for posting open games, and this is occasionally down for maintenance. If it is, you’ll just have to try again later (sorry), or use the Connect to IP option (port 33104).

Build Controls

The first phase of the game is where you build your ship. Your Core module in the middle of the screen. This has tiny engines and a puny laser built in, and your match is over when it’s destroyed. Around the edge of the screen are eight stacks of tiles, shared between all players. You have 60 seconds to grab tiles from the edge and attach them to your ship.

Left-click: grab a tile / place a tile if valid (when green)

Right-click: rotate the grabbed tile 90 degrees

Esc key: discard the current tile

Building Rules

Ships must be built following a few rules:

  • Tiles must connect to an existing part of the spaceship
  • Edges of the new tile must match all existing neighbouring tiles – either connector-to-connector, or blank-to-blank
  • No tile can be placed in the square directly in front of a weapon (shown with a red cross)
  • No tile can be placed in the square directly behind an engine (shown with a red cross)

After the time is up, you’ll be taken to the arena to fight.

Tiles

ga_coreCore. Lose this and you die.

 

ga_engine

Engine. Provides thrust and increases turning rate.

 

ga_laserLaser. Rapid firing, low damage weapon. Faster projectile than the missile.

 

ga_missileMissile. Slow firing, high damage weapon. Slightly higher DPS than the laser.

 

ga_gyroGyroscope. Increased turning rate.

 

ga_crewCrew. Increases rate of fire, and increases engine power.

 

ga_batteryBattery. Increases total energy reserves and recharge rate.

 

ga_armourArmour. More hit points than other modules.

 

 

Fight Controls

The arena stage is last man (or team) standing. There is no time limit and no walls around the arena, so just play nice and don’t run away forever… (this is remaining a prototype, not a polished full-featured game).

W/ S / Q / E : thrust forwards / backwards / right / left. Fires whichever engines you have pointed in that direction

A / D : steer left / right. Steering is faster the more engines and gyros you have, and slower the more mass of ship you have

Space : hold down to boost your engines, but this drains your energy bar quickly

Arrow keys : fire all of your weapons that face in that direction. Firing uses energy, and weapons won’t fire if there isn’t enough.

Tab : show the scores (just for fun, they don’t mean anything). Score is purely the amount of damage you’ve inflicted.

Your team mates have green names, and have green arrows pointing to them. Your enemies have red names and red arrows. You can damage your team mates, so be careful.

And that’s about it. Here’s a video of the previous version of the game. Enjoy!

Oct 012014
 

This is part 2 of how my spaceship building/fighting game is structured. Find part 1 here.

Space network synchronisation

Each player’s ship consists of a parent object with a PlayerShip script and a Rigidbody 2D, and a bunch of children (one for each attached ship module). I very much like the fact that you can just add a selection of children with box colliders (i.e. the modules) to an object with a Rigidbody and the physics interactions Just Work (certainly well enough for my purposes).

With that in mind, the only objects created with a Network.Instantiate() are the parent ship objects, one for each player. The server owns all network-instantiated objects, and nothing is network-instantiated on a client. The server keeps track of which object belongs to which player.

The clients have already been told which modules make up all the ships, so they create them all locally and attach them as children of the ships. The parent PlayerShips are the only things in the game that use the NetworkView state synchronisation (which automatically updates position and rotation 15 times/second). This is very efficient as there is only one synchronised object per player.

Prediction and interpolation

The ships use some simple prediction to minimise the effects of lag. I’ve seen a few people asking about how this works, so here’s the serialisation code:

void OnSerializeNetworkView(BitStream stream, NetworkMessageInfo info)
{
  if (stream.isWriting)
  {
    Vector3 position = rigidbody2D.position;
    Vector3 velocity = rigidbody2D.velocity;
    float rotation = rigidbody2D.rotation;
    float rotSpeed = rigidbody2D.angularVelocity;

    stream.Serialize(ref position);
    stream.Serialize(ref velocity);
    stream.Serialize(ref rotation);
    stream.Serialize(ref rotSpeed);
  }
  else
  {
    stream.Serialize(ref syncPosition);
    stream.Serialize(ref syncVelocity);
    stream.Serialize(ref syncRotation);
    stream.Serialize(ref syncRotSpeed);

    syncPositionFrom = transform.position;
    syncRotationFrom = transform.rotation.eulerAngles.z;
    syncBlendTime = 0.0f;
  }
}

And here’s the update code to calculate the transform every frame:

void Update()
{
  if (!Network.isServer)
  {
    syncBlendTime += Time.deltaTime;
    float blend = Mathf.Min(1.0f, syncBlendTime / blendTimeMax);
    transform.position = Vector3.Lerp(syncPositionFrom, syncPosition, blend);

    float newRot = Mathf.LerpAngle(syncRotationFrom, syncRotation, blend);
    transform.rotation = Quaternion.Euler(0.0f, 0.0f, newRot);

    // Update the from and to values by velocity.
    syncPositionFrom += syncVelocity * Time.deltaTime;
    syncPosition += syncVelocity * Time.deltaTime;
    syncRotationFrom += syncRotSpeed * Time.deltaTime;
    syncRotation += syncRotSpeed * Time.deltaTime;
  }
}

This will predict the position/rotation in the frames following an update, and blend out previous prediction errors over blendTimeMax (set it the same as your time between updates). This will fix all positional discontinuities (nothing will pop to a new position) but there will still be first-order discontinuities (velocity will pop).

That’s not a problem at all for the other ships, as it’s not noticeable in a game like this with slow controls. The only issue is if the camera is fixed relative to your ship (which it currently the case), because a tiny change in the ship rotation leads to a large movement of the background at the edge of the screen. It’s still barely noticeable, but ideally the camera position/rotation needs to be slightly elastic.

Controlling the ship

The Space scene contains a PlayerControls script which takes input from the keyboard and sends it to the server. You have controls for applying thrust in four directions (forwards, backwards, left and right), firing in each of the for directions, and steering left and right. The PlayerControls sends an RPC to the server whenever any of the inputs change (e.g. started or stopped steering) to minimise server calls. On the server, the inputs are passed to the PlayerShip owned by that player.

Ships are controlled by applying physics forces to the Rigidbody. Every FixedUpdate(), the PlayerShip uses GetComponentsInChildren() to find all the Engine components (scripts attached to the engine module prefabs) and send them the net horizontal and vertical thrust. If the engine is facing the right way is applies a force to the parent Rigidbody with AddForceAtPosition().

Applying the force at the actual engine location results is wild spinning for even slightly unbalanced ships, so I blend the position nearly all the way back towards the centre of mass to make is more controllable (97% of the way in this case, and even then it’s hard to drive with off-centre engines).

Steering simply uses AddTorque() to rotate the ship.

shipgame1

A ship with unbalanced engines

Weapons

Weapons are fired in a slightly different way to engines. Because there are a variety of weapons systems, I use BroadcastMessage() to call a function on every child script that responds to it (scripts are added to each weapon module). Each weapon script keeps track of its own cooldown and fires if it can.

Firing weapons creates Projectile objects. Each weapon module prefab has a Projectile prefab referenced in it, and each Projectile can have different graphics, speed, lifetime, damage and particle effects. The projectile is created on all clients by doing a Network.Instantiate().

Because projectiles go in straight lines there is no need to synchronise the transforms over the network. The initial position and velocity are set precisely the same as on the server, and the parent ship velocity is added immediately after creation with an RPC (use the new object’s networkView.viewID to identify it on the client). The projectile can then move itself locally and be in exactly the right place.

Impacts and damage are all calculated on the server. OnTriggerEnter2D() is used to detect when a ShipModule has been hit. Network.Destroy() is called on the projectile, a particle effect is instantiated on all clients, and damage is applied to the ShipModule.

If the ShipModule has been destroyed it informs the parent PlayerShip which checks if any other components are no longer connect. RPCs are then used to tell clients to destroy the relevant modules. If the red central component is destroyed then you’re out of the game.

No physics calculations or collisions are processed on the clients at all. The game is entirely server-authoritative to minimise cheating possibilities – the clients simply sends off inputs and receive updates. Overall I’m pretty happy with how it all works, and very happy that the entire game comes in at under 3000 lines of code (total, including comments and blank space)!

Next it needs a load of polish – better graphics, add some sounds, a building tutorial etc, but it’s a decent start.

Sep 282014
 

A little while ago I posted about my spaceship building/fighting game, made in Unity. Because Unity is quite different to how I’m used to writing games (pure C++), it required a bit of getting used to how to structure things. This post will give a high level overview of how it works and all fits together. Again, as a Unity novice I’m not saying this is exactly right, but I’m happy with how easily everything came together so it can’t be too far off!

I plan to do a few more improvements and usability tweaks to the game and then I’ll probably put it up for download. No guarantees on when though.

Scenes

The game consists of just three scenes: Lobby, Garage and Space.

The Lobby contains the UI for creating, joining and leaving servers, a Start button and a chat panel. There is a singleton NetworkManager that stores state about which server you’ve created or joined, and the other players in your game. I talked about that here.

On starting the game, every player loads the Garage scene. This scene contains the base ship and the components available to build it. After 60 seconds of building, the server calls time and tells every client to load the Space scene.

The Space scene contains very little except for a textured quad for the Background, a camera and a couple of manager scripts. All players are added in code, and at the end of the game the Lobby is reloaded.

Quickly about the networking side of things. The server player also plays the game as a client, so as much as possible the code is split out into Server and Client parts. The client-running-on-the-server goes through all the same processes as any other player for simplicity (but the NetworkManager shortcuts the message passing, as I spoke about before).

Garage structure

The Garage scene contains a bunch of GarageSlots which are where the available components appear. There’s also a GarageManager object which has references to all the GarageSlots (set up in the inspector). Finally there’s a PlayerShip which is mainly a container for ShipModules (the square tiles you add to your ship).

Each individual ShipModule is defined as a prefab which contains a sprite, a box collider, a ShipModule script (with info about the connectors on each face, hit points etc), and any module-specific scripts. There are currently eight types of module and around 30 different module variants, so there are 30 different prefabs.

unitygarage

All very straightforward. One problem is then how to create a global accessor for these modules, so that both the Garage and Space scenes can get references to the prefabs. Looks like we need another singleton, which we’ll call the ModuleLibrary.

Singletons with configurable parameters

The ModuleLibrary script contains references to every module prefab, set up in the inspector. This is all fine if the script only exists in one scene because you can just drag one into the scene and set it up. However, singletons like the NetworkManager work by newing up a NetworkManager script and adding it to an object. Instead I want a singleton that I can configure in the editor.

To do this we can set up an object containing a ModuleLibrary script, configure it by adding all the Module prefabs to it, and save that as a prefab. Then you can use this singleton get() function to instantiate it from the prefab:

static ModuleLibrary m_instance;
public static ModuleLibrary Instance
{
  get
  {
    if (m_instance == null)
    {
      GameObject obj = Instantiate(Resources.Load("ModuleLibrary")) as GameObject;
      m_instance = obj.GetComponent();
      DontDestroyOnLoad(m_instance);
    }
    return m_instance;
  }
}

One thing to note is that Resources.Load() takes a path relative to the Resources folder in your Assets list. This folder doesn’t exist by default so you’ll have to create it.

unityResFolder

Now we are able to get a prefab for any tile from this singleton and a module ID number.

Garage security

For a small hobby game I’m not at all worried about cheating, but it’s good practice to design a robust hack-proof system as much as possible anyway. To that end, the server keeps track of and verifies all steps in the ship building process.

The server generates the IDs of the modules that will be available in the slots, and tells all clients. When a player clicks a module to pick it up, their client sends the chosen slot ID back to the server. The server stores which type of module that client has selected, and generates a new one to fill the gap.

When a player then clicks to attach a module to their ship, the client only sends the grid coordinates and the rotation (one of four). The server already knows which component is selected and verifies that it’s valid. Therefore it’s not possible to send new modules back, or create invalid ships, by sending fake packets to the server.

From the Garage to Space

The details of everyone’s ships are stored in a ShipStore, which is another configurable singleton. The ShipStore on the server is what keeps track of the ships that each player is building. When the Space scene has loaded, the server ShipStore uses RPCs to tell every other player the details of all the ships.

Unfortunately the built-in Unity networking doesn’t support sending arbitrary byte arrays, so the transmission is a bit cumbersome – an RPC call is made for every single component on every ship and contains the player, coordinates, module ID and rotation. It’s not ideal but it works, and there are at most a couple of hundred messages.

At this stage there is a little bit of message passing to ensure that every client has finished loading and receiving ship data. Everyone has now build a ship and made it into space so it’s time for some action, but that can wait until part 2.