Daily Dev Feb 22 – Let there be light!

As I alluded to in my last post, yesterday I added the beginnings of lighting to my game – a simple object with a sprite (a lantern) and a point light. Unfortunately, it was not smooth sailing:

My character sprites weren’t being lit properly! They were being lit by the ambient scene lighting but the point light was about as effective as a pair of goggles in an acid tidal wave.

After a while spent experimenting, I determined that my player prefab was Proper Buggered and the only thing for it was to recreate it piece by piece, which worked a treat! Newly-working character lighting in hand, I started including torch placement as part of the dungeon generation. What could possibly go wrong?

Ah… It would appear that Unity does not take kindly to many point lights existing at once.

Simple solution: have them turn on only when the player gets close, and turn off again when they leave the area. Beauty! Here it is in action:

Best bit is, at first glance you can’t even tell it’s doing it, so here’s how it looks behind the scenes:

Until next time!


Daily Dev Feb 21 – Multiplayer Maps

I noticed something troubling shortly after sitting down to work on my game – my new map generation code was working splendidly, but new players connecting to my server wouldn’t get any map data and would be stuck wandering a black void! Aside from the amusement factor of seeing other players and being able to apparently walk through walls (on the server’s end, since the client saw no walls there was no collision – one downside of a non-authoritative server) this represented a major issue.

I put off my plans for working on monster spawning and combat today and focused on fixing that particular snafu, and fix it I did! The solution didn’t come easily – at first I thought I could just attach a network view to my TileMap (a construct from the 2D Toolkit) but of course that didn’t do anything since there’s no good having something listening to you if you’re not saying anything, and I couldn’t pass along the TileMap data object to new players since as a GameObject datatype, it can’t be transmitted as an argument using remote procedure calls. RPCs will, however, accept more simple data types such as string, integer and most importantly, Vector3.

For the uninitiated, a Vector3 is three float values typically used to describe a position in 3d space; an X, a Y and a Z co-ordinate. Ultimately though they’re just a three element array and the numbers can be used for anything, which made me a very happy camper.

I created RPC versions of two methods my Dungeon Manager uses to build the map – SetTile and Build. SetTile accepts four integer arguments, X and Y co-ordinates, a layer number and a tile ID. Build is called after you’re done setting tiles with SetTile and will update the TileMap allowing you to see the results. Can you see where I’m going with this? Every time the server placed a tile it calls the SetTileRPC I created, using a buffered RPC mode. When it’s finished generating the map, it calls the Build RPC, again in buffered mode.

The important part here is making the RPC calls in buffered mode – as the name suggests, in this mode all rpc calls are recorded in a buffer, which played back to new players in the order they were received.  Essentially, the server’s Dungeon Manager records every tile it places while generating the map and tells newly connected players’ Dungeon Managers to place all the same tiles, build the map and then pop the player into existence.

Wonderful stuff, wish it didn’t take so long to figure out. Networking is hard!

I didn’t have the energy or inclination to go back to the day’s planned work so instead I played around with adding lighting to the map – it looks pretty cool! For some reason player sprites aren’t being lit properly though, so there’s something to start on tomorrow!

Daily Dev Feb 20 – Dungeons!

I’m writing this at ~5am local time on Friday but I say it counts as Thursday’s Daily Dev because I started last night and, frankly, nobody’s going to argue with me.

Following on from the list of five things I wanted to do by next week, today’s Thing was dungeon map generation – having the game generate a level at random for our intrepid heroes to run around in.

Starting out was pretty simple, write a short method to build a room of a specified height and width, at specified x/y co-ordinates and wrap it in some logic to prevent it building over top of existing rooms. I even threw in some basic ‘theme’ functionality to switch out which tiles it uses for the floor and walls. The results are below, showing both the ‘flooded’ theme and the default:

Creating rooms at random

The next part was considerably more complex – coming up with logic that would allow the game to build a network of rooms connected by corridors. Approaching it in stages, I started with a method that would pick an existing room, pick one of its sides, decide on dimensions for a corridor and new room at the end of it and, if it didn’t overlap existing rooms/corridors, go ahead and build it. The logic behind the exact co-ordinate setting took the most time by far, between making sure corridors and new rooms didn’t exceed the edges of their neighbours and working around Unity’s bizarre number generator (Random.Range(x, y) will return a value between x and (y-1), not x and y. Wish I’d know that sooner).

Anyway, the end result is pretty pleasing, a nice little dungeon map just begging for slavering beasts, pots of gold and adventurers with an appetite for filthy, filthy lucre:

Cartography 101: Making your first map