Skip to content

7. 动画

悬架动画

如有需要,可以对汽车的 3D 悬架进行动画。 要启用悬架动画,你需要编辑脚本 “car.ini”,设置以下值:

ini
USE_ANIMATED_SUSPENSIONS=1” 启用动画
USE_ANIMATED_SUSPENSIONS=0” 保持动画为默认状态(禁用)

通常这意味着动画是禁用的,但在某些情况下它们始终开启,例如方向盘就是自动动画的。 注意:悬架动画确实存在一些缺点。动画化的悬架沿预先设定的弧线和运动轨迹运动,因此车轮无法在视觉上呈现玩家在游戏内选择的设置值,也就是说,外倾角(Camber)可能会与设置界面中选择的值有明显差异。 我们使用 NULL 层级来为悬架几何体制作动画。下面是一个示例:

  1. 将时间轴帧数设置为(例如)20 帧。
  2. 第 0 帧为较低位置。
  3. 第 10 帧为中立位置。
  4. 第 20 帧为较高位置。 引擎的工作方式如下:它检查悬架在 Y 轴上的位置,并找到合适的帧,使动画与物理悬架的位置相匹配。引擎会对帧进行插值,以生成平滑的运动。Assetto Corsa 会查找以下按如下方式命名的 NULL/DUMMY 对象:

p056_X0

SUSP_LF
SUSP_LR
SUSP_RF
SUSP_RR

NULL/DUMMY 的设计必须使悬架沿 Y 轴移动。正确为悬架制作动画的示例: 注意:在导出 FBX 之前,时间轴的总帧数必须设置为与所创建的动画帧数相同。 示例:如果你制作了 20 帧的动画,就不要在时间轴为 30 帧的情况下导出,这会导致崩溃。请记住,制作了 20 帧动画,就要把时间轴设置为 20 帧。空白帧会导致崩溃,不受支持。 悬架层级 悬架的层级必须与提供的两个 FBX 示例之一完全相同:TEMPLATE_Suspension_EASY.fbx 和 TEMPLATE_Suspension_COMPLEX.fbx 第一个场景包含简单的悬架层级,面向采用简单悬架系统的车辆。第二个则为复杂的悬架层级而准备,例如 60 年代的 Formula 1 赛车,拥有更复杂的摇臂和特殊悬架。这些示例中包含更多的 DUMMY/NULL。 有些名称可以自定义,我们已在 template.fbx 中以适当的方式命名了可自定义的 DUMMY/NULL: “Custom_name##”(其中 # 是数字)。 所有 DUMMY/NULL 都用于动画部件。是否使用它们是可选的。你可以按需创建任意数量的 DUMMY/NULL。 以下 DUMMY/NULL 是必需的:

悬架 Null:

Null说明
SUSP_LF左前
SUSP_LR左后
SUSP_RF右前
SUSP_RR右后

轮毂 Null:

Null说明
HUB_LF左前
HUB_LR左后
HUB_RF右前
HUB_RR右后

车轮 Null:

Null说明
WHEEL_LF是 TYRE_LF(轮胎网格)、RIM_LF(轮辋网格)和 RIM_BLUR_LF(轮辋模糊网格)的父级
WHEEL_LR是 TYRE_LR(轮胎网格)、RIM_LR(轮辋网格)和 RIM_BLUR_LR(轮辋模糊网格)的父级
WHEEL_LR是 TYRE_LR(轮胎网格)、RIM_LR(轮辋网格)和 RIM_BLUR_LR(轮辋模糊网格)的父级
WHEEL_RR是 TYRE_RR(轮胎网格)、RIM_RR(轮辋网格)和 RIM_BLUR_RR(轮辋模糊网格)的父级

在某些车辆上,传动轴可能是可见的。有一个约定名称可以自动为这些对象制作动画。 传动 DUMMY/NULL 名称:

Null说明
TRANSMISSION_L_1用于左传动轴
TRANSMISSION_R_1用于右传动轴

如果还有更多需要动画的传动部件,你可以使用连续编号。例如: TRANSMISSION_L_2、TRANSMISSION_L_3 等等。TRANSMISSION_R_2 等依此类推。 引擎会识别前缀 “TRANSMISSION_L_” 并在其后查找连续编号。可以动画的传动部件数量没有硬编码的上限。 传动 null 绕 X 轴旋转,并且需要

p058_X1

按照下图所示的方向取向: 该节点用于根据悬架动画沿 Y 轴为关节制作动画,而引擎会根据车轮自动绕 X 轴旋转传动部件。避免在 Z 轴上制作动画,因为该轴未被使用。 注意:为了获得正确的旋转方向,传动 null 的 Z 轴必须始终指向前方。 引擎还会识别用于每个车轮轮毂的另外 4 个节点。这些节点的作用是让轮毂能够根据车轮的外倾角进行旋转。

HUB_LF
HUB_LR
HUB_RF
HUB_RR

p058_X0

在上图的示例中,轮毂是转向臂的父级。 这样,你就可以为轮毂或悬架的上下运动制作动画,并在动画过程中根据实际物理悬架布局的需要改变轮毂的外倾角。 在 TEMPLATE_Suspension_COMPLEX.fbx 中,你可以找到正确层级的示例。 注意:SUSP_ 节点的位置必须始终与 Wheel_ 节点一致。AC 引擎通过检查 SUSP_ 节点来确定悬架在 3D 空间中的位置。车轮包围盒在 SUSP_ 节点与 Wheel_ 节点之间识别。这两个位置必须相同。 同样,FBX 文件 TEMPLATE_Suspension_COMPLEX.fbx 是一个完美的示例。 转向臂与方向约束 我们可以为许多不同的部件制作动画,只需将动画导入编辑器,再从那里导出到游戏即可,但 STEER 臂不能制作动画。它的位置会根据 HUB 的旋转在 3D 空间中变化。 为了将转向臂的运动约束到 HUB 的位置和旋转,必须使用前缀为 “DIR_customName” 的约定名称。它指示该网格负 X 轴的方向,名为 “customName” 的 null 会把 X 轴指向正确的方向。 示例:名为 “SteerArm_L” 的 null 会将其负 X 轴指向名为 “DIR_SteerArm_L” 的 null。 请注意动画网格所链接的 null 的旋转。在下图中,右侧的 Null 指向具有正 Z 轴,左侧的 Null 指向具有负 Z 轴。这样,-X 轴就可以指向车辆中心或网格所需的任何其他方向。 在 TEMPLATE_Suspension_COMPLEX.fbx 文件中,你可以找到合适的层级示例。

p059_X0

注意:如果有更多需要约束到 HUB 的对象,只需给它们起不同的名称,你就可以创建更多的约束。不过,从优化角度看,始终建议使用尽可能少的约束。 你可以在以下向量上为自定义 null 制作动画:旋转 - 位移 - 缩放。 在 TEMPLATE_Suspension_COMPLEX.fbx 示例文件中,你可以看到悬架弹簧沿 Y 轴缩放(SCALE Y)的动画。 注意:永远不要为网格制作动画,始终只对 NULL 制作动画!采用这种方式,你可以随时更改和更新网格,而无需重新导出动画。对任何需要动画的 NULL 都使用同样的技术来创建动画,例如车门、变速箱换挡杆或任何其他部件。

完整约束动画设置

如果你不想手动为悬架制作动画,可以创建完整的约束设置。 你可以利用 DIRECTION CONSTRAINT(方向约束)的逻辑,强制悬架自动运作,而无需为其制作动画。 这类悬架设置的一个示例可以在 SDK 附带的 EXAMPLE FBX 中找到:

文件说明
Costraint_suspension_Only.fbx用于通用 FBX 2014 版本
Costraint_suspension_Only_XSI_2014.scn用于 XSI 2014 版本
Costraint_suspension_Only_MAX_2013.scn用于 3ds MAX 2013 版本

动画导出

在场景中为 NULL/DUMMY 制作好动画后,你需要使用 AC 编辑器将动画导出为 AC 专用的剪辑格式,称为 name.ksanim。

p060_X0

必须遵循以下几条规则:

  1. 生成剪辑只需要为 null 制作动画,不需要为网格本身制作动画。你也可以导出网格,但编辑器只会导出带有动画关键帧的对象/null。如前所述,只对 NULL/DUMMY 制作动画是一种好的做法,这样你就可以独立于实际 3D 网格来更改动画。
  2. 导出带动画的 null 时,还必须导出它上方的层级树,因为在编辑器中,对象的名称由它在层级树中的位置决定。
  3. 始终使用 FBX 格式导出,因为它是唯一支持动画的格式。不要使用任何其他格式。 在上图所示的示例中,我们有两个以网格为子级的 null 层级。我们为换挡拨片和转向拨片制作了动画,需要将其导出。 我们不能只导出 SHIFT PADDLE_L 这个 null,而必须导出从 COCKPIT_HR 开始的整个层级,包括 STEER_HR 和 SHIFT paddle_L。 这样,编辑器就能根据 SHIFT PADDLE_L 在层级中的位置确定相应的 null。

动画优化

  1. 游戏会对帧进行插值。你不需要导出包含所有关键帧的动画。 对于车门、换挡杆等简单动画,你可以只导出重要的帧。 对于简单的车门动画,“关闭”和“打开”两帧就足够了,其余的由游戏插值完成。当车门更复杂、带有液压挺杆或垂直开启方式(比如 Mclaren P1 的车门)时,你可以添加更多帧,以更精确的方式为车门制作动画。但请始终记住:使用的帧越少,结果越优化,因为引擎会在关键帧之间平滑插值。
  2. 相同的帧会被优化。如果你创建了多个相同的帧,且它们之间的变化为 0,这些帧将被优化。 示例:换挡杆在完整动画的第 15 帧才开始动作,因为在此之前的帧里它固定在原位,等待车手的手先够到它。此时必须在第 0 帧放置一个关键帧,在第 14 帧再放置一个,两者都处于静止位置。换挡杆的动画从第 15 帧开始。在 0 到 14 帧之间不需要放置更多关键帧。

剪辑与命名约定

有两种预编程的播放方式:

  1. 乒乓(Ping-pong):动画播放到结尾后,再从尾到头反向播放。
  2. 循环(Loop):首帧与末帧相匹配,动画重新开始循环。 特定的命名约定在游戏内拥有预编程的播放方式,因此引擎知道播放方式应该是 LOOP 还是 PING-PONG。

车手动画剪辑名称:

剪辑说明
steer.ksanim循环播放,用于车手双臂在方向盘上的转动
shift.ksanim乒乓播放,用于车手手臂伸向换挡杆的动画(我们通常做一个简单的动画,参见 fbx 示例)
shift_dw.ksanim乒乓播放,用于操作拨片降挡(通常为左侧)的手指动画
shift_up.ksanim乒乓播放,用于操作拨片升挡(通常为右侧)的手指动画

车辆动画剪辑名称

剪辑说明
car_shift.ksanim乒乓播放,用于车辆换挡杆的动画

重要:该剪辑的帧数必须与 shift.ksanim 相同,以使手臂动作与换挡动画相匹配。如果在车手动画中换挡动作从第 10 帧开始,那么换挡杆也必须在完全相同的帧开始移动!

剪辑说明
car_susp_LF.ksanim由引擎控制,用于左前悬架的动画
car_susp_LR.ksanim由引擎控制,用于左后悬架的动画
car_susp_RF.ksanim由引擎控制,用于右前悬架的动画
car_susp_RR.ksanim由引擎控制,用于右后悬架的动画
car_door_R.ksanim乒乓播放,用于打开右侧车门的动画(关闭动画应为开门动画的反向播放。不要为关闭过程制作动画!)
car_door_L.ksanim乒乓播放,用于打开右侧车门的动画(关闭动画应为开门动画的反向播放。不要为关闭过程制作动画!)
car_wiper.ksanim循环播放,用于雨刮的动画(这里你必须为完整的往返行程制作动画)
lights.ksanim乒乓播放,用于动态车灯的动画(例如 Ferrari F40。只为开启过程制作动画)。
car_shift_up.ksanim乒乓播放,用于换挡拨片升挡的动画
car_shift_dw.ksanim乒乓播放,用于换挡拨片降挡的动画

注意:你可以创建所需的全部动画,也可以使用新名称,然后通过 .ini 脚本来调用它们(例如主动 DRS、尾翼等)。上面列出的名称会被自动识别并由游戏引擎管理。 例如:car_wing.ksnim 是一个自定义名称的动画。在某些车辆上,我们创建了名为 wing_rear.ksanim 或 wing_side.ksanim 的动画。这些可选动画通过 .ini 脚本管理。

剪辑说明
car_wing.ksanim乒乓播放,用于动态尾翼的动画(只为展开过程制作动画)

从编辑器导出动画

按照以下步骤导出动画:

  • 在编辑器中打开车辆 FBX。
  • 通过 File 标签页下的 Open FBX Animation 选项打开动画(见下文):

p062_X0

  • 找到并加载你之前导出到 “animations” 文件夹的 FBX 动画。 动画加载后,它会自动在 FBX 文件所在的同一文件夹中保存一个 clip_name.ksanim 文件,无需手动导出动画剪辑。
  • 选择编辑器界面底部的 Animation 标签页。拖动动画滑块,你应该能看到动画播放。

p063_X0

你可以在场景中加载多个动画。每次加载动画时,都会以源 FBX 的名称保存一个 .ksanim 文件。 如果你的 fbx 命名不正确,就必须重命名剪辑以符合我们的命名约定,例如车手手臂的动画应命名为 steer.ksanim 等。

检查车辆动画

当所有悬架剪辑都导出到正确的动画文件夹(参见“项目结构”一节)后,你就可以在编辑器中加载 car.fbx,检查动画是否正常工作。 只有在创建好动画剪辑并将其加载到编辑器之后,你才能进行这项操作。 注意:对于外部部件(悬架、尾翼、翻跳大灯),LOD B 必须包含与 LOD A 相同的 null 层级和动画 null 名称,但对于 HR 内饰(拨片和换挡机构)中的动画以及 Cockpit_HR null 下的车门 null,则无需如此。 打开你的 car_name.fbx 车辆加载完成后,你可以加载想要测试的悬架剪辑。 在名为 “Car Animations” 的标签页中,你会找到一些滑块。它们用于帮助你测试弹簧的动画、摇臂的约束以及车轮的旋转。

p063_X1

p064_X0

这些滑块让你能够在编辑器中逐帧检查悬架并发现任何问题。这里你可以看到一个示例:移动滑块即可检查轮毂的行为。

动画导出通用指南

导出动画(尤其是车门动画剪辑)时,有一些重要事项需要牢记。导出车门剪辑时,应具备以下层级: 复杂的车门动画

p064_X2

p064_X1

可能包含数量更多的 null,请确保命名约定保持一致,并(按每一侧)导出每个带动画的 null。更多信息请参见“动画导出”一节。 请注意,车门内饰部件的网格和 null 位于 COCKPIT_HR 这个 null 之下。这是因为座舱会从高分辨率切换到低分辨率,LR 车门将被隐藏。因此,我们复制了带动画的车门动画 null,并将它们放在 COCKPIT_HR 之外。 导出时,记得包含所有座舱车门 null(左图)。 注意:导出换挡拨片的动画(car_shift_dw 和 car_shift_up)时,务必确保同时导出父级 null。如果拨片位于方向盘上,那么每个动画都必须导出其中一个拨片 null(SHIFT_R 或 SHIFT_L)、方向盘 null(STEER_HR)以及 HR 座舱 null(COCKPIT_HR)。 为雨刮制作动画时,可以根据雨刮的复杂程度使用若干个 null。通常,带有 2 个、最多 3 个轴心点(即 2 或 3 个 dummy)的雨刮就足够了。 雨刮 null 必须位于场景的根节点,并且必须存在于 LOD A 至 LOD C。