Distance limit setup for eyes

February 24th, 2020

final result

Flexible eye rigging can bring even more life to your characters. In this tutorial we'll create an eye rig that always looks at a target, without the iris and pupil going outside the bounds of the eyeball. This is the long form version of a tip we previously published. Let's go through it step by step!

Images setup

circle

For the purpose of this tutorial, we'll keep things simple. The eyeball is made up of a white circle image located in our image path. We drag it from the images node into the viewport, then duplicate its slot.

circle

We'll turn this second circle into the iris of the eye. All we need to do is change the color of the attachment to an iris color we like. Images can be scaled and translated independently of bones in setup mode, so we'll scale the copy down to make it smaller in proportion to the eyeball. To establish the limit beyond which iris should not move, we also translate it so that it touches the border of the white circle beneath it.

circle

Next, we duplicate the iris slot to create the pupil. Pick a new color for the image attachment and scale down the attachment as before.

Lastly, let's also add a tiny reflection of light on the pupil. Duplicate the pupil slot, make it smaller, change its color to white and place it on top of the pupil.

Finally we are ready to start creating some bones!

Bones setup

bones

To get the desired effect, we need to create 3 bones. The limiter bone originates from the center of the eyeball and extends to its border. It's angled at to make alignment easier later on.

The pupil bone is placed in the middle of the pupil, which also aligns with the midpoint of the limiter bone. All the images except the white eyeball are parented to this bone. The pupil bone itself is parented to the limiter bone.

Lastly, the target bone is placed along the axis the other two bones are placed at. It is parented to the root bone.

IK setup

ik

Time for the magic trick! As a first step, we create an IK constraint, with the limiter bone as its parent and the target bone as the target. This causes the limiter bone to always point at the target bone.

By enabling the IK compress option on the IK constraint, we allow the limiter bone to shrink and grow as the target bone comes closer to or gets farther away from it. This way, the iris and pupil can move freely within the eyeball instead of being constrained to the eyeball's border.

If we move the IK target bone around, the iris and pupil will get distorted. This is due to the parent bone's rotation and scale being applied to the pupil bone. To fix it, we simply disable the rotation and scale inheritance on the pupil bone.

inherit

Result

final result

This simple setup lets the pupil and iris follow the target bone nicely, without distortion or going outside the eyeball!

You can download the finished project here.

The setup presented above is a general way to limit movement of elements to a circular area. Can you think of other use cases? Share them on the Spine forum!

Outline shaders for spine-unity

February 10th, 2020

Outline Shader Demo

We are happy to announce outline rendering support for all shaders in our spine-unity runtime! This makes it easy to show colored selection outlines around characters, animated Spine UI elements, and much more.

Outline Shader Enable/Disable

Each shader that comes with the spine-unity runtime now provides an additional Outline section. When you enable the Outline parameter of a material, the shader will automatically be switched from Spine/shader_name to its new Spine/Outline/shader_name shader variant, and back when you disable it.

The separate outline shader ensures that no render passes are wasted where no outline is needed and keeps draw call batching optimal.

Creating and switching to outline materials

Outline Shader Duplicate Existing Material

To create an outline material, first duplicate the original material.

Note: This is the *_Material next to your skeleton asset when using a normal SkeletonRenderer, SkeletonAnimation or SkeletonMecanim. For SkeletonGraphic it is SkeletonGraphicDefault.

Select the new material and enable the Outline property via the material inspector. This will automatically switch the material to the respective outline shader variant.

Now that the outline material is prepared, you can assign it to your SkeletonRenderer and SkeletonGraphic components as usual.

Apply via SkeletonRendererCustomMaterials

  • For SkeletonRenderer, this can be via done via SkeletonRenderer.CustomMaterialOverride or by adding a SkeletonRendererCustomMaterials component.
  • For SkeletonGraphic, you can directly set the SkeletonGraphic.material property.

If you want to see an example of outlines appearing when hovering the mouse over a skeleton, please have a look at the new example scene described in section Outline Shaders example scene at the end of this blog post.

Requirements for meshes and atlas textures

How the outline shader works - neighbourhood sampling

Normally, transparent pixels within a RegionAttachment or MeshAttachment do not contribute to the frame buffer. In our outline shaders, each transparent pixel will now test whether there are opaque pixels in its neighbourhood at a certain distance. If there are, the outline color will be drawn.

Note: This requires an additional render pass of the affected skeleton to maintain correct draw order.

Image and atlas textures - add padding or whitespace

Outline Bleeding across Images

When you see outline color appearing at borders of attachments as shown above, it is most likely the outlines of nearby atlas image regions, growing into your mesh.

You can add more padding via the atlas export settings to leave enough space for the neighbour outline. You may also consider disabling whitespace stripping instead of increasing the padding.

Export Settings for Outlines

Alternatively, you can reduce outline width until this problem no longer occurs.

Mesh attachments - leave space to not cut off the outline

Outline Cut by Mesh

The outline is only drawn within the mesh borders. When you see parts of the outline cut away as shown above, your mesh borders are likely being too tightly wrapped around the opaque pixels of your images.

To fix this problem, move the mesh vertices further out to provide enough space (shown in green below). You may need to add more whitespace around the borders of your images.

Outline Move Vertices Outwards

Alternatively, you can reduce outline width until this problem no longer occurs.

Outline shaders example scene

The spine-unity runtime package now comes with an additional example scene, Spine Examples/Other Examples/Outline Shaders. This scene shows how you can switch to prepared outline material variants of existing materials on mouse over. The example scene uses EventTrigger components of the Unity event system to react to mouse pointer enter and exit events.

Conclusion

These additions to our spine-unity runtime make it easy to add colored outlines to your skeletons. Don't hesitate to share your thoughts and creations on the Spine forum!

Mesh binding tutorial

January 21st, 2020

Many characters rigged in Spine require additional images for some of their parts during their animations, for example to add perspective or visual effects. When these new parts are meshes, it can be tricky to bind them to bones and setup weights because the pose where they are needed is in an animation, not the setup pose. This post covers how to do exactly that!

Binding in animate mode

Consider this bird's wings:

We'd like to have a "flapping" animation that uses a separate mesh for the downward and upward wings, to add visual variation to the bird. We don't want to add additional bones to do it, which would clutter the skeleton and make it difficult for the two meses to behave as the same wign. Instead, the wing bone should control both meshes.

For our bird, the setup pose looks like the left side in the image above. The downward wing is bound to the body and wing bones. When the wing bone moves up and down, the mesh deforms to look like the wing is flapping.

The upward wing mesh is tricky: we want the wing bone to control the tip of the upward mesh, as it does the downward mesh, but in the setup pose the wing bone is not positioned at the tip of the upward mesh. If we bind the upward mesh to the wing bone in the setup pose, it will make controlling the mesh difficult.

The solution is to bind the bones in animate mode (note that Spine 3.8.77 or later is required). You can download the bird project if you'd like to try doing it yourself. Open bird-before.spine and go to animate mode. Move the timeline position to frame 5, which is when the wing bone is at its highest. Next, we need to place the upward wing in the right place with the Translate tool:

If Auto Key is enabled, moving the mesh in animate mode will create a deform key, as in the image above. That is fine, the following steps will work either way.

Next, click Bind in the Weights view and choose the body and wing bones. Use the Weights tool to set the top 2 vertices 100% for the wing and the bottom 2 vertices 100% for the body:

Once that is done, both wing meshes are controlled by the wing bone, making it very easy to control when switching between them:

If you show the upward wing in setup mode, you'll find that it looks odd:

This happens because it was bound to the wing bone when it was moved up in the animation, but the wing bone is moved down in the setup pose. It is normal for a mesh to look strange in setup mode when it is intended for use in a pose from an animation, not in the setup pose.

Update bindings

The important part is that the bones are in the correct position when they are bound to the mesh, which is called the "bind pose". When the bones are moved from the bind pose, the mesh will be deformed based on the mesh's vertex weights. Let's look at what happens if bones are bound in the wrong position and how that can be fixed.

Start over with the bird-before.spine project, but this time in setup mode show the upward wing and move it into position with the Translate tool. Bind it to the body and wing bones, then show the downward wing.

Next go to animate mode and move the timeline position to frame 5. The upward wing only moves with the body bone because we haven't set weights for the wing bone yet. However, if we set the weights as we did before, the result is not what we want:

Whenever the vertices move when you are adjusting weights, it means that the bones have been moved since the bones were bound to the mesh. In this case, the wing bone has been moved up from where it was bound, so the vertices will move up when weighted to the wing bone.

The Update Bindings button in the Weights view can help in this situation! When clicked, it resets the bind pose for the bones using the current bone positions and mesh vertex positions. Afterward, when weights are changed the vertices will not move.

Back in Spine, on frame 5 in animate mode, click Update Bindings, then set the weights for the wing bone. You'll find the vertices don't move and the end result is the same as if we had bound the bones in this position.

Tips and fixing mistakes

You may need to adjust the pose of bones which are bound to a mesh, without affecting the mesh. To do so, enable image compensation and adjust the bones.

You may need to redo all the weights for a mesh. To do so, click Reset in the mesh properties at the bottom of the tree. This will remove all weights and reset the mesh so it is not deformed. If you want to keep the current vertex positions, you can remove the bones in the Weights view instead of using Reset.

It can be helpful to create an animation that keys the bind pose for the bones bound to a mesh. This allows you to get back to the bind pose for adding new bones or redoing the weights for a mesh. In the bird project we can do this by going to frame 5, but this may not be easy to remember and later the bones on frame 5 might have be moved.

Conclusion

Binding bones and setting weights can be a little tricky, but is a powerful feature. Showing different meshes in the middle of animations is very common and the workflows described above make it quite easy.

We hope you found this article interesting and we'd love to continue discussion on the Spine forum.

2D and 3D physics for spine-unity

December 2nd, 2019

Hinge Chain Demo

We are happy to announce improved support for HingeJoint and HingeJoint2D chains in our spine-unity runtime! This makes it easy to add realistic cape physics to your character, have it drag heavy objects around, swing a morning star, or much more.

HingeJoint and HingeJoint2D components are used to connect a Rigidbody or Rigidbody2D to one another, constraining them to move like they are connected by a hinge. It is perfect for doors, but can also be used to model chains, pendulums, and similar objects. When set up correctly, Unity's physics will apply momentum and collision response to all the chain elements. An important requirement is that chain elements must be laid out flat on the same hierarchy level, instead of forming a parent-child hierarchy.

Previous functionality

You might note that this functionality existed in previous spine-unity versions. You may have given it a try, but likely were unhappy with the result, no matter how you tweaked the Rigidbody parameters. The reason was that gravity was being applied, but it was not able to capture movement of the skeleton or parent bones, thus lacking momentum. Starting in the spine-unity 3.8, the physics rigging respects momentum and works correctly when flipping the skeleton.

Creating hinge chains

2D and 3D hinge chains are created from an existing SkeletonUtilityBone hierarchy.

Hinge Chain Setup

Select the first SkeletonUtilityBone chain element and in the Inspector choose Create 3D Hinge Chain or Create 2D Hinge Chain to generate the physics rig. The selected element and all its SkeletonUtilityBone children are turned into a hinge chain. Adjust the Rigidbody drag and mass parameters to tweak the result to your liking. Raising the drag value will make the Rigidbody move slower and create the effect of being heavy or interacting with air.

Note that the chain root node is no longer parented to bones of the skeleton, but placed at the top hierarchy level of the scene. This is a requirement in Unity to have momentum applied properly. Do not reparent the chain root to bones of your skeleton, or chain elements will no longer be affected by skeleton movement!

2D hinge chains

  1. Create your SkeletonUtilityBone hierarchy as usual.
  2. Select the first chain element in the Scene panel and in the Inspector choose Create 2D Hinge Chain to create the 2D hinge chain rig. Create Hinge Chain 2D
  3. This will remove the GameObject chain from the previous parent (cape-root in the example) and place a new HingeChain Parent GameObject at the top level of the scene. As mentioned above, do not reparent this GameObject to the skeleton! Hinge Chain 2D Hierarchy
  4. Adjust the chain element Rigidbody drag and mass parameters to tweak the result to your liking.

Note that this GameObject contains two child objects, named Hinge Chain and Hinge Chain FlippedX. When the skeleton is flipped, these GameObject instances will automatically be activated and deactivated to enable the respective hinge chain.

3D hinge chains

  1. Create your SkeletonUtilityBone hierarchy as usual.
  2. Select the first chain element in the Scene panel and in the Inspector choose Create 3D Hinge Chain to create the 3D hinge chain rig. Create Hinge Chain 3D
  3. This will remove the GameObject chain from the previous parent (cape-root in the example) and place a new HingeChain Parent GameObject at the top level of the scene. As mentioned above, do not reparent this GameObject to the skeleton! Hinge Chain 3D Hierarchy
  4. Adjust the chain element Rigidbody drag and mass parameters to tweak the result to your liking.

When the skeleton is flipped, the HingeChain Parent GameObject will automatically be rotated by 180 degrees to adjust the hinge chain to the flipped bone locations.

These additions to our spine-unity runtime make it easy for physics to affect your skeletons for more dynamic behavior. Don't hesitate to share your thoughts and creations on the Spine forum!

Older