Author Topic: FAQ  (Read 66261 times)

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #30 on: June 06, 2013, 10:47:05 AM »
Q: Why am I not getting the same number of draw calls as atlases in my animation? Why are there multiple instances of a material in my Skinned Mesh Renderer?

In order to draw an animation in the correct order, SmoothMoves uses a depth value. The depth value will order the triangles of a mesh to draw in the correct sequence, allowing you to move bones behind other bones. If you have a bone with a different material on it, Unity has to make a material change which costs a draw call. If there are more bones with different materials, then each change will result in another draw call.

SmoothMoves groups the draw calls into submeshes. Each submesh has its own material. It is possible that some submeshes share the same material because a submesh between them used a different material.

Example:

Let's say you have a Chef animation with the right arm and hand at depth 10. You then put a weapon bone at depth 5 which uses a different material. Finally, all the other bones are set to depth 0.

SmoothMoves has to break the mesh up into three separate submeshes (and three draw calls) to accommodate the depth and material changes, resulting in an order like:

submesh 1: (right arm and hand: chef material)
submesh 2: (weapon: weapon material)
submesh 3: (all other bones: chef material)

(in the following screenshot, z offset is used to show depth more clearly, though most likely all your triangles would be rendered in the same plane)


To avoid having extra draw calls, you can do one or all of the following:

  • Put all of your bone textures into a single atlas. This way SmoothMoves will not need to break up the bone rendering into multiple submeshes
  • Group all of your bones with the same atlas near each other in depth. For example: you could have all of your chef's bones at depths 1 through 10, then place the weapon on depth 0. This would result in two draw calls instead of three.


echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #31 on: June 06, 2013, 10:57:33 AM »
Q: Why are my events not firing on the last frame?

Events like user triggers, texture changes, atlas changes, depth changes, collider changes, and pivot changes are all governed by Unity's animation event system. Unity's system sometimes has trouble firing events on the last frame of an animation if the animation wrap mode is set to "Once" and the processor of the device it is running on is going slow.

There are a few workarounds:

1) Move your event to the second to last frame of an animation clip. This will ensure that Unity fires the event before reaching the end of the clip.

or

2) Use "ClampForever" wrap mode instead of "Once". ClampForever will continue to stay on the last frame of an animation after it has completed the clip. The downside to this is that the clip is still recognized as playing, even though it is done.

or

3) Use yield statements to perform an action after a certain amount of time. For example, to play an animation after another, you could use the following code:

Code: [Select]

using UnityEngine;
using System.Collections;
using SmoothMoves;

public class NewBehaviourScript : MonoBehaviour
{

    public BoneAnimation boneAnimation;

    void Update ()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            StartCoroutine(PlayQueuedAnimations("QuickAttack_01", "QuickAttack_01"));
        }
    }

    private IEnumerator PlayQueuedAnimations(string animation1, string animation2)
    {
        boneAnimation.Play(animation1);

        yield return new WaitForSeconds(boneAnimation[animation1].length);

        if (animation1 == animation2)
            boneAnimation.Stop(animation1);

        boneAnimation.Play(animation2);
    }
}


You can put any value in the WaitForSeconds function, this example just waits until the first animation is done by waiting the length of the first animation.

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #32 on: July 25, 2013, 02:10:22 PM »
Q: I upgraded to Unity 4.2, and now my depths are messed up. What do I do?

Unity 4.2 introduced a bug that causes sub-meshes within a mesh to batch. This is bad because it doesn't let you layer your animation's sprites with different atlases since like materials will be batched together. Ultimately, this causes the depth settings of your bones to not be used which can affect the way your animation is drawn.

UPDATE: Unity has fixed the bug in version 4.2.1.

You can download new Unity versions here:

http://unity3d.com/unity/download/


« Last Edit: September 02, 2013, 10:51:57 AM by echo17 »

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #33 on: August 05, 2013, 08:18:58 AM »
Q: How can I change my animation curve tangents without selecting each keyframe and changing the tangent?

You can easily create a batch processing script to modify your curves. Here is an example script that should get you started:

http://echo17.com/support/BatchProcessCurves.cs

To use:

  • Place the script in your project in an Editor folder. "SmoothMoves/Editor" is fine
  • Open the window by going to the Unity menu "SmoothMoves/Tools/Batch Process Curves"
  • Drag your animation data to the script
  • Select your curve type (tangent mode)
  • Select your animations, bones, and properties to modify
  • Click "Update Curves"

Note that when changing an entire curve, if one side tangent (in or out) has a constant value, then the entire curve will be constant. Some of the tangent mode options will not make sense when modifying an entire curve (like "Left Linear Right Constant", for instance), but I put every option in there to be complete in case you want to modify for your own project needs.
« Last Edit: August 05, 2013, 02:46:46 PM by echo17 »

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #34 on: August 28, 2013, 06:12:16 AM »
Q: I'm having a problem, what is the best way to get help?

Now and then you will come across a problem or question that may not be answered in these FAQs. If so, the best way to communicate the issue with me is to create a simple project that shows the problem occurring. Being able to dig into your animations and run them against my source code is the quickest way for me to see what is going on.

Please include the invoice number you received when you purchased SmoothMoves. I will only debug your projects if I can verify that you have purchased the plugin.


Keep in mind that SmoothMoves comes with the source code for the Runtime and Build portions of the plugin as of version 2.2.7. You may even be able to dig into the code and determine what is happening on your own.

Be sure to keep your project simple. Try to eliminate anything else that is not relevant to the problem so that it is easier to narrow down the issue. Larger projects will take more time to sift through and may introduce other errors not directly related to SmoothMoves. If possible, create a project from scratch and build an animation that produces the issue you are seeing.

Also, be sure to include a list of steps that I can perform to reproduce the issue. Keep in mind that I have never seen your project before and do not know how to interact with it without your guidance. Let me know what you expect to see, since what I observe may appear operational to my uninitiated eye.

Note that the more complicated your example project or the less detail you provide in how to demonstrate an issue you are seeing, the lower the priority I will assign to helping you solve your issue. Most of my time is spent helping people with my various products, so to make it fair to everyone I will choose to help those that make it easier first.

When you create your project, just zip up the entire project folder. If you send me individual assets, the links between them will be lost and I will have to recreate the project from scratch. This can possibly produce skewed results since I have created a different project from the one you have sent. The best way to determine if your project is testable is to open it yourself and try to run it.

You can send your project to the email in my signature. I try to respond as quickly as possible (with the exception of weekends, holidays, and vacation time).

Note: Please DO NOT post your project on public forums! This is a violation of the Unity Asset Store license agreement since your project will have the editor dll which you are not free to distribute.
« Last Edit: October 27, 2015, 02:00:43 PM by echo17 »

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #35 on: September 03, 2013, 05:41:39 AM »
Q: How do I modify the source code?

As of version 2.2.7, SmoothMoves comes with the runtime and build source code for the plugin. The editor code will continue to remain locked.

The runtime/build source is a solution that produces a compiled dll library, so you can't use the scripts directly in your project. You will need to extract the zip file to some location, preferably outside of your project. You can then open it in a solution editor. After you make your changes, you will need to compile the solution, then copy the dlls it produces back to your Unity project, replacing the dlls located in your SmoothMoves folder.

I personally set up a post-build copy script in my solution projects using Visual Studio to copy the dlls to my Unity project. This saves me the step of having to copy the files after a successful build. To do this:

  • Right-Click the Project you want to modify (i.e. SmoothMoves_Runtime). Select Properties from the context menu.
  • Switch to the Build Events tab
  • Enter a copy script in the Post-build event command line section



An example of your copy script might look like this. Your paths may be different depending on your project name and the location where you extracted the source code. This particular example assumes you have extracted the zip file just above your project's directory. This example's Unity project is called "Demo".

Code: [Select]

copy "$(TargetDir)$(AssemblyName).dll" "$(TargetDir)\..\..\..\..\..\Demo\Assets\SmoothMoves\Plugins\SmoothMoves\$(AssemblyName).dll" /Y


Note: You should never extract the source code into your project directory or you will get compile errors. Try to find a location outside of your project for the source. Only the compiled dlls should be in your Unity project.

You can find a free version of Visual Studio, called Visual Studio Express. Just do a Google search for this product and download.
« Last Edit: September 04, 2013, 02:07:37 PM by echo17 »

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #36 on: September 09, 2013, 06:11:25 AM »
Q: Why isn't the Flash platform supported?

Adobe seems to have abandoned their own product, leaving little choice for other tools but to stop supporting it as well. Unity has officially announced that they will no longer be supporting Flash in the future. Combine that with the issues that Flash has with the .NET environment, and you get a platform that has no traction.

Have a look at this blog by Unity's CEO David Helgason:

http://blogs.unity3d.com/2013/04/23/sunsetting-flash/

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #37 on: October 17, 2013, 01:44:13 PM »
Q: I'm using a source control program and my animations are messed up after I backup / restore. What do I do?

Source control and Unity do not generally play nicely together. Unity keeps track of assets in a project by assigning each one a unique GUID. This ID will change if an asset is overwritten by an outside process like source control. Unity also keeps track of links between assets, such as the links between atlases and their base textures, and also animations and their atlases.

If you use a source control program, or try to change an asset outside of Unity, you will effectively bypass Unity's internal database of GUID's and connections. This will lead to problems because atlases will no longer know where their textures are, and animations won't know where their atlases are.

Using the following illustration, the letters are a simplified representation of Unity's GUID system. The links between assets are symbolized by the arrows:



Now, let's say you make a change outside of Unity, like deleting the chef's hat base texture and creating a new one. Unity sees the new hat object and gives it a unique GUID and removes the old hat GUID because it no longer exists. The atlas is still looking for the old hat texture, however, so it's link is pointing to old data.



To resolve this, you will need to drag the texture into the atlas, thereby establishing the new link. Then the atlas needs to be rebuilt.

If you make a change to the atlas outside of Unity, you will need to relink your new atlas in every keyframe in the animation where the old atlas was linked.

Obviously, this is a tedious process, so it should be avoided at all costs. To keep source control on your project and create backups, you can do one of two things:

1) Package your animations, atlases, and base textures together in a Unity package. This package keeps the GUID's and connections between assets intact, allowing you to import and export into any project. You can then use source control programs on these packages. The drawback being that you have to first export the package before source control, and import the package after source control.

or

2) Zip up your entire project and source control the zip file, keeping a working archive of your progress.

For more information on sharing assets, see this FAQ:

http://www.echo17.com/forum/index.php?topic=247.msg354#msg354

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #38 on: October 25, 2013, 05:46:35 AM »
Q: When I scale my animation, my bones don't resize or move around incorrectly. What is wrong?

When you scale an animation, all the animation curves are scaled too. If you do not provide keyframes for all your curves, then you may see unintended results, such as bones scaling incorrectly or moving into the wrong positions.

Be sure that you have at least two keyframes for each property on each bone where you have an initial value set. SmoothMoves tells you where you don't have these set by displaying a small yellow triangle with an exclamation mark next to each bone and each property where you are missing keyframes. Resolving these warnings by adding a second keyframe will fix your scaled animation.


echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #39 on: November 12, 2013, 07:44:03 AM »
Q: How do I set up a rig for a character so that I can use the same animations with just different bone offsets for variations of the character?

There are probably a number of ways this can be handled. I'm a programmer, so I tend to think in terms of scripting. The solution that seems easiest to me would be to create a single animation, then in code have a number of rigs set up that will offset the bones at runtime. You can set these rigs up in the inspector so it still integrates well with Unity. The code for this might look something like:

Code: [Select]

using UnityEngine;
using System.Collections;
using SmoothMoves;

/// <summary>
/// This class is used to store the rig bone's offset. Note we are using an offset so that the
/// underlying position animation will still play, just at an offset location. The transform is
/// hidden in the inspector and cached at startup to be used later.
///
/// Also note that we only need to specify the bones that will be offset, not the entire skeleton.
/// </summary>
[System.Serializable]
public class BoneOffset
{
    /// <summary>
    /// The name of the rig bone to offset
    /// </summary>
    public string boneName;

    /// <summary>
    /// The offset value of the bone from the base animation
    /// </summary>
    public Vector3 positionOffset;

    /// <summary>
    /// Hidden transform that is cached at startup for efficiency
    /// </summary>
    [HideInInspector]
    public Transform boneTransform;
}

/// <summary>
/// This class stores the character's rig. Note that we only need to specify the bones that
/// will be offset, not the entire skeleton.
/// </summary>
[System.Serializable]
public class CharacterRig
{
    /// <summary>
    /// name of the character just for the user's benefit
    /// </summary>
    public string characterName;

    /// <summary>
    /// an array of bone offsets for this rig
    /// </summary>
    public BoneOffset[] boneOffsets;
}

public class CharacterRigModifier : MonoBehaviour {

    /// <summary>
    /// private variable that keeps track of the current monster
    /// </summary>
    private int _currentRigIndex = -1;

    /// <summary>
    /// this is the bone animation that we will be modifying
    /// </summary>
    public BoneAnimation boneAnimation;

    /// <summary>
    /// An array of character rigs that can be set up in the editor
    /// </summary>
    public CharacterRig[] characterRigs;

    void Awake()
    {

        // cache the bone transforms for each rig bone to be used later

        for (int rigIndex = 0; rigIndex < characterRigs.Length; rigIndex++)
        {
            for (int boneIndex = 0; boneIndex < characterRigs[rigIndex].boneOffsets.Length; boneIndex++)
            {
                characterRigs[rigIndex].boneOffsets[boneIndex].boneTransform = boneAnimation.GetBoneTransform(characterRigs[rigIndex].boneOffsets[boneIndex].boneName);
            }
        }
    }

    void Update()
    {

        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            // if key 1 is pressed, set the current character as character zero
            _currentRigIndex = 0;
        }
        if (Input.GetKeyDown(KeyCode.Alpha2))
        {
            // if the key 2 is pressed, set the current character as character one
            _currentRigIndex = 1;
        }

}

    void LateUpdate()
    {
        // in the late update, we will override the bones' positions by offseting them by the rig offset. Note that this
        // will only offset the bones in the rig and leave the other bones alone.

        // exit the function if we are not applying a rig
        if (_currentRigIndex == -1)
            return;

        for (int boneIndex = 0; boneIndex < characterRigs[_currentRigIndex].boneOffsets.Length; boneIndex++)
        {
            characterRigs[_currentRigIndex].boneOffsets[boneIndex].boneTransform.localPosition += characterRigs[_currentRigIndex].boneOffsets[boneIndex].positionOffset;
        }
    }
}


In the inspector, you would then set up the character rig bone offsets. Note that you only need to set up offsets for bones that will be in different positions than the base animation.



The beauty of this system is that you can still move your bones in the base animation. The rig offsets will just place the bone in a relatively new location while still following the underlying curves.
« Last Edit: November 12, 2013, 01:08:58 PM by echo17 »

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #40 on: November 27, 2013, 01:16:15 PM »
Q: How can I do a mass update to change an atlas in an animation in the editor?

You can write an editor script to go through a BoneAnimationData asset and update keyframes that have an atlas set. You'll need to replace with a new atlas as well as a new texture.

Here is a sample script to get you started. To use, just copy into your "Assets/SmoothMoves/Editor/SmoothMoves/" project folder. Go to the Unity menu "SmoothMoves > Tools > Change Animation Atlas". Drag your animation data asset to the window, select the original atlas you would like to replace, and select a new atlas to change it to. You'll need to set up a texture mapping for each texture in the atlas so that SmoothMoves knows what to update it to. Finally, click "Replace" to make the changes. The console window will output how many keyframes were updated.

Be sure to back up your animation data assets before running the script on them. (Ctrl + D will duplicate an asset) Feel free to modify the script as needed.

You can download this script here: ChangeAnimationAtlas.cs


echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #41 on: December 06, 2013, 11:11:07 AM »
Q: How can I use SmoothMoves with Unity 4.3+ 2D sprites and physics

In order to use SmoothMoves with the 2D sprites and physics introduced in Unity 4.3, you will need to make a few changes. The reason these are not included with the plugin is because SmoothMoves intends to support Unity 3.5.6+, which does not include 2D sprites and physics.

Have a look at this complete example of using SmoothMoves in Unity's 4.3 2D example:



Download here: SM2D.zip (26MB)

The SmoothMoves runtime files were modified to accommodate 2D processing. These files are: BoneAnimation.cs, AnimationBoneCollider.cs, and added Collider2DEvent.cs. The runtime and build source code comes with SmoothMoves, so you are free to modify it as you see fit.

If you would like the source code that includes these 2D changes, please send an email to the address in my signature along with your invoice number from your SmoothMoves purchase


These are the changes made to Unity's example to accommodate SmoothMoves:

  • Added a script "SortingLayer.cs" to the Scripts folder. This script ensures that the animation will be rendered on the correct 2D layer

  • Created a bone animation and placed it under the hero character gameobject

  • Added a "Weapon" layer to the project

  • Made the "Weapon" and "Enemy" layers interact in the Physics matrix


In the "PlayerControl.cs" script, these changes were made:
  • Linked to the BoneAnimation
  • Registered the 2D collider function for the BoneAnimation
  • Added input to attack in the "Update" function
  • Added animation state changes in the "FixedUpdate" function
  • Added "PlayQueuedAnimations" function
  • Added "ProcessCollider2D" function to hurt the enemy

In the "PlayerHealth.cs" script, these changes were made:
  • Added a link to the BoneAnimation
  • Play the dying animation when the health runs out

If you are just interested in setting the sorting layer or order for an animation, please see this FAQ:

http://www.echo17.com/forum/index.php?topic=247.msg2911#msg2911
« Last Edit: February 18, 2015, 06:54:43 AM by echo17 »

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #42 on: December 16, 2013, 08:04:12 AM »
Q: How do I determine what animation clip(s) are playing?

SkinnedMeshes can have multiple animations playing on them at once, so there is no concept of a "current" animation. Instead, you can either query whether a particular animation is playing or return a list of animations playing at any given time.

To determine if an animation is playing, you can use the IsPlaying function of the BoneAnimation class. Something like:

Code: [Select]

SmoothMoves.BoneAnimation boneAnimation;
bool isPlaying;

// by name
boneAnimation.IsPlaying("Run");

// or by index
boneAnimation.IsPlaying(2);


To get a list of animation clips playing, you can call something like these functions:

Code: [Select]

SmoothMoves.BoneAnimation boneAnimation;

// by name:

List<string> playingClips = new List<string>();

foreach (AnimationClipSM_Lite clip in boneAnimation.mAnimationClips)
{
    if (boneAnimation.mAnimation.IsPlaying(clip.animationName))
        playingClips.Add(clip.animationName);
}

// or by index:

List<int> playingIndices = new List<int>();

for (int i = 0; i < boneAnimation.mAnimationClips.Length; i++)
{
    if (boneAnimation.mAnimation.IsPlaying(boneAnimation.GetAnimationClipName(i)))
        playingIndices.Add(i);
}


If you are only interested in the first animation clip that is playing, then you could do something like this:

Code: [Select]

SmoothMoves.BoneAnimation boneAnimation;

// by name:

string firstPlayingAnimationName = "";

foreach (AnimationClipSM_Lite clip in boneAnimation.mAnimationClips)
{
    if (boneAnimation.mAnimation.IsPlaying(clip.animationName))
    {
        firstPlayingAnimationName = clip.animationName;
        break;
    }
}

// or by index:

int firstPlayingAnimationIndex = -1;

foreach (AnimationClipSM_Lite clip in mAnimationClips)
{
    if (mAnimation.IsPlaying(clip.animationName))
    {
        firstPlayingAnimationIndex = GetAnimationClipIndex(clip.animationName);
        break;
    }
}


echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #43 on: February 25, 2014, 12:28:19 PM »
Q: Does SmoothMoves support Mecanim? Why do I get errors stating that the animation is not retargetable?

SmoothMoves is designed to work with Unity's legacy animation system and therefore does not support Mecanim or its associated animation controller. Since Mecanim was introduced in later versions of Unity, it would not be backward-compatible with older versions that are still being used by many people. The goal of this plugin is to provide 2D skeletal animation across a wide range of Unity versions.

Mecanim also introduces more overhead in processing than the legacy system. From Unity's page on the subject:

http://docs.unity3d.com/Documentation/Manual/MecanimPeformanceandOptimization.html

Quote
Simple Animation

Playing a single Animation Clip with no blending can make Mecanim slower than the legacy animation system. The old system is very direct, sampling the curve and directly writing into the transform. Mecanim has temporary buffers it uses for blending, and there is additional copying of the sampled curve and other data. The Mecanim layout is optimized for animation blending and more complex setups.


2D animations generally don't require the same level of blending that 3D animations would since most of the mesh is just quads, one per bone. SmoothMoves still allows you to perform mixing, blending, and fading of your animations. Please see the video tutorials covering these subjects here:

http://www.youtube.com/user/echo17software/playlists

If you would like a superb alternative to Mecanim that is tightly integrated with Unity, have a look at Playmaker. This is a top-notch asset that will allow you to code any sort of state management you can dream up and is not limited to just animations, like Mecanim.

https://www.assetstore.unity3d.com/#/content/368

SmoothMoves even comes with scripts tailored to Playmaker that will help get you going quickly. You can find these here (under "Extra Goodies"):

http://echo17.com/smoothmoves.html

Have a look at this video showing a very simple SmoothMoves animation using Playmaker:

Smooth Moves Tutorial - Playmaker
« Last Edit: February 25, 2014, 12:33:27 PM by echo17 »

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #44 on: June 09, 2014, 06:07:21 AM »
Q: How do I fix errors after importing "SmoothMoves_Editor_dll_after4.3" package or after updating to Unity 4.5 or greater?

If you get these errors / warnings in the console after importing the SmoothMoves_Editor_dll_after4.3 update package:

Error: NullReferenceException: Object reference not set to an instance of an object
SmoothMoves.TextureAtlasInspector.OnInspectorGUI ()


Warning: unexpected top level layout group! Missing GUILayout.EndScrollView/EndVertical/EndHorizontal?
UnityEditor.DockArea:OnGUI()


You simply need to click on the SmoothMoves_Editor.dll and click "Reimport". Unity 4.5 has a bug where it will not automatically reimport newly added dlls that replace older dlls, so you have to manually do this yourself for now.


Unity 4.5 or later:

If this problem persists, be sure you are on SmoothMoves version 2.4.1c or greater. Also be sure that you download the package through the Asset Store download manager window and not the asset page. The Asset Store has a bug that will sometimes not update packages if you download through the asset page.



You may even need to delete the SmoothMoves folder from your project, redownload, then import to get Unity to see the changes.
« Last Edit: July 15, 2014, 06:13:00 AM by echo17 »