Spline Editor

 Hello World

In this manual, we'll talk about the Spline Editor. 

With Spline Editor, you could make a spline in 3D-space:

  1. Combine with constraint system to drive object movement, e.g.: FollowPath constraint;
  2. Retrieve data on demand from the spline path in run-time; 

Here's a GIF animation that demostrates the usage of "Spline + FollowPath" to move object.

Spline1

 

 Okay, now let's get started, ლ(╹◡╹ლ)


 Get Started

Let's start with the very basic.

Currently we've these Spline implementations available:

  • Uniform Catmull-Rom Spline;
  • Centripetal Catmull-Rom Spline

And to create a spline, just add one of the available spline MonoBehaviour.

Spline2

Once you added the spline MonoBehaviour, you will see it in the scene like this:

spline3

Good, we've just made the first spline here. :D

In the next page, we'll see how to make the spline more curvy.


 Make Spline

Let's continue with what we've done in the previous page.

The spline is drawn in the scene as long as you have the GameObject with spline behaviour in selection. Developers could click the blue control points(abbr. CP) and drag them around to modify the spline.

One thing to note that, if you click another object in the scene, it will remove the SplineGO (Spline GameObject) from the selection, and stop editing the spline. This is troublesome as it's hard to not click on other objects.

To handle this, Spline editor will prevent deselecting current SplineGO by clicking on other object, if you've selected a control point. So if you need to select other objects when you're editing spline, you could click on hierarchy window to select other objects, or click "ESC" to deselect current control points.

Enough foreword, let's see how to manipulate the spline.

The image below shows the inspector GUI of Catmull-Rom Uniform Spline (the Catmull-Rom Centripetal spline's GUI is the same as this one). 

spline4

Basic control

The first line has three buttons,

  • Add Point: insert a new CP after current selected one; if current selected CP is the last one, will add the new CP along the tangent direction with average distance of segment. the selection will move to the newly created CP after this operation.
  • Del Point: delete current selected CP, move the selection to the next CP if possible;
  • Make Cycle/Break Cycle: use this option to control whether the spline should form a closed cycle;

The second line provides interface to select CP directly; the first CP has index of 0; Clicking arrow button to select the prev/next CP.

The third line is used to edit the position of selected CP;

The fourth line is to specify the "tilt" angle, which is used to tweak the "UP" direction around the CP; it makes spline to roll specified angle additively, which affects the existing "UP" direction; 

About UP direction of Spline

The spline inherently defines "FORWARD" with derivative, but it cannot defines "UP" by itself, it needs we impose some arbitrary rule to define "UP". However, in order to define the object movement with spline, "UP" is a must. (consider a jet flying straight forward and rolling, you cannot define it with spline without "UP" control)

Skele's spline editor provides two method to define "UP": "Y-up" & "Minimum";

"Y-up" could provide better control, as long as your spline doesn't have strict up/down segment; 

"Minimum" could ensure smooth "UP" direction change, but might be harder to manipulate than Y-up.


 Hotkeys

Spline editor provides several hotkeys that might help improve your workflow.

I: Insert new control point

X: Delete selected control point;

C: Set camera focus on selected control point;

ESC: deselect current control point;

 

 

Constraint System Manual

Hello World

In Skele v1.9 we introduced the Constraint System.

Constraints are special MonoBehaviours that connect multiple Transform components' properties (position/rotation/scale) in various way and can execute in edit-mode / play-mode / run-time.

All constraints only affect its owner GameObject. (Except the IK constranit which affect the whole bone link)

Each constraint has an "influence" value ranged from [0,1], it controls the percentage of effect this constraint has on its owner, from "no-effect" to "full-effect".

Every constraint is managed by some "ConstraintStack" MonoBehavioiur, which is used to control the evaluation order and activation state. One GameObject can have one constraint stack, one constraint stack can have multiple constraints. The constraints are evaluated from top to bottom in stack. we can achieve many useful motions with combination of multiple constraints. (e.g.: we could make the player's position.xz to be the average of his two feet's position.xz, with two CopyPosition constraint and influence setting. Sounds like RootMotion?)

Skele's constraint system is made to be similar to Blender's constraints system, you could also refer to the Blender's constraints reference manual.

NOTE: most of the constraints don't work with non-uniform scaling, please keep the target transform and ancestors in uniform scaling (i.e.: localscale.x == localscale.y == localscale.z ) 

Here's an intermediate example of constraint usage: We used CopyPosition, Floor, IK constraints to make walking animation. (click to open gif)

constraintEg1

 

You can find examples scenes for each constraint type in the Skele installation directory at "Assets/Skele/_ExampleScenes/Constraints", check the description and play with each example to understand how it works.

In the next pages, we'll explain each constraint's usage and options.

 

Okay, now let's get started! ლ(╹◡╹ლ)


Get Started

There're some operations that all constraints share, we would explain in this page together.

◊ ConstraintStack 

ConstraintStack is the main hub when access constraints on GameObject. When work with constraints, the first thing to do is to add ConstraintStack on GameObjects.

ConstraintStack is a standard MonoBehaviour, so you could add it like any other Behaviours.

ConstraintStack1 

The image above is a constraint stack with three constraints. As you can see, the editor mainly contains three sections:

The first section is the list of constraints. There're five items per line:

  • The constraint button, clicking this will bring up the editor panel for that constraint, also this button's background indicates the "active" and "influence" state;
  • The active button, clicking this button will toggle the active state for the constraint;
  • The move-up button, clicking this button will bring the constraint up one slot in the stack;
  • The move-down button, clicking this button will push the constraint down one slot in the stack;
  • The delete button, clicking this button will remove the constraint from stack and destroy it from owner GameObject;

The second section is the "Exec Order" used to decide the execution order among multiple ConstraintStacks. Like the Unity's script execution order setting, the lower the "ExecOrder", the earlier it gets evaluated.

The third section is the "Add Constraint" button, it will bring up the list of available constraints when you click the button. Clicking anyone in the list will automatically add the constraint into current ConstraintStack.

ConstraintStack2 


◊ Common settings of constraints

Each constraint has its own unique functionality, and unique settings.

But they do share some common settings, let's examine them here.

ConstraintStack3

The image above shows the editor for a constraint. Although there're many options inside, we only focus on those are shared by most constraints.

The first line has the "active" & "gizmos" toggles, Although all of the constraints has "Active" property, only about half of the constraints has gizmos;

The second line is the "target" field, except the LimitPostioin/Rotation/Scale, all of the constraints need a target to work;

The last line is the "influence" bar, which is shared by all of the constraints. It controls how much influence this constraint has on the owner GameObject;

 

In the next pages, we will explain each constraint with the corresponding examples scenes.

 


Copy Position 

CopyPosition constraint uses the target's position to calculate owner's position.

Check the preview image below:

CopyPosition1 


Here we explain each options in the CopyPosition editor;

CopyPosition2 

Target Obj

Specify the target object, owner's position will be dependent on the target;


Copy Rotation

CopyRotation constraint uses the target's rotation to calculate owner's rotation property.

Check the preview image below:

CopyRotation1 


Here we explain each options in the CopyRotation editor;

CopyRotation2 

Target Obj

Specify the target object, owner's euler angles will be dependent on the target;


Copy Scale 

CopyScale constraint uses the target's scale vector to calculate owner's scale vector.

Check the preview image below:

CopyScale1


Here we explain each options in the CopyScale editor;

CopyScale2 

Target Obj

Specify the target object, owner's scale vector will be dependent on the target;


Copy Transform

CopyTransform constraint uses the target's position & rotation & scale to calculate owner's position & rotation & scale.

Check the preview image below:

CopyTransform1 


Here we explain each options in the CopyTransform editor;

CopyTransform2 

Target Obj

Specify the target object, owner's Position/Rotation/Scale will be dependent on the target;


Limit Distance 

LimitDistance constraint ensures the distance between owner & target meets specific conditionts.

Check the preview image below:

LimitDistance1 


Here we explain each options in the LimitDistance editor;

LimitDistance2 

Target Obj

Specify the target object, owner's position is under the effect of this constraint to ensure that the distance between owner & target meets specified condition.


Limit Location

LimitLocation constraint ensure the position of owner to stay within specified limits.

Check the preview image below:

LimitLocation1 


Here we explain each options in the LimitLocation editor;

(You might already notice that this constraint doesn't need a target to work)

LimitLocation2 

Limits

The "Limits" provides six available limit options; The options are all independent, developers could toggle on/off any of them to fit specific needs;

E.g.:

  • If we toggle on XMin & XMax, then the position.x of owner will be limited with the given range;
  • If we toggle on only XMin, then the position.x of owner will be limited to be always larger than XMin;
  • If we toggle off both XMin & XMax, then the position.x of owner will not be affected by this constraint;

(Also, if all of the six limits are enabled, then a blue box gizmos will be drawn to indicate the limited space)


Limit Rotation

LimitRotation constraint ensure the specific components of localEulerAngles of owner to stay within limits.

Check the preview image below:

LimitRotation1 


Here we explain each options in the LimitRotation editor;

(You might already notice that this constraint doesn't need a target to work)

LimitRotation2 

Limits

The "Limits" provides three groups of limit options for each component of localEulerAngles;

Developers could turn on/off each group independently;


Limit Scale

LimitScale constraint ensures the scale of owner stays within given ranges;

Check the preview image below:

LimitScale1 


Here we explain each options in the LimitScale editor;

(You might already notice that this constraint doesn't need a target to work)

LimitScale2 

Limits

The "Limits" provides six available limit options; The options are all independent, developers could toggle on/off any of them to fit specific needs;

E.g.:

  • If we toggle on XMin & XMax, then the scale.x of owner will be limited with the given range;
  • If we toggle on only XMin, then the scale.x of owner will be limited to be always larger than XMin;
  • If we toggle off both XMin & XMax, then the scale.x of owner will not be affected by this constraint;

Transform Mapping 

TransformMapping constraint extracts vector from target's pos/euler/scale property, lerp it to generate a new vector, and applies the result to owner's some Transform property .

Check the preview image below:

TransformMapping1 


Here we explain each options in the TransformMapping editor;

This constraint is more complex than the previous ones, well, you can even tell that form the length;

This constraint could extract a source vector from target's position/euler/scale property, then mapping the source vector to destination vector with some calculation, finally, put the destination vector into the owner's specified property (could be different from source vector's source) 

TransformMapping2

Mapping

This section decides how to map vector from target to owner.

"Src data type" decides which property of target transform is used, options include: position / euler / scale;

"Dst data type" decides which property of owner transform is set to, options include: position / euler / scale;

"Source to Destination Mapping" gives a finer granularity control of vector mapping, you could control which component of source vector to be mapped to which component of destination vector. For each component of destination vector, we could select "X/Y/Z/None" to indicate which component from source vector is used (None means unchanged) 

"Extrapolate" decides whether the value mapping is continued or clamped outside the given range;


So, let's take the image above as an example.

it means to mapping target.position to owner.localScale; 

  • target.position.y => owner.localScale.x;
  • target.position.x => owner.localScale.y;
  • target.position.y => owner.localScale.z;

Maintain Volume

MaintainVolume constraint squashes/stretches object along given axis.

Check the preview image below:

MaintainVolume1 


Here we explain each options in the MaintainVolume editor;

MaintainVolume2 

Volume section

Volume section contains three parts: Base, Axis, Multiplier.

Base value is calculated with scale.x * scale.y * scale.z and is automatically set when MaintainVolume is added. Usually you could modify the Multiplier field instead of directly manipulating this.

Axis specify the axis that will trigger the squash/stretch, only scaling on that axis will make the GameObject squash/stretch; 

Multiplier is a parameter used to multiplied on Base;

The result scale would be: < Sqrt(Base*Multiplier/y), y, Sqrt(Base*Multiplier/y) > when Axis=Y;


Clamp To

ClampTo constraint binds the owner on a spline path, and moves owner based on an offset value, which is calculated based on some component of owner's position. When offset = 0, owner at the start; When offset = 1, owner at the end of spline.

(Check Spline Editor manual for instructions on how to make spline)

Check the preview image below:

ClampTo1 


Here we explain each options in the ClampTo editor;

MaintainVolume2 

Target Spline

Developers need to specify a spline in this field to make the constraint work.


Follow Path 

FollowPath constraint binds the owner on a spline path, and moves owner based on an offset value. The constraint can not only affect the owner's position, but also set the rotation of owner based on the spline's setting.

When offset = 0, owner at the start; When offset = 1, owner at the end of spline.

(Check Spline Editor manual for instructions on how to make spline)

Check the preview image below:

FollowPath1 


Here we explain each options in the FollowPath editor;

FollowPath2 

Target Spline

Developers need to specify a spline in this field to make the constraint work.


Look At

LookAt constraint controls the owner's rotation with another target object, with a specified lookAxis pointing toward the target, and a specified upAxis to help calculate the rotation.

Check the preview image below:

LookAt1 


Here we explain each options in the LookAt editor;

LookAt2 

Target

The target transform, LookAt constraint needs this target to work;


Locked Track 

LocekdTrack constraint, is kind of like LookAt constraint, but the main difference is that it only rotates around ONE axis.

So you could imagine it as a compass, and the target is the magnet.

Check the preview image below:

LockedTrack1 


Here we explain each options in the LockedTrack editor;

LockedTrack2 

Target

The target transform, this constraint needs this target to work;


IK Solver

CCD Solver(IK Solver) constraint, directly calls the CCDSolver to bend the IK link to reach the specified target, it can also utilize IK-constraints such as AngleConstraint & ConeConstraint to improve quality;

To find out how to setup IK-constraints to improve the IK solver calculation quality, check the CCDIK part of skeleton animation manual.

Check the preview image below:

IKSolver1 


Here we explain each options in the CCDSolver editor;

CCDSolver can setup the IK-link in auto-mode by "BoneCount" if all the joints are in a hierarchy formed by transform.parent.

Or user can setup manually the IK-link in manual-mode, this could enable to make up a link without constraint of hierarchy.

In most cases, auto-mode should be able to satisfy the needs.

(Be noted to click "Apply" button after modifying the link)

CCDIKSolverAuto

CCDIKSolverManual

Target

The target transform, the IK link will try best to reach the target constantly;


Child Of

ChildOf constraint makes the owner to operate like it's the child of the target transform. Plus you could also opt-out position/rotation/scale property for this pseudo relation.

This is useful when you need to attach something to some transform but doesn't want to change the real hierarchy.

Check the preview image below:

ChildOf1 


Here we explain each options in the ChildOf editor;

ChildOf2 

Target

The target transform, it will plays the pseudo parent role for owner;


Floor

Floor constraint makes the owner to stay at the specified side of a plane.

This constraint is useful to make floor & wall, and can be used to constrain foot's IK target when make walking animation.

Check the preview image below:

Floor1 


Here we explain each options in the Floor editor;

Floor2 

Target

The target transform, it will act as the plane to restrain the owner, it doesn't matter if it has mesh, we only use its transform data;


Shrink Wrap

ShrinkWrap constraint pulls the owner towards the target's mesh.

This constraint is useful to make floor & wall, and can be used to constrain foot's IK target when make walking animation.

Check the preview image below:

shrinkWrap1 


Here we explain each options in the ShrinkWrap editor;

Project method

(ShrinkWrap contraint using Project method)

shrinkWrap2 

This method will cast a ray from pivot of owner along specified direction, if it hits the target's mesh, the hit point will be taken as the new position of owner;

Target

Owner will be projected on the mesh surface of this target;

Be noted that, if the raycast from owner cannot hit on the target mesh, then the owner's position will be unchanged;

 

Nearest Vertex method

(ShrinkWrap constraint using NearestVertex method)

shrinkWrap3

This methods will put owner at the nearest vertex on the target mesh, when in editor, this method will turn on the renderer's wireframe.

Target

The target's mesh provides the vertex position for owner to project to.


Empty Marker

Empty Marker is not a constraint, it's a helper component to help developers to select GameObjects which're hard to visualize and select by usual means;

(If you're familiar with the other 3D-softwares such as Blender/Maya/etc, you should know about such helper objects already)

EmptyMarker1

See the preview image above, usually we cannot select the "spine" or "neck" transform by clicking the model in the scene, it will cycle between the root GameObject & the one with SkinnedMeshRenderer(SMR). An alternative is to select the transforms in the hierarchy window or load the selection with Ctrl+Alt+number.

EmptyMarker would be very effective and easy to use in such cases. Want to select the spine transform? just click the RectFrame mesh in the above image. 

EmptyMarker is a great partner for constraints and IK system. Check the image below (click to open gif).

constraintEg1 

These markers are automatically disabled & hidden when in game-mode & runtime, so you don't need to worry about they disrupt the scene setting or increase the performance cost.


* How to add the EmptyMarker?

1. Navigate to the target GameObject, add the "EmptyMarker" MonoBehaviour. e.g.: Hips;

2. Click the "Presets", select one from the popup list, recommend the "RectFrame";

(You could use custom meshes too, just put the mesh file under the directory "Assets/Skele/Common/Res/Marker/Models". Then when you press Presets, the new model will be found and shown in the list)

EmptyMarker2

3. When the GameObject with EmptyMarker is selected, the mesh will be tinted yellow. Now click it again to navigate to the marker's mesh GameObject (which is named as "mesh").

EmptyMarker3

4. When you select the mesh object, you could move/rotate/scale it to make it easier to select and handle later.

EmptyMarker4 


Example: Walk Motion

In this page, we'll show an example of using constraint to make animation clips. It's an intermediate-level example which involve IK, IK-constraint, constraints, helper-object, AnimationView, clip baking, clip compressing.

Be noted that making clips is only one of the many usage of constraints.

This example consists of three parts:

In the first part, you would see how to setup the IK:

  • example to set up helper objects;
  • example to set up IK solver;
  • example to set up IK-constraints;
  • Move the limb with IK solver 

To avoid confusion, I need to point it out that IK-solver could act as an independent component, developer could using it outside the Skele's Bone-Editor.

In the second part, we will show how to use CopyPosition constraint to connect the position properties from hips and the feet, so we could move the whole model by only moving the two feet.

Also we'll use Floor constraint to prevent the foot-target to burrow into the ground.

In the third part, we will show how to make the clip with what we've setup.

Then we'll show you how to bake the clip to make it also work on models without constraints;

Also you'll see how to use the Animation Compressor to reduce keyframes in the clips;

 


Auto Biped Constraint Setup Utility

In v1.9.6,we introduced this new utility to help developers setup their biped constraints swiftly.

This includes constraints to:

  • limit elbow to rotate in one plane, and limit the rotation angle;
  • limit knee to rotate in one plane, and limit the rotation angle;
  • limit shoulder's rotation range, and limit the twist range;
  • limit thigh's rotation range, and limit the twist range;

(By 'twist', we mean rotation around the primary axis, e.g.: shoulder to elbow axis)

BipedConstraintSetup

1. get started

This utility can be brought up via the menu item at "Window/Skele/SetupBipedConstraint";

2. options 

(1) The first thing to do is to fill the "Root" field; you should put the topmost GameObject of model (usually with the Animator) in there.

This field is automatically filled for you if the model is selected when the EditorWindow is opened up;

(2) The "bones" list is a bone mapping table, it is automatically filled when the "Root" field is changed.

Usually you don't need to touch anything in the list, there're some special cases though, e.g.:

  • The skeleton structure is kind of unusual, and you might need to manually change the bone mapping here;
  • You don't want to setup constraints on some limbs, so you could try removing the hands references from the list;

(3) The "Options" will affect what kind of constraints be added to the model

  • If nothing is selected, constraints will be added on shoulder/elbow/thigh/knee, this is the basic setting, it improves the IK quality when manipulate the bones;
  • If 'Add IKTarget' is selected, besides the constraints above, IK-targets will be added at wrists & ankles. They enable devs to move the limbs by dragging the IK-target, without starting the SMREditor;
  • If 'Floor constraints' is selected, you need to specify another object as Floor(check the Floor constraints page), then the IK-targets on ankles will be constrainted to not go below the floor;
  • If 'Pelvis Follow' is selected, two 'CopyPosition' constraints will be added at the 'Hips' bone, to make it stay at the center position of two ankles' IK-targets. i.e.: the model will move with the two feet.

 

You could also check the tutorial video below for reference: