Author Topic: FAQ  (Read 66260 times)

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #15 on: March 01, 2013, 12:59:30 PM »
Q: When I rebuild my atlases, my animation looks messed up. How do I fix this?

When you make a change to an atlas, this will modify the uv coordinates of your textures that your animations use. This can cause existing animations to look messed up:



To get around this, you simply have to rebuild your animations. If you have the SmoothMoves control panel open with Auto-Build on, then this will happen automatically when you start the scene. Otherwise, you can force a rebuild on the bone animation scene gameobject or Force Build from the control panel to rebuild all animations in all scenes.

« Last Edit: March 01, 2013, 01:02:34 PM by echo17 »

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #16 on: March 05, 2013, 07:43:32 AM »
Q: How do I swap textures in my animation?

To swap out textures in your animation, you can use one of a number of different functions.

Note when specifying the "original" atlas and texture, you are referring to the original atlas and texture that you set up in the editor, not the current atlas and texture. This saves you from having to keep track of what the current atlas and texture is at any given time.

For all the code below, the following members are assumed to be set up:

Code: [Select]

SmoothMoves.BoneAnimation boneAnimation;
string animationName;
string boneName;
string originalAtlas;
string originalTexture;
string toAtlas;
string toTexture;


Swapping a texture across all bones and all animation clips:

Code: [Select]

boneAnimation.SwapTexture(originalAtlas, originalTexture, toAtlas, toTexture);


Swapping a texture on a single bone across all animation clips:

Code: [Select]

boneAnimation.SwapBoneTexture(boneName, originalAtlas, originalTexture, toAtlas, toTexture);


Swapping a texture on all bones in a single animation clip:

Code: [Select]

boneAnimation.SwapAnimationTexture(animationName, originalAtlas, originalTexture, toAtlas, toTexture);


Swapping a texture on a single bone in a single animation clip:

Code: [Select]

boneAnimation.SwapAnimationBoneTexture(animationName, boneName, originalAtlas, originalTexture, toAtlas, toTexture);



To restore a texture back to what is was set in the editor, you can use the various Restore functions

Restoring all textures:

Code: [Select]

boneAnimation.RestoreTextures();


Restoring the texture on a single bone across all animations:

Code: [Select]

boneAnimation.RestoreBoneTexture(boneName);


Restoring the texture on a single animation for all bones:

Code: [Select]

boneAnimation.RestoreAnimationTexture(animationName);


Restoring the texture on a single bone in a single animation:

Code: [Select]

boneAnimation.RestoreAnimationBoneTexture(animationName, boneName);


Note that you do not have to specify a new atlas, but you can use the same from and to atlas to swap a texture from within a single atlas.

Note also that if you do not set up a reference to an atlas in the animation data, then you will not be able to swap to it at runtime. You will get errors stating that the atlas cannot be found. Every atlas that you will be swapping to must have at least one reference in your animation data.

You can do this easily by creating an extra animation clip. This clip will not be played at runtime, but is just there to add keyframe references. In the first keyframe on any bone, you then set a reference to an atlas and pick a texture at random from that atlas. This gives your animation "awareness" of the atlas so it will be able to swap to it at runtime. You will need to do this for each atlas that may be swapped to at runtime. Just pick a new keyframe on any bone for each atlas reference.



Check out the API for more information:

http://echo17.com/support/smoothmoves_api_documentation/class_smooth_moves_1_1_bone_animation.html
« Last Edit: April 14, 2014, 11:41:30 AM by echo17 »

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #17 on: March 08, 2013, 02:38:27 PM »
Q: What platforms are supported?

SmoothMoves has been tested on:

  • iOS
  • Android
  • PC
  • Mac
  • Webplayer
  • WP8

SmoothMoves will not run on Flash due to the fact that Flash does not utilize the full .NET library. SmoothMoves requires some .NET structures that Flash does not implement.

If you want to try it on other platforms, you can download the FREE minigame "Rise of the Dough" from the Unity Asset Store. This minigame uses SmoothMoves for all of its animations, so if it builds and runs on the platform you choose, then the plugin should work on that platform too.

Rise of the Dough: https://www.assetstore.unity3d.com/en/#!/content/5162
« Last Edit: June 30, 2014, 01:50:27 PM by echo17 »

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #18 on: March 08, 2013, 02:40:19 PM »
Q: What Unity licenses / versions are supported?

SmoothMoves will run on both Indie (free) and Pro versions of Unity, 3.5.6+
« Last Edit: March 11, 2013, 06:21:23 AM by echo17 »

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #19 on: March 08, 2013, 02:51:12 PM »
Q: Are there any examples of games made with SmoothMoves?

There sure are!

Rise of the Dough (by echo17)
http://www.echo17.com/smoothmoves_riseofthedough.html

You can also download "Rise of the Dough" Unity project on the Asset Store for FREE here:
http://u3d.as/content/echo17/rise-of-the-dough/3A4

Check out the WIP Showcase board here:

http://www.echo17.com/forum/index.php?board=7.0
« Last Edit: October 07, 2013, 10:38:50 AM by echo17 »

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #20 on: March 08, 2013, 03:08:34 PM »
Q: How do I make an animation face the other direction?

There are two ways you can accomplish this:

1. Rotate the animation's transform on the y axis by 180 degrees

In the inspector:



In code:

Code: [Select]
SmoothMoves.BoneAnimation boneAnimation;
boneAnimation.transform.localEulerAngles = new Vector3(0, 180.0f, 0);

This will show the back faces of the animation's mesh, so you will need to be sure you have a shader that does not cull backfaces for this to work. The default shader that the Texture Atlas editor creates will work fine (alpha blended particles), but you can just as easily use your own.

OR

2. Scale the animation's transform on the x axis -1.0f

In the inspector:



In code:

Code: [Select]
SmoothMoves.BoneAnimation boneAnimation;
boneAnimation.transform.localScale = new Vector3(-1.0f, 0, 0);

Since SmoothMoves renders the triangles of the mesh in order of depth (higher depth rendered first), you will always have your animation rendered correctly, no matter which way it is facing.

Note: if you are using the rotation method and you have bones with different z positions, these will be reversed after the rotation. If you are using the z position at all, you might want to try the scaling method.
« Last Edit: October 22, 2013, 08:44:37 AM by echo17 »

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #21 on: March 18, 2013, 02:02:52 PM »
Q: How do I change the properties of a sprite at runtime?

You can swap atlases, materials, textures, and colors of sprites at runtime with just a few lines of code.

When swapping atlases, be sure to set the texture afterward or your sprite will not show anything.

You can swap textures by GUID or name. GUID is a global identifier for a source texture that is shared among all the atlases that texture shows up in. If you will be swapping to an entirely new texture in a different atlas, I'd suggest swapping the texture by name. Using this method you would need to be sure your source textures that will be swapped are named the same for each atlas.

When setting color, be sure you have a shader that supports vertex colors, like the default shader assigned by SmoothMoves (Particles/Alpha Blended).

Here is some sample code that swaps atlases, swaps textures, and changes colors on a sprite:

Code: [Select]

    public SmoothMoves.Sprite sprite;
    public SmoothMoves.TextureAtlas atlas1;
    public SmoothMoves.TextureAtlas atlas2;

    void Update ()
    {
        // swap to the first atlas
        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            sprite.SetAtlas(atlas1);
            sprite.SetTextureName("Head");
        }

        // swap to the second atlas
        if (Input.GetKeyDown(KeyCode.Alpha2))
        {
            sprite.SetAtlas(atlas2);
            sprite.SetTextureName("Head");
        }

        // change to the "Head" texture
        if (Input.GetKeyDown(KeyCode.H))
        {
            sprite.SetTextureName("Head");
        }

        // change to the "Body" texture
        if (Input.GetKeyDown(KeyCode.B))
        {
            sprite.SetTextureName("Body");
        }


        // set the color to a red with half alpha strength
        if (Input.GetKeyDown(KeyCode.C))
        {
            sprite.SetColor(new Color(1.0f, 0, 0, 0.5f));
        }

        // set the color to white
        if (Input.GetKeyDown(KeyCode.X))
        {
            sprite.SetColor(Color.white);
        }
    }


If you want to just swap materials, both materials will need to reference an atlas texture that has the exact same layout of elements. You could even have two materials referencing the same atlas texture. This would be useful if you just wanted to process the texture differently (swapping from alpha blending to multiply, for instance).

Here is how to swap materials:

Code: [Select]

    private MeshRenderer _meshRenderer;

    public SmoothMoves.Sprite sprite;
    public Material material1;
    public Material material2;

    void Start()
    {
        _meshRenderer = sprite.GetComponent<MeshRenderer>();
    }

    void Update ()
    {
        if (Input.GetKeyDown(KeyCode.O))
        {
            _meshRenderer.material = material1;
            sprite.SetTextureGUID(sprite.atlas.GetTextureGUIDFromName("Head"));
        }
        if (Input.GetKeyDown(KeyCode.P))
        {
            _meshRenderer.material = material2;
            sprite.SetTextureGUID(sprite.atlas.GetTextureGUIDFromName("Head"));
        }

    }

« Last Edit: April 29, 2013, 09:04:35 AM by echo17 »

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #22 on: March 19, 2013, 06:50:33 AM »
Q: How do I switch textures for multiple resolutions (SD / HD / Retina / etc)?

It is best to create your textures at the highest resolution that will be needed (or even higher to allow future, higher resolutions). The atlas that uses these high resolution textures is the one you will assign to your animation in the editor. If you wish to switch to a lower resolution at runtime, you can do this easily with a SwapMaterial call.

But first, you will need to create lower resolution textures to switch to.

1) Select your high resolution material and atlas texture in the project window. Go to the Unity menu "Edit > Duplicate". A copy of your original material and texture will appear in the project window.



2) Assign your duplicated texture to the duplicated atlas by dragging and dropping the texture onto the material's texture window.



3) Adjust your duplicated texture size to a lower value. This will depend on what your lower resolution will be, perhaps half the size or less. In the example we're setting it to some extremely low value to make the switch clear



4) In your script, swap the material at runtime. You'll probably want to put in some logic to determine whether the texture should be swapped, perhaps detecting the device you are running on.

Code: [Select]

using UnityEngine;
using System.Collections;
using SmoothMoves;

public class Swap : MonoBehaviour
{

    public BoneAnimation boneAnimation;
    public Material fromMaterial;
    public Material toMaterial;

    void Start ()
    {
        boneAnimation.SwapMaterial(fromMaterial, toMaterial);
    }
}


5) Assign your objects in the hierarchy window



When you run your scene, you will see the swapped textures



Note that in this example we only swapped out the Chef's material, leaving the weapon material unswapped. You can see that the weapon is still at full resolution. In a real game, you would probably want to swap out all your materials to a lower resolution, repeating the steps above for each material / texture.

The animation does not need to be restructured to accommodate the new material since the skinned mesh uses UV coordinates to map the texture. UV coordinates are relative from 0 to 1 so any size texture will work as long as the duplicated textures have the same layout.

You are not limited to swapping to just a single new material. You could have any number of alternate materials / textures set up for different resolutions. You will just need to use some logic to determine which material will be the best one for the device your game is running on.

Note that any time your atlas changes (after an atlas rebuild), you will need to make copies of your duplicated textures (you can leave the duplicated materials alone).
« Last Edit: March 19, 2013, 08:08:13 AM by echo17 »

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #23 on: March 19, 2013, 07:08:47 AM »
Q: How do I change a material / shader on my animations?

You can switch out materials (and therefore shaders) at runtime using the SwapMaterial function.

1) Create a new material and rename it.



2) Drag the atlas texture to the new material. Set the material's shader and properties.

Note that we are dragging the original atlas texture, not creating a new texture. Both materials will use the same original texture.



3) Create a method in your script to swap the material

Code: [Select]

using UnityEngine;
using System.Collections;
using SmoothMoves;

public class Swap : MonoBehaviour {

    public BoneAnimation boneAnimation;
    public Material fromMaterial;
    public Material toMaterial;

    void Start ()
    {
        boneAnimation.SwapMaterial(fromMaterial, toMaterial);
    }
}


4) Assign your objects in the Hierarchy.



At runtime, your original material will be swapped with the new material, and therefore the new shader.




Mapping a new atlas based on an old atlas:

If you want to create a new atlas texture that has the same layout of a current atlas texture, you can use the following scripts:

http://www.echo17.com/support/AtlasReplacer.zip

Instructions are included with the package. Basically, you set up a replacement file that maps your old textures to your new textures. The new textures have to have the same dimensions as the textures they will be mapping. You can reuse this file anytime you make changes to your source textures to regenerate a new atlas texture.




« Last Edit: September 13, 2013, 01:55:47 PM by echo17 »

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #24 on: March 22, 2013, 03:06:58 PM »
Q: What workflow & Apps do you recommend to create SmoothMoves characters?

There are a number of different ways to create the artwork for your animations, each with their own advantages, but here's how I do it:

  • Draw my art in Adobe Ideas on my iPad / iPhone, save in the creative cloud
  • Import from creative cloud on my computer, clean up the art in Illustrator and export to png
  • Solidify and scale in Photoshop (see this FAQ for info about solidifying)
  • Import into Unity, build atlases, build animations, etc.

Adobe Ideas

Adobe Ideas is something I've just discovered and it's perfect for cartoon inking. It's vector based, so you don't have to worry about resolutions, which is great when working on a small device like the iPad or iPhone. Vector art also allows you to later scale up if a new device with super-duper retina comes out. Check out this link by an artist who uses Adobe Ideas to ink their cartoons: http://ericmerced.com/

It only allows 10 layers, however, so I have to create a new drawing for each body part since each body part has ink, color, shading, and highlight layers. Here's how I do that:

  • Create a sketch of my character on one layer, save the drawing
  • Duplicate the sketch image, naming it to the body part I'm working on
  • Ink the body part on a new layer
  • Color the body part on a layer below the ink layer (sometimes I make several color layers for ease of use)
  • Shade the body part on a layer above the color layer(s) and below the ink layer. For shade, I just use 100% solid pencil with black ink. I then set the layer transparency to 10-20%.
  • Highlight the body part on a layer above the shade layer and below the ink layer
  • Repeat steps 2 - 6 for each body part

Example of my sketch split up into body parts. Each frame is a separate drawing, I just combined them for simplicity here. The first drawing shows the original sketch. Each drawing has the sketch layer, I just hide it before exporting.



Here is a screenshot of Adobe Ideas for the head body part. You can see that the body part has several layers: ink, a couple of color layers, shading, and sketch



You end up with a lot of drawings for one character, but I love the portability of the iPad / iPhone for drawing. I went through many different tools to try to find the best solution for me: Cintiq, Samsung Slate, Fujitsu Lifepad, Pressure sensitive styli for iPad (pogo connect and jot touch), but in the end vector art on the iPad with a regular stylus was my happy spot (and the cheapest alternative).

Some other drawing apps & programs I've used and like:

  • Adobe Ideas (iPad / iPhone / Android [Android only has one layer]): link
  • Autodesk Sketchbook (pc / mac / iPad / iPhone / Android): link
  • Procreate (iPad): link
  • Photoshop (pc / mac / iPad / Android): link
  • Illustrator: (pc / mac): link
« Last Edit: June 05, 2013, 06:45:08 AM by echo17 »

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #25 on: May 16, 2013, 02:11:30 PM »
Q: Why do queued animations not process color?

When you call a queued function like PlayQueued or CrossFadeQueued, Unity actually makes a copy of the animation state to play at a later time. This is done so that you can cross fade and mix with the same animation. See these links:

http://docs.unity3d.com/Documentation/ScriptReference/Animation.PlayQueued.html
http://docs.unity3d.com/Documentation/ScriptReference/Animation.CrossFadeQueued.html

Because the animation state is copied and not part of the normal array of animations that are currently playing, SmoothMoves cannot see the state. Since the state is not visible, SmoothMoves will not know to blend colors on the queued animation.

There are ways around this, the most popular are:

1) Use a yield statement to play one animation after another. This is by far the simplest and lightest method. Something like:

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);
    }
}

2) Set a user trigger to fire at the end of one animation to start the next animation. Something like:

Code: [Select]

using UnityEngine;
using System.Collections;
using SmoothMoves;

public class NewBehaviourScript1 : MonoBehaviour
{
    private bool _quickAttackStarted = false;

    public BoneAnimation boneAnimation;

    void Start()
    {
        boneAnimation.RegisterUserTriggerDelegate(UserTrigger);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            _quickAttackStarted = true;
            boneAnimation.Play("QuickAttack_01");
        }
    }

    private void UserTrigger(UserTriggerEvent ute)
    {
        if (ute.tag == "Quick Attack 01 Done")
        {
            if (_quickAttackStarted)
            {
                if (boneAnimation.IsPlaying("QuickAttack_01"))
                    boneAnimation.Stop("QuickAttack_01");

                boneAnimation.Play("QuickAttack_01");
            }

            _quickAttackStarted = false;
        }
    }
}


The second method example assumes you have set a user trigger in your animation called "Quick Attack 01 Done" on the last frame of the "QuickAttack_01" animation



echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #26 on: May 20, 2013, 06:03:19 AM »
Q: How can I copy keyframe data from one animation to another?

Using the script below, you can either create a new clip or replace keyframes in an existing clip. You can also specify what bones you want to copy from so that you don't have to have the same skeleton in each animation.

Download the following script:

http://www.echo17.com/support/CopyAnimationClipWindow.cs

Instructions:

To run, first copy the script "CopyAnimationClipWindow" to the SmoothMoves editor folder. Then, go to the Unity menu: "SmoothMoves > Tools > Copy Animation Clip".

Interface:

Refresh Data button: updates animations, clips, and bones if they have changed since the window was opened.
"Create" and "Replace" mode buttons: Switches between copying keyframes into a new clip and replacing keyframes in an existing clip.

Select a "from" animation, then a clip in that animation. You can then specify the bones you want to copy. If you are creating, you just select the animation you want to copy to. If you are replacing, you will also need to select a clip to replace keyframes in.

To run, click the "Run" button at the bottom of the screen. If all goes well, you will see a "Success" message.

Restrictions:
1) All the bones selected in the interface must be present in the animation you are copying to (the bone names must be present).
2) If you are in Create mode, the animation you are copying to must have at least one animation clip present (even if that clip has no data). This is because if you don't specify every bone, it has to copy the starting keyframe for the other bones from the default clip (first clip) of the "to" animation.
3) Bone names are case sensitive.

Be aware that keyframe data is relative to the parent bones, so if you don't copy all bones, you may get different behavior in your "to" animation. For example, using my chef animation, if you only copy the hand bone of a clip and not each bone in the bone hierarchy tied to the hand (Root > Bounce > Body > Arm Left > Hand Left), then the hand will not move exactly the same since its transforms are dependent upon its parents.

Feel free to modify the code as you see fit. There might be bugs or improvements you can implement.

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #27 on: May 20, 2013, 12:57:44 PM »
Q: How do I use SmoothMoves with Playmaker?

There are a set of SmoothMoves action scripts for Playmaker located here:
http://www.echo17.com/support/playmaker_smoothmoves_actions.rar - extract to your Playmaker Actions folder

You can also download a unity package that includes some example demos of how to use the action scripts here:
http://www.echo17.com/support/smoothmoves_playmaker_unitypackage.rar - extract, then import into your project containing SmoothMoves and Playmaker

« Last Edit: May 21, 2013, 05:58:50 AM by echo17 »

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #28 on: May 30, 2013, 06:20:33 AM »
Q: How can I anchor bones so that they follow other bones without scaling?

First, you'll need to set up your bones so that you have a base bone, an anchor bone that follows the base bone, and the bone you want to follow the anchor. The anchor bone should be a child of base bone, but the follow bone should not. In code you will make your follow bone set its position to the anchor bone.

Example:

Base Bone: Body
Anchor Bone: Arm Anchor
Follow Bone: Arm



Now when you scale the base bone, the anchor bone will follow the base bone, but the follow bone will stay where it is. It is important to note that you'll need to have at least two keyframes for the anchor point, even through it doesn't move, in order for SmoothMoves to generate an animation curve.



Now, you'll create a super simple script that makes the follow bone's position the same as the anchor bone every frame (in the LateUpdate after all the animations are done).

Code: [Select]

using UnityEngine;
using SmoothMoves;

public class Anchor : MonoBehaviour
{
    private Transform _anchorTransform;
    private Transform _followAnchorTransform;

    public BoneAnimation boneAnimation;
    public string anchorBoneName;
    public string followAnchorBoneName;
   
    void Start ()
    {
        _anchorTransform = boneAnimation.GetBoneTransform(anchorBoneName);
        _followAnchorTransform = boneAnimation.GetBoneTransform(followAnchorBoneName);
    }

    void LateUpdate ()
    {
        _followAnchorTransform.position = _anchorTransform.position;
    }
}


In the inspector, you'll set the anchor bone and follow bones.



Now the follow bone moves along with the base bone without distorting due to scaling.

You can find a complete example project here. Just extract, then import into a Unity project:

http://echo17.com/support/Anchor.rar

echo17

  • Administrator
  • *****
  • Posts: 1108
    • View Profile
Re: FAQ
« Reply #29 on: June 02, 2013, 04:16:02 AM »
Q: How do I set up my own animation events? How can I set certain frames to trigger external events like playing a sound, etc.?

SmoothMoves has what are called User Triggers that let you call functions in your scripts to perform just about anything you can think of. You set a user trigger in the animation editor, give it a tag, then set up a delegate in your script to process the user triggers.

Set up the user trigger

In the animation editor, set a keyframe and toggle the User Trigger on. Give the user trigger a tag. Note that you can give multiple user triggers the same tag if they will be performing the same task (playing the same sound, for example). This allows you to have fewer logic branches in your code when deciding how to process a user trigger.



Set up the user trigger delegate in your script

In your code, tell your bone animation what delegate to use to process the user triggers for that animation. Then set up the delegate and your logic to handle the trigger.

Code: [Select]

public SmoothMoves.BoneAnimation boneAnimation;
public AudioSource swishSound;

void Start()
{
    boneAnimation.RegisterUserTriggerDelegate(UserTrigger);
}

private void UserTrigger(SmoothMoves.UserTriggerEvent userTriggerEvent)
{
    if (userTriggerEvent.tag == "play swish")
    {
        swishSound.Play();
    }
}


You can see this in action in the Rise of the Dough minigame that comes with SmoothMoves in the Chef script.