Playing Animation Local to Position in Unity

Hey all, I’m just now getting started with importing animations into Unity, and I have what will probably end up being a really basic question.

So I have a simple character, non-deforming. I’m animating him to bob up and down very slowly along the positive y axis in Maya, so the animation goes from like 0 to 1 on y and then back down again. Now in Unity, this animation comes in fine. However, my character is positioned away from the origin in Unity, and whenever I hit the play button to preview the animation, the character snaps back to the origin (since that was where the y translation was keyed in Maya).

My question is this: is there any way to say “Hey Unity, I want to play this animation local to where the character is currently positioned”? In other words, if the character is positioned off-origin in the Unity game-world, is there a way to have him animate in place wherever he is positioned? Or maybe I need to go about the animations in Maya a different way?

Thoughts? Thanks! :smile:

1 Like

You just need to place the animated object inside an empty parent object. The animation will then be positioned in the parent’s coordinate space, and you can move the parent to reposition the visible object.

11 Likes

doesn’t this seem a bit of a long winded approach? surely just being able to flag an animation as ‘Local’ would suffice and would be a trivial addition to animations? Perhaps in the AnimationState class?

Even if parenting (say you have planets under a Sun parent) you may still want an animation to be absolute/global even though it’s parented!
For whatever reason, you may want the planets to bob up and down locally as they orbit… but then play a global space anim if you select them, forcing an absolute position… just one example!

So letting users decide how the anim transforms are applied could open up more flexibility and do away with redundant busy work! :slight_smile:

2 Likes

Is there still no way to do this, i.e. for a weapon on a player character animation.

Either that or can you script animations instead?

1 Like

It much easier to say that than to do it and keep proper backwards compatibility. It just doesn’t fit current Unity design. The way it works: Animatoin component just overrides values in Transform - that how you get “world space” animation. What you’re suggesting is that Animation should add values to Transform (that how you would get "local space animation), which means Animation component would have to store the original values somewhere and then if you want to change the “world space” on which animation is played you would have to change it not on Transform, but somewhere else where Animation component stored it, so it just becomes a mess. Does it make sense?

So just parent your game object to empty game object, or add another root in your 3D file and do not animate it (then animation should not affect it).

3 Likes

Yes, this seems logical, just wish it was documented in the user manual !

I also need to move animations around and have them keep their local movement. But when I parent 6 animated objects to an empty Transform, as soon as I push “Play” all my animated objects disappear!

If I de-parent them from the empty Transform, they play as normal. What’s going on!?

This is a tricky topic and has taken me a while to figure out, though I did find a solution that may help others. You can use a script to offset an animation by applying the offset during LateUpdate. It won’t work during Update because the transform values will get overwritten by the animation. As pointed out by Paulius, the animation clip simply sets values to the transform. You can add your own values to the transform afterward:

function LateUpdate() {
	transform.localPosition.x += myOffset.x;
	transform.localPosition.y += myOffset.y;
	transform.localPosition.z += myOffset.z;
}

hey walkerfx, in your script, where did you define myOffset?
I’ll give that a shot!

hey Paulius - it makes total sense what you say yet I don’t see the problem, in principle at least, with how you described approaching the issue? What I suggested would still be backward compatible as well - the default setting for the new Local/Absolute enum (or however you implement it) would be what the normal behaviour in previous versions would have been.

I understand of course that in practice modifying a component at the source level isn’t as simple as “just” adding a new enum.

Cheers! :slight_smile:

Hey there, just in case someone is struggling with this as well and finds this topic by googling, I managed to put together a very simple script file (in C#) that makes the animation of the object play locally:

using UnityEngine;

[RequireComponent(typeof(Animation))]
public class LocalAnimation : MonoBehaviour
{
	Vector3 localPos;
	bool wasPlaying;

	void Awake()
	{
		localPos = transform.position;
		wasPlaying = false;
	}

	void LateUpdate()
	{
		if (!animation.isPlaying  !wasPlaying)
			return;

		transform.localPosition += localPos;

		wasPlaying = animation.isPlaying;
	}
}

It’s very brute force but quite simple, all you need to do is to add it to your object that has the animation. It will check if the animation is playing and modify the position of the object accordingly.

2 Likes

What about introducing a new component type (or even subclass of “animation” ) called “LocalAnimation” ( or “AnimationLocal”, or “AnimationAdditive” or something ) ? That surely would keep backward compatibility while give the user some comfort…

If i re-think about it: why not just introduce a boolean property to the Animation component called “additive” or “local” or whatever, which is off by default ?

3 Likes

Just in case someone else runs into what I did, be sure to create your empty game object first. Then drag your model from the Project panel to the new empty game object in the Hierarchy panel.

In my case, having the model already in the hierarchy panel > creating empty game object > moving model inside empty game object > same undesired result with model position jumping around.

Hope this helps.

JMc

1 Like

Thank you oooo lord i was like 3 hours on that and it was just drawing fomr the project apnel and not into the hierarchy and then etc …GOOD BLESS YOU MAN YOU ROCK !

1 Like

I am having the same problem with jumping. I am using the free version of unity 4 but I am following a tutorial that was created with unity 3.5. Of course they don’t talk about the animator controller in the tutorial but I was able to figure that out. So now the animation is running when I hit play.

However I am having issues with the character jumping back to the origin. I have tried creating an empty game object and parenting the character to it. I even tried creating the empty game object then putting the character in it from the project window as suggested by thesfid.

Any ideas why this might not be working for me?

Thanks!

Which tutorial is it ? You are using the legacy system, right ? If you are using Mecanim the parent game object trick will not work and its probably a different problem you are having.

I’m doing the lynda.com unity 3.5 essential training

Yeah I was trying to use the Mecanim Animator component. Which was giving me the “jumping to origin problem” even with parenting to an empty game object.

I then tried the Legacy animation component. The character stayed put, but the animation doesn’t play and I made sure to add the animation clips to the component.

1 Like

With mecanim there is similar trick to parenting but its a lot more tedious and needs to be done in the animation file and Unity. Since Legacy will be completely phased out by Mecanim in the future, it would be nice to be able to have a similar trick with mecanim to have animations played at local position on objects which don’t have bones. Currently to animate a non-rigged object with mecanim and have them play locally they need to be inside two parents to make it work…

Anyways about your problem on legacy, Did it give you any errors or warnings ? Are you using code to animate your character or you just put some animation on the animator component and had Play Automatically checked ?

Make sure you set both the model and animations to Legacy in the Rigs tab : http://docs.unity3d.com/Documentation/Components/FBXImporter-Rig.html

Its usually the most common mistake. The docs are your friend :P.

1 Like

In legacy…

For local animations, your child needs to be named properly inside of the animation, otherwise Unity ignores it. See my post about this…
http://forum.unity3d.com/threads/168050-Help!-I-don-t-get-it-AnimationClip.SetCurve-quot-relativePath-quot

When the animation appears not to play, it’s because the name of what is suppose to be animated does match the object name inside of the animation clip. When it jumps, it’s because it’s a global animation. Meaning the parent is the target of the animation.

Thanks guys! I’ll see if I can get your suggestions to work.

I am stuck at this as well. In 3.5 the parenting trick is not working. I will keep searching around.