I decided to try exporting a Blender model in an FBX with animations to Unity. There are two animations, open and close for the top door of this model. Here's the thing - it seems my model likes to jump into the origin of BOTH animations when the model started, ie. if I import the model and the door is open, and I decide to trigger to CLOSE it, it will close properly - but then, when I try to OPEN it, it decides it needs to stay at the SAME origin as the closing door animation first, THEN it opens - basically causing the door to move too far OUTSIDE of the model.
I've also made a point to try leaning on ONE animation in the Mecanim animator control - but it seems while it gets back to the correct place for the door when moving in the opposite direction, it doesn't do it at the same speed, but does so erratically. Finally, when I try to have one door animation transition to the SAME door animation with the opposite speed (ie. door close to door close, one with speed of 1 and one with -1) it still jumps erratically.
Here's the last Mecanim animator setup I attempted:
This was the approaching of trying to use the same animation in the other state, but negative speed instead of positive. It doesn't work like you would expect.
I'm using state triggers to transition between these states in the code below:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;
public class TriggerAnimation : MonoBehaviour {
public Transform cockPit;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetKeyDown("t"))
{
//AnimationPlayableUtilities.PlayClip("CockPit_ExtDoor|Open");
Debug.Log("I'm being pressed");
//GetComponent<Animator>().SetTrigger("ExtDoorOpen");
GetComponent<Animator>().SetTrigger("IntDoorOpen");
//GetComponent<Animator>().SetTrigger("CockPit_Door|Open");
}
if (Input.GetKeyDown("u"))
{
//PlayableGraph graph = new PlayableGraph();
//AnimationPlayableUtilities.PlayAnimatorController(GetComponent<Animator>(), GetComponent<RuntimeAnimatorController>(), out graph);
Debug.Log("I'm being pressed");
//GetComponent<Animator>().SetTrigger("ExtDoorClose");
GetComponent<Animator>().SetTrigger("IntDoorClose");
//GetComponent<Animator>().SetTrigger("CockPit_Door|Close");
}
if (Input.GetKeyDown("x"))
{
GetComponent<Animation>().Play("CockPit_IntDoor|Open");
}
if (Input.GetKeyDown("z"))
{
GetComponent<Animation>().Play("CockPit_IntDoor|Close");
}
}
}
Can someone let me know if there's a better way to approach this and how? I've tried jumping between several articles on this, including a demo tutorial on Mecanim for Unity on their website - no dice...
I've had many difficulties with bringing animations from blender into unity. There are a lot of pitfalls. Here are a couple things i would try. let me know if any of these work for you.
When animating a model in blender it often happens that the origin of your model has accidentally been moved or is not in the exact same place between your two animations and when that gets imported into unity it has a way of messing with your animations. So just double check between your animations and make sure that the origin has not shifted between the two animations
The docs for apply root motion here
basically what it does if enabled is for any movement that takes place in your animation it adds whatever movement transpired in the animation to its current position Therefore if the root object of the door moved left by 2units when it opens and your are applying root motion the object would then be 2 units left of where you would expect. And it would just continue to stack getting further and further left.
I am assuming that you do not want to actually have the position of the door move but instead just have the animation make it appear as if the door is moving. If so in that case Assuming that your object is setup right. Which in my mind if it was a sliding door it would have an object tree like this RootObject>Frame>Door. With that being the case the only object that should have any animation keys on it should be the door object. the other parent objects should be stationary.
These are just some useful troubleshooting tips i found helpful in the past.
I don't know how your animation clips look like and how your transitions look like but here are a few tips:
if (Input.GetKeyDown("x"))
{
GetComponent<Animation>().Play("CockPit_IntDoor|Open");
}
if (Input.GetKeyDown("z"))
{
GetComponent<Animation>().Play("CockPit_IntDoor|Close");
}
Animator.Play
directly "jumps" into the target state without any transition. But the animation is restarted everytime you hit the key.
Triggers
get stacked so if you press eg the open button mutliple times and than press the close button, you will make both (or even multiple) transitions between the two states since a Trigger
is only reset, if it is used (or reset actively in a script using Animator.ResetTrigger
).
And another issue I see is that currently you use decoupled if
statements ... so it is theoretically possible to press all 4 keys at the same time what might leed to some issues (The Play
call would directly jump to the target state but the triggers from the before Settrigger
calls would be still there and stacked so it is possible that your animator makes various transitions from the next frame on.) You rather shouls use if-else
statements to allow only processing one key press at a time.
For a simple door with only two states and no complex animations between those I would suggest a different approach:
Dont export animations from Blender only the model
For a rotating door make sure the pivot is on the axis you ant to rotate around
In the animator have only two states eg Opened
| Closed
Instead of Triggers use a bool eg IsOpen
Create your "animations" in the way that both have only exactly 1
keyframe and disable Loop Time
in the inspector. Unity interpolates between the two animations automatically so if there is only one keyframe per animation all the interpolation between the values (positions, colors, rotations etc) is handled automatically by Unity itself.
Make your transitions the following way
ExitTime
-> 1
We won't use the exit time actually but this fixes a little bug throwing a warning
Difference in effective length between states is too big. Transition preview will be disabled. UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
if you let it on 0
HasExittime
-> false
FixedDuration
-> true
(we want to configure stuff in seconds) TransitionDuration(s)
-> Here you configure now how long you want the transition to take (it also can be different fo opening and closing) TransitionOffset
-> 0
(the animation has only 1 keyframe so we don't want to start it in another frame)
and finally your two conditions
IsOpen == false
IsOpen == true
Than later in the code you instead would use
// Store the component frerence instead of getting it everytime again
private Animator _animator;
private void Awake()
{
_animator = GetComponent<Animator>();
}
private void Update()
{
if (Input.GetKeyDown("t"))
{
Debug.Log("t is being pressed");
_animator.SetBool("IsOpen", true);
}
// use if-else in order to process only one of the buttons at a time
else if (Input.GetKeyDown("u"))
{
Debug.Log("u is being pressed");
_animator.SetBool("IsOpen", false);
}
// you still can keep those for jumping to a state directly without the transition
else if (Input.GetKeyDown("x"))
{
_animator.Play("Opened");
}
else if (Input.GetKeyDown("z"))
{
_animator.Play("Closed");
}
}
Now using a Bool value instead of Triggers you don't have to care about stacked calls. I hope this 1 keyframe animations approach fits your requirements.
If you require having multiple "steps" in your opnening and closing process eg because of having some complex unlock animations before the door actually moves, I would recommend to
HasExitTime = true
and ExitTime = 1
IsOpen = true
or to "more closed" on IsOpen = false
For better understanding here is an example how a more complex setup might look like only using such 1 keyframe animations
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.