Blender 到 Unity 动画 - 跳帧
Posted
技术标签:
【中文标题】Blender 到 Unity 动画 - 跳帧【英文标题】:Blender to Unity Animation - Jumps In Frames 【发布时间】:2019-05-15 07:02:09 【问题描述】:我决定尝试将带有动画的 FBX 中的 Blender 模型导出到 Unity。该模型的顶门有两个动画,打开和关闭。事情是这样的——我的模型似乎喜欢在模型开始时跳入两个动画的起源,即。如果我导入模型并且门是打开的,并且我决定触发关闭它,它将正确关闭 - 但是,当我尝试打开它时,它决定它需要保持与关闭门动画相同的原点首先,然后它打开 - 基本上导致门在模型之外移动得太远。
我还特意尝试在 Mecanim 动画器控件中依靠 ONE 动画 - 但它似乎在向相反方向移动时回到门的正确位置时,它并没有这样做速度相同,但速度不规律。最后,当我尝试将一个门动画过渡到具有相反速度的 SAME 门动画时(即门接近关门,一个速度为 1,一个速度为 -1),它仍然会不规律地跳跃。
这是我尝试的最后一个 Mecanim 动画师设置:
这是尝试在其他状态下使用相同动画的方法,但速度为负速度而不是正速度。它不像你想象的那样工作。
我在下面的代码中使用状态触发器在这些状态之间进行转换:
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");
谁能告诉我是否有更好的方法来解决这个问题以及如何处理?我试过在这方面的几篇文章之间跳转,包括他们网站上关于 Mecanim for Unity 的演示教程 - 没有骰子......
【问题讨论】:
【参考方案1】:我不知道您的动画剪辑和过渡效果如何,但这里有一些提示:
if (Input.GetKeyDown("x"))
GetComponent<Animation>().Play("CockPit_IntDoor|Open");
if (Input.GetKeyDown("z"))
GetComponent<Animation>().Play("CockPit_IntDoor|Close");
Animator.Play
直接“跳转”到目标状态,没有任何转换。但是每次按键都会重新开始动画。
Triggers
被堆叠所以如果你按下例如打开按钮多次,然后按下关闭按钮,您将在两种状态之间进行两次(甚至多次)转换,因为 Trigger
仅在使用时被重置(或在脚本中使用 Animator.ResetTrigger
主动重置) )。
我看到的另一个问题是,目前您使用解耦的 if
语句......所以理论上可以同时按下所有 4 个键,这可能会导致一些问题(Play
调用会直接跳转到目标状态,但之前 Settrigger
调用的触发器仍然存在并堆叠,因此您的动画师可能会从下一帧开始进行各种转换。)您宁愿使用 if-else
语句只允许处理一个一次按键。
对于只有两种状态且在它们之间没有复杂动画的简单门,我建议采用不同的方法:
不要只从 Blender 中导出动画模型
对于旋转门,请确保枢轴位于您要旋转的轴上
在动画师中只有两种状态,例如Opened
| Closed
使用布尔值代替触发器,例如IsOpen
创建您的“动画”,使两者都只有 1
关键帧并在检查器中禁用 Loop Time
。 Unity 会自动在两个动画之间进行插值,因此如果每个动画只有一个关键帧,则所有值(位置、颜色、旋转等)之间的插值都由 Unity 自己自动处理。
按照以下方式进行转换
ExitTime
-> 1
我们实际上不会使用退出时间,但这修复了一个引发警告的小错误
状态之间的有效长度差异太大。过渡预览将被禁用。 UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
如果你让它0
HasExittime
-> false
这意味着不要等到动画完成或在某个帧完成过渡,而是立即进行(只有关键帧的动画自动默认长度为 1 秒)
FixedDuration
-> true
(我们想在几秒钟内完成配置)
TransitionDuration(s)
-> 您现在可以在此处配置您希望转换需要多长时间(打开和关闭也可以不同)
TransitionOffset
-> 0
(动画只有一个关键帧,所以我们不想在另一帧开始)
最后是你的两个条件
打开 -> 关闭:条件:IsOpen == false
关闭 -> 打开:条件:IsOpen == true
在后面的代码中你会使用
// 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");
现在使用 Bool 值而不是触发器,您不必关心堆栈调用。我希望这 1 个关键帧动画方法符合您的要求。
如果您需要在打开和关闭过程中有多个“步骤”,例如因为在门实际移动之前有一些复杂的解锁动画,我建议
为每一步使用一个状态 用HasExitTime = true
和ExitTime = 1
链接所有一个方向
使用前面提到的设置在这些状态之间进行插值
最后在每个“步骤对”之间有两个过渡条件,因此每个动画要么在IsOpen = true
上过渡到“更开放”,要么在IsOpen = false
上过渡到“更封闭”
为了更好地理解这里是一个示例,更复杂的设置可能看起来像只使用这样的 1 个关键帧动画
【讨论】:
谢谢。你在我过去的帖子中也很有帮助,但这是非常有用的信息,即使我必须承认我没有完成你建议的一切。老实说,这样做的目的更多是让我练习创建一个简单的驾驶舱,并练习从 Blender 本身导入它的门动画——但我想你用 Unity 代替了一个很好的观点。尽管如此,我还是特别记下了 1.) 您关闭“退出时间”参数的建议和 2.) 您更改过渡持续时间的建议。这些我可以完美应用!【参考方案2】:将搅拌机中的动画整合到统一中时遇到了很多困难。有很多陷阱。这是我会尝试的几件事。让我知道这些是否对您有用。
在输入Docs on how to adjust origins here 时,确保您的原点在搅拌机中的相同位置 在搅拌机中为模型制作动画时,经常会发生模型的起源 在两个动画之间被意外移动或不在完全相同的位置 当它被导入统一时,它就会弄乱你的动画。 因此,只需仔细检查您的动画,并确保原点没有 在两个动画之间切换 确保您没有在 unity animator 中应用 RootMotion应用根运动的文档here
基本上,如果启用它的作用是针对发生在您的 动画它将动画中发生的任何运动添加到其当前位置 因此,如果门的根对象在打开时向左移动了 2 个单位并且您 应用根运动,对象将在您想要的位置左侧 2 个单位 预计。而且它会继续堆叠,越来越左。 确保删除动画剪辑中的所有 transform.position 键。 我假设您不想实际移动门的位置,但是 而是让动画让它看起来好像门在移动。如果是这样的话 假设您的对象设置正确。在我看来,如果它是一扇推拉门,它会 有一个像这样的对象树 RootObject>Frame>Door。既然如此,唯一的 应该有任何动画键的对象应该是门对象。另一位家长 物体应该是静止的。 小建议。我会使用布尔而不是触发器。这样就更容易跟踪门的状态。 (即,您的动画基于“isClosed”布尔值)这些只是我在过去发现的一些有用的故障排除技巧。
【讨论】:
我想你提出的建议一样好 - 我特别要记住布尔值的建议。您能否在答案的要点 1、2 和 3 中详细说明您的意思? 希望编辑有所帮助。如果您有任何其他问题,请告诉我。 您好,是的,这非常有帮助。解决提示 #1 的最佳方法是什么?我对这个场景还是很陌生,所以我非常感谢这一切 我在第一点添加了一个有用的链接,用于调整搅拌机的原点。祝你好运以上是关于Blender 到 Unity 动画 - 跳帧的主要内容,如果未能解决你的问题,请参考以下文章