2D Puppet Rigging - Tips Tricks

I thought I would share some tips and techniques I have come up with over several projects on some helpful ways to use puppet style animation rigs in Unity using just the tools and features in Unity. There certainly are great extensions (Smooth Moves), and third party apps (like Spine), and those will work very well depending on your needs.

My needs were to have something native and leveraging built in features. While given some level of control for animators, and the ability to essentially retarget and control certain aspects externally. Here are some of tips and methods I use to do that:

Setting up rig that allows for flexibility and a type of retargeting.

Typically when you set up your animation, you structure things hierarchically and animate those pieces directly. That becomes a problem if you need to change the pieces or access/modify them dynamically. Since this particular character/animation will need part modification and access, I have structured with empty Transforms for the parts I will be animating. Like this:

I try to use descriptive and generic names, this helps keep things clean and non specific. (and easily reusable)

I have also placed an empty object as a child of each called “—sprite”, in that folder is where I will place the actual sprites. The sprite folders are centered on the parent.

Additionally I used gizmo lines to simply draw lines to the parent. These aren’t really important, but they can be helpful to visualize things.

Also, I added a custom icon to each parent container, you can do that from the inspector.
1624030--99540--$2DRig_002_icon.jpg

This is very useful. Icons are selectable, so you can click on them to select the proper node while animating. This helps prevent clicking on the wrong elements or the nested sprites. Additionally, since it is on a gameObject (not a sprite), when animating you can use the normal transform widgets.

Adding the sprites.
Typically, will use full image of the character behind it for alignment. I will then go through and place all the elements in the sprite nodes of each object.

Doing it this way means that you can simply align them the way you want. Since the pivot point is actually the node and not the sprite, you don’t have to go through and adjust the pivot point on all your sprites.


… adding the rest.

Note about names:
Since I am going to be doing skin switching, it is helpful to have common named elements for each of the skin elements. For the base, all the elements are prepended with “BASE_”. More on this later.

After all the elements are placed and set up, I will then adjust the z-depths. I do it this for better control. If I need to put this character in front or behind another character, I change the layers or order on all the parts via script and the whole character will be in front or behind other elements via sorting order.

Continued…

11 Likes

Next I will add the other skin elements in the same way.

Now because I named them all with specific names, I can use the Unity search to show specific parts like this:

and this…

I will continue to do this with all the parts until I have everything in place.

Continued…

3 Likes

Animating

I will go ahead and turn off the other skins using the search and unchecking them in the inspector.
image

Now I will animate the character as normal, taking care to only animate the top level parts, but clicking on the icons.

Skins via layers

Once I have my animations complete, I will use layers to handle the skins. I will create a new animation for each skin, including the base. In the animation, I will only be animating the game object active state. I will need to set it for every piece. Again, using the search feature, I will search for each skin by name and activate or reactive them.

I will then do this for each for each of the “skin” animations, I will repeat this process. In the case of this character, only some of the parts are replaced or some just overlay, so I will set them as needed. Making sure that every part is accounted for. If some aren’t they will bleed over the normal animations.

Continued…

1 Like

Creating the “skin” layers
Now that I have my four skin layers, I set up the layers in the animator. (If they have already been placed in the default layer, delete them from there. )

Create a new layer, in this case I called it Base, and add the skin animation (gear_base). It should be the default. In the control widget, set it to “override” and since this is the default, I will set the weight to 1.
1624043--99556--$2DRig_014_layers.jpg

Create a layer for each, and for those ones set the weight to zero.
1624043--99557--$2DRig_015_layers.jpg

Now you have layers that can be used as skins.
Programmatically, you will set them by index and weight (in this case either 1 or 0). The index number will be order they appear in the animator. The first layer with your animations on it is 0, so your skins start at one.

The trick here is that you will need to only have one layer set to 1, the others at 0. So to change from the Base to the Archer, I will do this:

	void TurnOnArcher()
	{
		anim.SetLayerWeight(1, 0);
		anim.SetLayerWeight(2, 1);
		anim.SetLayerWeight(3, 0);
		anim.SetLayerWeight(4, 0);
	}

Though more typically, I will have the skins stored in an array elsewhere and do something like this.

	void SetSkinLayerWeight(int i)
	{
		int layer_state;
		for (int n = 1; n < skins.Length+1; n += 1) 
		{
			val =((n)==i)?1:0;
			anim.SetLayerWeight(n, val);
		}
	}

Or however you want to do it, those are just simple example to illustrate the functions to be used.

Dynamic weapons.
The skins were done with layers, they could also be done programmatically, which is how I have set up the weapons in this example.

When I set up the rig, nested in each of the hands, I placed an empty object to hold weapons.
1624043--99558--$2DRig_016_weapons.jpg

I am going to place all the weapons I need in advance in this holder and then turn them off.

This certainly can be done dynamically, but for this example I have built them in. It allows me to accurately place them.

Now they can be directly turned on or off via code with SetActive(). Everything inherits its parent properties, but it isn’t directly controlled by the animator, so there are no problems with fighting the animator.

Continued…

5 Likes

Final:
This is just one example. It isn’t a great fit for every solution, and it makes the animation a little heavy because of the all the parts. I probably wouldn’t use this if there were tons of characters on the screen but a dozen or so are fine. You can also take it further by not having all the parts in place at first and just adding them as needed programatically.

Hopefully this was useful, and here is a quick web player to show some of the switching, and there is button (Menace) for one of the animations, showing how the layer masking only affects the active states and can be used across all animations.
https://dl.dropboxusercontent.com/u/28107/unity/RigExample/index.html

Feel free to ask questions, and will try to answer them as best as I can.

Cheers,
ZG

[Any updates or corrections I will add to this post]

3 Likes

Hey… thanks for the terrific post, very clean workflow.

Terrific tutorial! Thanks for putting this together.

Can you further explain how’d you handle multiple characters z sorting? You said you’d put them on different layers but that’s not really practical once you have many characters and/or spawning them programatically…

What would you recommend for those situations?

I would only use layers if there few characters on screen. That example was for fighting game, so there were really only two on the screen at a time. Normally what would do is just use layer order instead. since all the z-depth are set already, each character only needs one number for the ordering.

I will loop through all the children, find the renderers and apply the sorting order. Something like this:

	private int _sortOrder
	
	public int sortOrder
	{
	    get { return _sortOrder; }
	    set { 
			if(value!=_sortOrder)
			{
				_sortOrder = value;
				SpriteRenderer[] sprite_renderers = gameObject.GetComponentsInChildren<SpriteRenderer>();
				foreach (SpriteRenderer spr in sprite_renderers)
				{
					spr.sortingOrder = _sortOrder;
				}
			}
	    }
	}

If I am going to do it a lot, I will cache the results of the find instead of looking for them each time.

Thanks! That sounds a like good approach! :wink:

Very nice tutorial, maybe even stickyworthy.

1 Like

aaand stuck

This has definitely made me rethink how I’m doing my character animation.

Any plans to make a video tutorial about this?

2 Likes

I actually use this method for animated films in maya. I would love to try in unity. Thank you for the post. You should def make a video tutorial.

This is the link to the film that I made using puppet rigging method.
https://www.youtube.com/watch?v=B6iN5q6LlWs

1 Like

how do you make that line in editor? :confused:

You mean the lines that show the connections to the various parts? For that I use the Gizmos.DrawLine and draw lines from each child to the parent.
1658404--103645--Screen Shot 2014-06-10 at 1.23.56 AM.png

In a bit more of an advanced version of the rigging/animating tool, I use Handles.DrawSolidRectangleWithOutline

1658404--103646--Screen Shot 2014-06-10 at 1.46.27 AM.png
Using handles provides a little more flexibility for display.

oic… so it’s for advanced users i think :stuck_out_tongue:
I never code the editor… and when I tried to follow some tutorials I think it needs some basic understanding about the editor and it would waste my time as I’m currently working in a project. Maybe I’ll try learning that when I finished this one.
and also the Anim Rig component, i never know that the inspector could be that adorable :stuck_out_tongue:

Not at all. No editor scripts or scripting are required. I do have a larger system in place for controlling and manipulating puppet rigged animations, but the above steps/method doesn’t require any of them. It is just a base method to allow for flexibility and more control over the sprites that that make up the rig.

To add connection lines for the nodes, one can simply add the following script to the main nodes:

using UnityEngine;
using System.Collections;

public class RigNode : MonoBehaviour {
    public Color lineColor = Color.red;
   
     void OnDrawGizmos()
    {
        Gizmos.color = lineColor;
        Vector3 parentPos = transform.parent.position;
        if(transform.parent != null) // ignore if no parent (stage top level)
        {
            Gizmos.DrawLine(tranform.position,parentPos);
        }
    }
}
2 Likes

Wow! This is just awesome! Thank you very much for this zombiegorilla!

Wow Thanks a LOT