Unity2D – Sprites 2

25 10 2013

Hey what do you know, sprites are catching up.

Alright, where did we leave off on?

public static class NewSpriteObject
  public static GameObject Make(Texture2D texture)
    throw new NotImplementedException(); 

Remember my definition of a sprite object? no? oh well, if I could re-read the previous post so can you šŸ˜›

let’s continue.

It’s really not as simple as I’ve portrayed it and off the top of my head I can think of several paths to take to achieve the end goal. First of which, the simplest, is to generate a node which contains all the information required to render a mesh and texture/material and manipulate its data through Unity’s normal transform. The second approach is to generate the same node with the same data but reroute the transform information to update the underlying mesh. Third we could create a parent node (let’s call it the sprite node) and a child node (let’s call that one the graphic node) which would contain the mesh/material data and manipulate them via the sprite itself. We could also combine the approaches and mix’n’mash between transform manipulation and direct vertex updates.

But which road to choose??
Heck, it’s not like I’ve got a word count here, let’s go with all of ’em and see where we end up.

Ok. First approach. Let’s create a node, attach the correct components and call it a day. The sequence of method calls would look something like this;

public static GameObject Make(Texture2D texture)
  var sprite_node = new GameObject("Sprite");
  var mesh_filter = sprite_node.AddComponent<MeshFilter>();
  var mesh_renderer = sprite_node.AddComponent<MeshRenderer>();

  var mesh = NewSpriteMesh.Make(Vector2.one);
  mesh_filter.sharedMesh = mesh;

  var material = NewSpriteMaterial(texture);
  mesh_renderer.sharedMaterial = material;

  sprite_node.transform.localScale = new Vector3(texture.width, texture.height, 1.0f);
  return sprite_node;

So, what’s right about this approach and what’s less right?
It’s pretty simple, pretty easy and gives use what we need at the most basic level. A node that renders our texture in game. The main drawback of this approach is our lack of a pivot point control over the mesh (not to mention having negative scale if we want to flip it).

But wait! This code does not work. What is this magic called NewSpriteMaterial? (I’m going to assume you know what the NewSpriteMesh class is by now).

The NewSpriteMaterial isn’t any more complicated.

public static class NewSpriteMaterial
  public static Material Make(Texture2D texture)
    var material = new Material(Shader.Find("SpriteShaderName");
    material.name = "sprite-material";
    material.mainTexture = texture;
    material.mainTextureOffset = Vector2.zero;
    material.mainTextureScale = Vector2.one;
    return material;

The shader used doesn’t have to be any more complicated than Unity’s transparent shader if you want.

One thing I would like to point out, before finishing this post, is the usage of ‘shared’ mesh and material. This can lead to subtle issues like copy/pasting sprites where all the sprite nodes actually share the same material (Unity does this as an optimization – which I really wish I had more control over) and one change to the material will lead to it propagating to all other nodes. You’d think that using the regular, ‘mesh_renderer.material’ will solve this but at edit-time Unity will emit an error/warning and leak memory. On the same note, because we’ve not actually saved either mesh or material if we delete all nodes which reference them we’re looking at another memory leak (this can be fixed by pressing play and stop which forces Unity to garbage collect unreferenced objects). I will post code later for simple asset serialization.

And that’s it for the first approach. Not too difficult, very rewarding and easy to implement.

“Land of immortals I wait for my day, to reach the wisdom of your skies”




Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: