Search Unity

Smooth Moves - 2D Skeletal Animation

Discussion in 'Assets and Asset Store' started by echo17, Feb 20, 2012.

  1. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    If this is happening after the clip has completed, you might try to explicitly stop the other clip. I know there is an issue with triggers that keep firing on cross faded clips with the current animation event system. I'm overhauling this to use Unity animation events to avoid this issue, but that won't be ready until the next release.


    That's a good idea. I'll add it to my list of items to consider.
     
  2. geo123

    geo123

    Joined:
    Nov 20, 2012
    Posts:
    10
    Hi Echo,
    Many thanks for you prompt reply.

    I had another question that after create a enemy walking animation clip. Can I control the the animation play FPS using script. So when I adjust the moving speed of enemy, I want the walking animation clip play faster.


     
  3. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    Yep, you can control your animation speed in two different ways.

    Have a look at a post on my dedicated forum here
     
  4. geo123

    geo123

    Joined:
    Nov 20, 2012
    Posts:
    10
    Hi Echo,
    Thanks. Thanks for your help.

    One more questions. I can see in the inspector allow change tint color of shader.
    So how to refer to that property in bone animation in order let me change it using script.

     
  5. sanjodev

    sanjodev

    Joined:
    May 29, 2012
    Posts:
    63
  6. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    You can change the mesh color of an animation through the function SetMeshColor. Using this function is better than setting the mesh color property directly because it will update the necessary structures for you.

    Code (csharp):
    1.  
    2.  
    3. SmoothMoves.BoneAnimation boneAnimation;
    4.  
    5. boneAnimation.SetMeshColor(Color.red);
    6.  
    7.  
    8.  
    You can also turn on and off color processing in code. This is helpful if you don't want to constantly be processing color blending when no color changes are occurring (improving performance).

    Code (csharp):
    1.  
    2.  
    3. SmoothMoves.BoneAnimation boneAnimation;
    4.  
    5. boneAnimation.updateColors = true;
    6.  
    7.  
     
  7. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    Very cool. I love the animations. This is a great example of how well smooth animations can excel over traditional sprite animations. Good luck with your game!

    I've added a spot to my showcase in the first post of this thread. If you want, you can also start a thread in my Forum's Showcase Board
     
  8. geo123

    geo123

    Joined:
    Nov 20, 2012
    Posts:
    10
    I had change the Meshcolor as you say. It is unlucky that it didn't work. There two property in inspector that is bone animation script Mesh color
    and shader Tint color. I only can see the color change when update shader tint color. What going wrong with it?

     
  9. geo123

    geo123

    Joined:
    Nov 20, 2012
    Posts:
    10
    Oh sorry ,
    it should be set boneAnimation.updateColors = true not false.. before MeshColor setting take effect.
    Actually I want my character go into angry state. by using itween do color change to present a color transition effect on the character.
    I believe that it can be achieve by add one more clip in smoothmove animation. But I think using itween is much simple which what I need is just change the color property. If adapt this approach, I had to access color property of the bone animation instead of call SetMeshColor. Don't know there is conflict with smoothmove animation.

     
  10. xikky

    xikky

    Joined:
    Dec 11, 2012
    Posts:
    47
    How can I set up a bone animation with a character control? I tried hard to make this work but the animation either does not move or does not move how it should.
    Any tips pls?
     
  11. runonthespot

    runonthespot

    Joined:
    Sep 29, 2010
    Posts:
    305
    HI there,

    I have a situation where I want a procedurally animated projectile to hit one of my smooth moves characters at a specific point. I created a bone without an associated sprite calling it "target". Can you suggest the best strategy for this? Referencing the bone directly didn't work too well when rebuilding the animation, so currently I have it using transform.Find to locate the object.

    Thanks,
    Mike
     
  12. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    As long as UpdateColors is set to true, you should be able to set the color of the mesh with:

    Code (csharp):
    1.  
    2.  
    3. SmoothMoves.BoneAnimation boneAnimation;
    4.  
    5. boneAnimation.mMeshColor = Color.red;
    6.  
    7.  
     
  13. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    Take a look at the project "Rise of the Dough" included with the SmoothMoves plugin. The "Chef" game object has a character controller attached, so you should be able to use this as an example.
     
  14. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    You can get a reference to a bone's transform using:

    Code (csharp):
    1.  
    2.  
    3. SmoothMoves.BoneAnimation boneAnimation;
    4. string boneName;
    5. Transform boneTransform;
    6.  
    7. boneTransform = boneAnimation.GetBoneTransform(boneName);
    8.  
    9.  
    BoneAnimation's API docs.
     
  15. runonthespot

    runonthespot

    Joined:
    Sep 29, 2010
    Posts:
    305
    Brilliant! Thanks! I missed that.
     
  16. Mars91

    Mars91

    Joined:
    Mar 6, 2012
    Posts:
    572
    How can I change material to an animated obj?
    If I change it using the inspector when I press play the material back to the original one so I wrote a custom script to change material on start but it do not worked, then I move the script into Update() but sometimes, for a single frame, the material back to the original one.
    Is there a way to change the material to an animated sprite?
     
  17. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    Not for a sprite, no. You can change the material to a bone animation using:

    Code (csharp):
    1.  
    2.  
    3. SmoothMoves.BoneAnimation boneAnimation;
    4. Material originalMaterial;
    5. Material newMaterial;
    6.  
    7. boneAnimation.SwapMaterial(originalMaterial, newMaterial);
    8.  
    9.  
     
  18. Firelight

    Firelight

    Joined:
    Feb 13, 2013
    Posts:
    1
    This is a very cool plugin, hat down for the effort, but unfortunate each animated object in the scene creates a new draw call... for me this is a way to big limitation to even consider the using the plugin...

    My final option is to use spriter to create the animations and than create animated sprites using tk2D because I need a lot of monsters in the scene...
     
  19. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    Thanks for the kind words! Yeah, SmoothMoves creates skinned meshes to get access to the amazing capabilities that Unity provides. Unfortunately, Unity will not dynamically batch skinned meshes, so you will get at least one draw call per animation.

    What I do in my personal projects is to have a hybrid of tools:

    1) SmoothMoves for my few smoothly animated characters
    2) 2DTK for my animated and static sprites (backgrounds, props, etc)
    3) nGUI for my interface

    This trinity seems to work pretty well, giving you a good draw count for the capabilities you get out of it.
     
  20. OverridingTrombe

    OverridingTrombe

    Joined:
    Dec 17, 2012
    Posts:
    6
    Edit: Ignore this post for a while. I've tried on other SmoothMoves animation I have but they don't have this error. Working on it.


    Edit2: Solved. Apparently I put the reference in Awake() instead of Start(). The errors went away after that. Cheers

    Hello there echo17. This tool is really awesome indeed (heck it accelerated my development quite a lot!), but I find these troubling:

    First case:
    I do not know if this been asked before but if you Instantiate a GameObject that have BoneAnimation attached on runtime, I get the null reference exception log maybe (due to unity not finding that BoneAnimation ) although the bone animation reference still works (as in they did crossfade in the GameView)..

    Second Case (related from the first)
    Tried it by duplicating the same GameObject before runtime (hence two identical GameObject), click Play, and null ref exception was logged on the duplicate, not on the original.

    Nevertheless, SmoothMoves ForceBuild tool remove that nag away on the second case though, but does that means that you actually have to build all the SmoothMoves reference before runtime? Instantiating these guys on runtime feels a bit erratic due to this null reference errors I have for GameObject with SmoothMoves.
     
    Last edited: Feb 14, 2013
  21. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    Yeah, SmoothMoves needs to build its dictionaries in the Awake function of the bone animation. Since your script's awake may be called before the bone animation, those dictionaries might not be set up yet. Your solution to move the code to the Start is the correct one.
     
  22. OverridingTrombe

    OverridingTrombe

    Joined:
    Dec 17, 2012
    Posts:
    6
    Final question (sorry >.<):

    How do you 'access' bones in the animation? I'm wondering this since you have RestoreAllOriginalBoneColors() and I can't find any way to access it from the online docs.

    I ask this because I'm going to iterate through each of them to change its color since changing the mesh color currently changes all of my cloned animations (I do see that you can unlink them for Sprites, but not for Bone Animations).
     
  23. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    There is a hidden structure in BoneAnimation called mBoneSource that is an array of the class AnimationBone. AnimationBone contains bone names, transforms, etc. I hide this data because modifying it directly (without going through the editor) can cause problems. Iterating should be okay, though.

    Code (csharp):
    1.  
    2.  
    3. SmoothMoves.BoneAnimation boneAnimation;
    4. Color c;
    5.  
    6. foreach (AnimationBone bone in boneAnimation.mBoneSource)
    7. {
    8.     Debug.Log("Bone Name = " + bone.boneName + ", Position = " + bone.boneTransform.position);
    9.  
    10.     boneAnimation.SetBoneColor(bone.boneName, c, 1.0f);
    11. }
    12.  
    13.  
     
  24. OverridingTrombe

    OverridingTrombe

    Joined:
    Dec 17, 2012
    Posts:
    6
    Brilliant! Thank you for that! Was iterating through all the bones transform and trimmed the strings earlier (not pretty...).

    Definitely would put up a good word about SmoothMoves anyday now. Keep up the great work! :cool:
     
  25. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    You're most welcome!
     
  26. danboutros

    danboutros

    Joined:
    Mar 26, 2012
    Posts:
    32

    FOLLOW UP QUESTION!

    Let's say I wanted to copy > paste JUST the layer info of the collider, but have it paste across all frames on a limb WITHOUT affecting other settings of an animation. How would I do that?
     
  27. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    No easy way to do that currently. I have a setting to copy the collider property, but that grabs all of the collider settings (size, center, type, layer). For just the layer, you'll need to go into the keyframes and manually change the layer values.
     
  28. danboutros

    danboutros

    Joined:
    Mar 26, 2012
    Posts:
    32
    Well then...

    NEW WISHLIST ITEM!
    A little icon near a group of settings that you can choose:
    - "copy settings",
    - "paste settings to this frame",
    - "paste setting to all frames",
    - "paste settings to all frames with this bone in this SM file".
     
  29. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    Interesting ideas. I'll add them to my list of items to consider.
     
  30. danboutros

    danboutros

    Joined:
    Mar 26, 2012
    Posts:
    32
    Thank you kind sir. Please know that I am a designer and I find these quick-tweak / global-tweak solutions highly helpful. Having to get granular tends to slow the design flow down.

    BTW, your tool has been central to our game, so many thanks for making.
     
  31. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    You are most welcome!
     
  32. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    Controlling Bones Through Code

    Hey everyone!

    Just wanted to let you know that there is a MUCH simpler solution to overriding your bones in code. I had told everyone before to leave out keyframes for the bones you want to override because Unity will take over the animation and not let you modify the transforms. This led to complicated animations and mixing, much more difficult than it needed to be.

    Instead, you can leave your animations fully intact, with every bone having keyframes. All you have to do is control your bones' transforms in the LateUpdate (instead of the Update) function. This processes the transforms after Unity has done its thing, so it just works!

    For those who have no idea what I'm talking about, or why you would ever want to override your bones, here's an example: Say you want your character to aim their weapon where the mouse is located. You could do something like this in code:

    Code (csharp):
    1.  
    2.  
    3. using UnityEngine;
    4. using SmoothMoves;
    5.  
    6. // simple script to aim a character's left arm at the mouse
    7. public class Aim : MonoBehaviour
    8. {
    9.     // internal variables used to store values so that we don't have allocs at runtime
    10.     private Transform _leftArmTransform;
    11.     private Vector3 _transformScreenPosition;
    12.     private Vector3 _leftArmRotation;
    13.     private Vector3 _mouseOffset;
    14.  
    15.     // references for the Inspector
    16.     public BoneAnimation boneAnimation;
    17.     public Camera camera;
    18.  
    19.     void Start ()
    20.     {
    21.         // cache our transform for faster processing later
    22.         _leftArmTransform = boneAnimation.GetBoneTransform("Arm L");
    23.  
    24.         // set the arm rotation to zero
    25.         _leftArmRotation = Vector3.zero;
    26.      
    27.         // play the idle animation
    28.         boneAnimation.Play("Idle");
    29.     }
    30.    
    31.     void Update ()
    32.     {
    33.         // don't want to override here, Unity's animation will stamp on any changes
    34.     }
    35.    
    36.     // bone processing goes here, after Unity has made its changes using its animation processes
    37.     void LateUpdate()
    38.     {
    39.         // check to see if the mouse button is down
    40.         if (Input.GetMouseButton(0))
    41.         {
    42.             // set the arm's transform
    43.             SetArm();
    44.         }      
    45.     }
    46.  
    47.     // this function calculates the arm's rotation and sets the arm's bone
    48.     private void SetArm()
    49.     {
    50.         // get the screen position of the arm bone (relative to the camera)
    51.         _transformScreenPosition = camera.WorldToScreenPoint(_leftArmTransform.position);
    52.  
    53.         // get the offset vector from the arm's screen position to the mouse position
    54.         _mouseOffset = (Input.mousePosition - _transformScreenPosition);
    55.  
    56.         // calculate the z rotation angle using the tan of y/x
    57.         _leftArmRotation.z = Mathf.Atan2(_mouseOffset.y, _mouseOffset.x) * Mathf.Rad2Deg;
    58.  
    59.         // set the arm's rotation
    60.         _leftArmTransform.eulerAngles = _leftArmRotation;
    61.     }
    62. }
    63.  
    64.  
    This could also be used to move bones, look at objects, rotate eyes, etc. Hope this helps!
     
    Last edited: Feb 16, 2013
  33. dasbin

    dasbin

    Joined:
    Jan 14, 2012
    Posts:
    261
    Heh, I just came on here to ask about overriding bone positions!

    I'm not sure if this approach helps my situation though. What I want to do is programatically edit keyframes at runtime. So a script will edit the position of a bone at a particular keyframe at runtime, and from then on, whenever that animation clip plays, the bone will move to that position when it hits that edited keyframe. Is this possible? If not, what kind of workaround would you suggest for achieving a similar result?

    Essentially, I'm making some "switches" that generate their on/off bone transform positions based on some particular criteria supplied at runtime (or, in some cases, at random).
    Those positions are just single-keyframe animation clips (that is the keyframe I want to edit) that I blend between as needed (as the switch turns on or off, it just blends to a different single-keyframe clip). But the positions in those frames need to be edited at runtime.
     
    Last edited: Feb 18, 2013
  34. geo123

    geo123

    Joined:
    Nov 20, 2012
    Posts:
    10
    Hi echo,
    I would like to change the shader of BONE animtion using script. However it is found that the shader will restore to original on after played another animation.
    script I use is

    boneAnimation.mRenderer.material.shader= mat1.shader

    Is something wrong set shader in this way?
     
  35. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    Unfortunately, this won't be possible. The keyframes from the editor are used to generate the animation clips that Unity uses in its animation process. The generation of these clips are done at design time (force build, auto-build, etc). Doing this at runtime (and updating) would be costly in terms of memory, and quite slow. Also, a lot of the functions that perform these updates are only available in the Unity editor dll, which is not available at runtime.

    You might try mixing animations on top of other animations. You wouldn't get precise programmatically set values, but you might be able to fake it enough to do what you are aiming for.
     
  36. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    If you could send me your zipped project to support@echo17.com, I can take a look and try to diagnose the issue.
     
  37. geo123

    geo123

    Joined:
    Nov 20, 2012
    Posts:
    10
    Hi Echo,

    Sorry, I cannot release the asset as it is a company project.

    I try to change shader at onstart() / bonanimation.play('xx') also failed to work propertly. I can see the shader had been changed by monitor the inspector property but restore after 0.5 second. Sometimes they even just don't change the shader.

    It only works when I change the shader on the game object inspector property before start the scene play.

     
  38. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    Totally understand, but it will be nearly impossible for me to give you a good answer without seeing everything and how it interacts. Check your animations and make sure you aren't mixing an animation that is resetting your texture to something else. Also, check all your scripts, you may have multiple scripts trying to update the same animation. That's about as much as I can suggest from here...
     
  39. geo123

    geo123

    Joined:
    Nov 20, 2012
    Posts:
    10
    Hi echo,
    Thks your quick reply.

    I had tested with chef animation which provided in your example 'rise of Dough'. It found the same issue. when I change chef instance shader property neither through runtime inspector or script. I can see the instance will reset back to initial shader after a while.


     
  40. Samb88

    Samb88

    Joined:
    Mar 26, 2009
    Posts:
    208
    Hey echo, I hope this is a simple request. Could you add a switch for doublw sided polygons, so every face got a backface? This is needed for advanced post processing shader like depth of field. With double sided faces you can use another shader like the cutout shader. Then the character will also receive and cast shadows!
     
  41. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    I'll add this to my list of items to consider, thanks!
     
  42. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    If you could zip up your modified version "Rise of the Dough", with comments on where you are changing the shader, I'll take a look at that. You can email it to: support@echo17.com
     
  43. geo123

    geo123

    Joined:
    Nov 20, 2012
    Posts:
    10
    Hi Echo,
    I try to modify 'Rise of the Dough' and ultimately found that in order to change shader. Had to use

    boneAnimation.mRenderer.sharedMaterial.shader=mat1.shader . That had solved the issue.
    But I found when back to edit scene , the default shader will changed accordingly. Is it the correct way to set sharedMaterial.shader


    I had used this before
    boneAnimation.mRenderer.material.shader=mat1.shader before which the shader will restore automatically.

    what is the difference between material.shader and sharedMaterial.shader

    Thanks for your support.
     
  44. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    Hmmm... that's interesting. Not really sure what the differences are. SmoothMoves doesn't interact with shaders, so I haven't spent any time learning about them. Just a guess (so don't take it too literally), it might be that sharedMaterial is used across all your objects, whereas material is only used by a single instance of your object.
     
  45. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    I just realized, you might be able to do this already without the extra back-facing polygons. Instead of rotating the character 180 degrees along the y axis, you might try setting the x scale to -1.0f. This way, the normals are still facing the same direction, but the character's x values are mirrored.
     
  46. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    Hey everyone,

    I've started a FAQ post on the official SmoothMoves forum here

    I'll be adding to it as topics come up. Take a look here if you have a question, these are the hot topics that get asked a lot.
     
  47. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,422
    Does the latest Version of SmoothMoves work with Unity 4?
     
  48. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    Yep, it sure does. I compile and publish using 3.5.6 so you aren't forced to update to Unity 4, but it will still work on the latest.
     
  49. hemdanw

    hemdanw

    Joined:
    Nov 5, 2012
    Posts:
    14
    Hi,

    I am trying to use PlayQueued in a state machine, but ran into a variety of issues trying to determine when an animation is done or close to done.

    (1) IsPlaying(animationX) - returns false before an animation has been played, returns true while an animation is playing, BUT also returns true even *after* an animation has completed. I thought maybe this was because animation looping might be on, but even with loop "once" mode, it still returned IsPlaying == true, so the method cannot be used in a polled mode to determine when an animation has completed.

    (2) Next I tried using a user trigger. The trigger indeed gets fired, but only the first time. If I queue the same animation again, the trigger is not fired the 2nd time. I added "AnimationCompleted" user triggers to all my clips, and indeed every animation will only trigger once, so I cannot determine when the next same animation has completed.

    (3) Ultimately, I'd like to change states when the last queued animation is about to complete. It would have been very helpful if there was a method to get the number of remaining queued animation. Then I would be able to do something like this:
    if (myBoneAnimation.NumQueuedAnimations() < 1) { changeState(nextState); }

    (4) Using (3) in conjunction with something like myBoneAnimation.PercentComplete() > 0.75f would be great... I didn't see anything to provide this data on the BoneAnimation class.

    If these methods could be made available we'd be very grateful.

    Appreciated,
    hemdanw
     
  50. echo17

    echo17

    Joined:
    Nov 24, 2011
    Posts:
    1,252
    I'm working on a revamping of the event system in SmoothMoves that will use Unity's built-in animation event. This should clear up this problem. The new code is in alpha testing so it will be a little while before it is ready.

    This should also be taken care of by the new animation event system

    Unfortunately, Unity does not keep track of the animation queue, so I don't have access to this information in SmoothMoves. SmoothMoves uses Unity's skinned mesh animation process to handle all the playing, fading, blending, and queuing, so if it isn't available there, I won't be able to pass it back to you.

    Same as the above answer.