Multiple sprite sheets, Sprite Lamp, and Unity

So I mentioned yesterday that I’ve been working on a small tech demo in Unity, to help make sure I notice all the difficulties that can come up with Sprite Lamp, and the first one that has presented itself is the issue of animating with multiple (sets of) sprite sheets. A few people asked me about this already but I didn’t quite have my head in the game enough to give good answers. Hopefully now that I’ve played with it a bit more directly, I can do better.

Here’s the script referenced in this post.

Oh and before I go on, a quick annoying reminder that Sprite Lamp is at 30% off on Steam as I write this!

Animations with a single sprite sheet

The simple situation for frame animation in Unity is one big sprite sheet. This is, I suspect, reasonably common – especially with people working with pixel art, and textures going up to 4096×4096. Someone in this situation who wants to use Sprite Lamp is in a pretty easy situation in terms of programming – essentially, everything just works easily. You’ll want to make a sprite sheet of the diffuse channel, cut it up with Unity’s sprite editor, create animations, and apply them to a game object with an animation controller. So far, everything is normal. Then, you’ll want to create a corresponding normal map sprite sheet with Sprite Lamp (either using whatever texture packer tool you want, though be wary of rotating normal maps, or by drawing the lighting profiles in sprite sheet positions then processing them all at once). You don’t need to cut this up into sprites in Unity after you’ve imported it. Then, apply a Sprite Lamp (or other) material to your game object, drag the normal map sprite sheet into the NormalDepth slot, and everything should be fine.

The reason this works smoothly is because if you have one big sprite sheet, all the animation system is changing is the UVs on the sprite, and because the Sprite Lamp shader doesn’t do anything fancy with UVs, it’ll just look up into each sheet in the same spot.

Multiple sprite sheets

This is where things get tricky. The issue is that Unity’s animation controller automatically switches textures as necessary, but it only provides for switching the main texture, because usually you only have one texture when you’re doing this kind of animation. By way of example, say you have a character who can walk or run. If you’re making a normal 2D game without lighting, you might have two textures: WalkSheet, and RunSheet. Ordinarily, when your character is walking around, Unity will be switching between sprites in one sheet, and thus changing the UVs – but when your character switches to running, Unity has to switch to the RunSheet texture, which it does automatically.

Suppose instead though, you are using Sprite Lamp, so you have six textures. WalkSheet, WalkSheet_Normal, WalkSheet_Emissive, RunSheet, RunSheet_Normal, and RunSheet_Emissive. Your character starts walking around fine, with WalkSheet, WalkSheet_Normal, and WalkSheet_Emissive applied – all is well. Then they break into a run though, and we’re screwed. The animation system switches the diffuse texture to RunSheet, but the normal and emissive channels keep the Walk versions. This will look somewhere between pretty broken and horribly broken, depending on whether or not the walk and run sheets have similar layouts.

How to get around this? Well, essentially, I’ve written this script. It’s still not tested all that much, so I haven’t added it to the official Unity pack yet, but it has worked in my use case and will hopefully work in yours (if not, let me know). The script works by creating a dictionary at load time, which uses a texture as its key, to look up the corresponding textures. Then in the update, it will check the object it’s attached to to see if the texture it’s using has changed – if it has, it automatically sets all the other textures.

To use it, the first thing to do is attach it to your character (or whatever). Second, you have to populate some lists – this is currently done manually, but I’m looking into nicer ways to handle this.  The lists are ‘primaryTextures’ and ‘otherTextures’. Into ‘primaryTextures’, drag all the sprite sheets that your AnimationController knows about – so in our above example, that would be WalkSheet and RunSheet. In the ‘otherTextures’ list, you’ll want to drag all the auxiliary stuff Sprite Lamp uses – here, that would be ‘WalkSheet_Normal’, ‘WalkSheet_Emissive’, ‘RunSheet_Normal’, and ‘RunSheet_Emissive’. For each element of ‘primaryTextures’, the script will search for any textures in ‘otherTextures’ that are suitably named, and associate them so that they get set at runtime.

That should be just about it! As always with Unity things, if I’ve missed some obvious smarter way to do this, please let me know. Also, I’ll be along soon with a more concrete example of this method that you can download, in case my description here doesn’t make things clear.

Coming up next…

The other problem I rapidly ran into here is the problem of ‘light sources’ that exist in the emissive texture map. They tend to move around within the sprite, and you’ll likely want an actual light source to move with it, but the engine doesn’t know how to move it appropriately. I’m working on a script that will automatically parse an emissive map and approximate clusters of bright pixels by creating a light of the appropriate intensity/colour/position. It’s at proof-of-concept-ish stage now and isn’t ready to distribute just yet, but so far it looks pretty cool, particularly by matching the light’s movement to the animation’s framerate.

Sprite Lamp sale, and the eating of dogfood

Hi folks!

First thing’s first, Sprite Lamp is on sale on Steam this week, for thirty percent off.  A couple of people asked me when that was going to happen, so here we go. I turned thirty a couple of days ago so I thought that was as good an excuse as any. I’ll note that this sale includes the upgrade from the hobbyist version to the pro version. So yeah, here are the links to the Steam pages if you want to get in on that.


Mac holdup

I’m not enjoying giving bad news for the mac port, but unfortunately there has been a hold up – we’ve recently been having a pretty major show-stopping bug with some not-yet-understood combination of mono, graphics drivers, and OSX versions. Rob has more resources than I do for this, and he’s currently messing about rolling things back to get it to the point it’s usable. Once we get it to some working state, the plan is to release an alpha to kickstarter backers, to get a feel for reliability, and hopefully that will give us the data we need to move on to a proper release.

Linux alpha incoming

Progress is much more forthcoming on the Linux build, fortunately, and I’m hoping to get an alpha to backers soon. I’m still struggling with the Steam libraries on Linux, but other than that things seem to be coming together pretty okay.

Eating our own dogfood

Developers might recognise this rather gross-sounding phrase. ‘Eating your own dogfood‘ refers to the practice of using your own products internally. Technically, I think this would mean Snake Hill Games was making a new game, and it was using Sprite Lamp, but this isn’t the case (yet). Rather, I’ve noticed that too often, I don’t have a great answer to questions people ask about using Sprite Lamp with Unity, because while I have developed the shaders and put them in a toy environment, I haven’t actually used them for real. Unity is big and complex, and try as I might, I frequently overlook application details that are tripping people up. In an attempt to head that off at the pass, Halley and I have decided to make a small tech demo using Sprite Lamp and Unity. Hopefully the following things will result:

  • I’ll encounter problems with using Sprite Lamp and Unity, and fix them.
  • I’ll encounter workflow issues with Sprite Lamp now that we’re using it for real, and fix them.
  • Halley will create a bunch of art, and write some blog posts on workflow and artistic best practices, that will perhaps be of some use to people.
  • We’ll perhaps end up with some generic assets that people might find use of in their games.
  • We’ll be able to give more concrete answers to questions like “How long will it take to make assets for use with Sprite Lamp?”, as well as point people to a live example of what games that use Sprite Lamp can look like.

This won’t take a great deal of my time (it will be more artwork than codework) but it has already borne some fruit. Tomorrow, I’ll be posting an update about using multiple sprite sheets with Unity’s animation system, and adding a script to the official Unity integration package that automates the process of switching out different sprite sheets.

Anyway, I’m not going to say much about this little tech demo just yet – it’s in very early stages, and there’s nothing really worth showing off yet – but I’ll post a bit more about it soon.

Scattershot update

Quite a few things to put out there today.

Mac and Linux progress

This has been my main focus recently, and though I’m aware that this part of the project is well overdue (more on that in the ‘lessons learned’ section later on), we’re down to the last handful of bugs before the alpha releases on MacOS. Rob reports that he’s been having more trouble than expected with various parts of the project – it was a bit of an unknown working with C# and MacOS in the first place, but there have been more unknown unknowns than either of us saw coming. At this point it’s essentially all UI fixes, but unfortunately they’re not the kind of thing that can be handwaved, even for an alpha. It’s been frustrating at our end, since Halley is a Mac user and has been keen on getting this version sorted for a long time, but the end is very much in sight. I apologise for how long this is taking, though – I don’t mean to gloss over the fact that it’s much longer than expected.

As for Linux, because the MacOS version is mostly in Rob’s hands now, I’ve been looking at the Linux build. This isn’t as big a deal as the Mac version (in terms of work, I mean) because it doesn’t involve an entire UI rewrite, but there are lots of problems that have previously been in the too-hard basket because previous releases haven’t been in any way final, which I’m now having to face head on. A big part of all this is packaging and general unfamiliarity with deployment conventions at this point.

A few engine things

Unreal 4

This is an odd one. Lots of people have been asking me about integration between Sprite Lamp and Unreal 4. I feel a little bit like the winds of change are blowing in the indie gaming word – it seems like everywhere I turn, people are talking about their new project using Unreal 4, or the various advantages the engine offers. I don’t know whether Unreal 4 is going to replace Unity in the near future, but it was enough to convince me that it’d be irresponsible to not look into Sprite Lamp and Unreal 4 playing together.

I’ve spent some time recently learning the engine a bit, and… well, beyond normal maps, it’s not clear there’s much I can do with Unreal 4. As usual, it’s a modern engine and can therefore handle dynamic lighting and normal maps just fine. However, because it uses deferred rendering in a very fundamental way, it’s no longer possible to just write your own custom lighting model with Unreal 4 as far as I can see (and the fancier features of Sprite Lamp’s shaders fall into that category). I’ll add two caveats to that – first is, obviously people are capable of achieving amazing things with Unreal 4’s lighting, and that includes nonphotorealistic results, so very likely things like cel shading are still possible. It just means that I won’t be writing the exact shader from the preview window of Sprite Lamp into Unreal 4, because that appears to not be possible. The other thing is that since Unreal 4 has its full source code available, technically it’s not really true to say that anything can’t be done – almost anything is possible. However, I think that trying to maintain a source-modified version of the engine (that would survive integration when Epic updates and so on) is probably more trouble than it’s worth for everyone involved.

Godot

Another engine that seems to be picking up steam a bit is Godot. Since it’s completely free and open source, Godot’s appeal isn’t hard to understand. I don’t know a great deal about it yet, but I’ve been following along and it seems that 2D lighting is a priority for them in the near future, which is obviously very relevant to my interests, and perhaps yours. That said, unlike Unreal, I haven’t particularly gotten the impression that lots of people using Godot are also using Sprite Lamp – if you’re a Godot fan and would like me to look closer at its use with Sprite Lamp, let me know.

Real life issues

As you’re probably aware, Sprite Lamp has been out on Steam and Humble for a couple of months now, and though it’s doing okay for itself, taken in combination with the above issues about the Mac port taking way longer than expected, it would be financially risky for me to just assume that I can live indefinitely on Sprite Lamp. This has necessitating me getting myself a ‘real job’. It’s a job that doesn’t consume all my time, and don’t plan on completely returning to the normal full time employment world for a little while yet (not while Sprite Lamp is ongoing, certainly).

Lessons learned

One day, I’ll do a proper Sprite Lamp post-mortem, but there are two important things I’d like to put out there in case anyone might learn from them.

First off, it’s clear to me now that the biggest technical misjudgement on my part for this project was underestimating the difficulty of working with unfamiliar platforms. I’ve only ever been a Windows developer, so (I thought) I had a suitably healthy fear for working with other platforms – that’s why I went and made proof-of-concept stuff for MacOS and Linux before promising those versions on the Kickstarter campaign. Still, I was unprepared for how much work gets bogged down (for me, at least) by not knowing the operating system. As a simple example, I recently spent an embarrassingly long time tracking down some issue with apt-get on my Linux install that was stopping me from progressing, which ultimately culminated in having to install a newer version of Linux (which, to its credit, went very smoothly). That stuff adds up, and it’s not psychologically great when it feels like you spend as much time fighting with problems of unfamiliarity as you do writing code. I’m hoping future projects of mine can be cross platform, but I’m definitely going to be less gung-ho in my assumptions. Certainly I cringe internally to recall my intention to do a simultaneous cross-platform release.

Second off, and a little personally, I didn’t foresee how much being a (very very mildly) public figure would be a source of stress, and how crap I would be at maintaining stuff like this blog, a social media presence, etc. I’m actually not a terribly shy person in real life (although admittedly with game development to some extent you’re grading against a curve there), but apparently I am in the internet world, which seems to be the reverse of how most people feel. This mostly makes me respect community managers a lot more, but also gives me some reason to pause in the goal of being an indie developer, since it kind of comes with the territory. Not sure how I’ll feel about that going forward, but if anyone has actually read this far and has any advice on the same kind of thing, please let me know.

 

Anyway, that’s it for now, and I’m back to figuring out Linuxy things. To anyone who read this far, I hope you celebrated whatever they’re inclined to to the best of their ability, and that 2015 is as good or better than 2014.