• 论坛

导航

  • 主页
  • 样式指南
  • 入门
    • 概述
    • Mod的结构
    • Forge更新检查器
    • 依赖管理
    • 调试分析器
  • 概念
    • Sides
    • 资源
    • 注册表
    • Jar签名
    • 国际化和本地化
  • 方块
    • 概述
    • 介绍方块状态
    • 方块互动
  • 动画 API
    • 概述
    • 骨骼
    • 动画状态机
      • 概念
      • 编程API
      • 文件格式
    • 使用API
  • TileEntity
    • 概述
    • 特殊渲染器
  • 物品
    • 主页
    • 战利品表
  • 模型
    • 模型概述
    • 模型文件
    • 方块状态
      • 方块状态JSON概述
      • Forge方块状态JSON
    • 绑定模型到方块和物品
    • 彩色纹理
    • 物品属性概述
    • 高级模型(未翻译)
      • 高级模型介绍
      • IModel
      • IModelState and IModelPart
      • IBakedModel
      • Extended Blockstates
      • Perspective
      • ItemOverrideList
      • ICustomModelLoader
  • 渲染
    • TileEntityItemStackRenderer
  • 事件
    • 基本用法
  • 网络
    • 主页
    • 概述
    • SimpleImpl
    • 实体
  • 数据储存
    • 能力系统
    • World Saved Data
    • 拓展实体属性
    • Config注解
  • 工具
    • 合成
    • 矿物词典
    • 权限API
  • 效果
    • 音效
  • 惯例
    • 版本命名
    • 文件位置
    • 加载阶段
  • 参与Forge开发
    • 入门
    • PR指南

动画状态机文件

动画状态机 (ASM) 文件是动画API的核心. 它们定义了动画的执行方式以及如何使用骨架文件中定义的剪辑。

概念

ASM包含_参数_,剪辑,状态_和_转换(parameters, clips, states 和transitions)。

状态(States )

动画_状态_ 机可以在许多不同的_状态_中。 您可以在状态部分中定义哪些状态。

转换(Transitions)

转换定义允许哪些状态进入其他状态,例如允许“关闭”状态进入“打开”状态。

提示

但是,转换 不会 定义状态之间播放的动画。 如果要这样做,则必须创建一个播放动画的附加状态,然后使用事件转到下一个状态。

参数(Parameters)

提示

参数在代码中称为TimeValues,因此这是SomethingValue的命名约定。

所有参数都采用输入,通常以秒为单位的当前游戏时间作为浮点数(考虑特定tick)并输出另一个时间。 此输出用作剪辑的输入,告诉它当前动画的进展。

每个参数都可以在ASM中定义,也可以在代码中加载ASM时定义。 加载时参数通常是VariableValue类型,它返回一个代码内可变的值,忽略其输入。 其他类型允许你对输入进行数学运算(SimpleExprValue),返回一个常量(ConstValue),引用其他参数(ParameterValue),返回 输入unmodified(IdentityValue)并执行两个参数的组合(CompositionValue)。

剪辑(Clips)

提示

剪辑可以是ASM剪辑,在ASM中定义的剪辑,也可以是电枢剪辑,在骨架文件中定义的剪辑。 对于本页的其余部分,除非另有说明,否则“剪辑”将引用ASM剪辑。

剪辑接收输入,通常是时间,并使用它对模型执行某些操作。 不同类型的剪辑做不同的事情,最简单的是动画电影剪辑(ModelClip)。 您还可以覆盖另一个ASM剪辑的输入(TimeClip)。如果输入为正,则在动画另一个剪辑时触发事件(TriggerClip)。在两个剪辑之间平滑混合(SlerpClip)。 在ASM参考另一个剪辑(ClipReference)或什么也不做(IdentityClip)。

事件(Events)

Various things can trigger events in the ASM. Events in the ASM are represented using only text. Some events are special, with text that is formatted like this: !event_type:event_value. Right now there is only one kind of event_type, namely transition. This tries to transition to whatever state is defined in the event_value. Anything else is a normal event and can be used from the pastEvents callback, but more information about that is on the implementing page.

各种东西可以触发ASM中的事件。 ASM中的事件仅使用文本表示。 有些事件很特殊,文本格式如下:!event_type:event_value。 现在只有一种event_type,即transition。 这会尝试转换为event_value中定义的任何状态。 其他任何东西都是正常事件,可以从pastEvents回调中使用,但有关它的更多信息在[使用API][implementation]页面上。

编程API

警告

ASM代码API只能用于 客户端 。 在代码中存储ASM时,请使用一端不可知的“IAnimationStateMachine”接口。

可以通过调用ModelLoaderRegistry.loadASM来加载ASM。 它需要两个参数,第一个是ResourceLocation表示 存储ASM的位置,以及第二个加载时定义参数的ImmutableMap。

一个例子:

@Nullable
private final IAnimationStateMachine asm;
private final VariableValue cycle = new VariableValue(4);

public Spin() {
     asm = proxy.loadASM(new ResourceLocation(MODID, "asms/block/rotatest.json"), ImmutableMap.of("cycle_length", cycle));
}

在这里,使用一个名为cycle_length的额外参数加载ASM(用端代理SidedProxy以避免在服务器上崩溃)。 这个参数的类型是VariableValue,所以我们可以从我们的代码中设置它。

使用ASM实例,您可以使用.currentState()获取当前状态,并使用.transition(nextState)转换到另一个状态。

VariableValue参数可以通过调用.setValue来设置它们的值,但是你不能读回这个值。 无需通知ASM此更改,它会自动更改。

文件格式

ASM存储在json文件中。 位置无关紧要,但它们通常放在asms文件夹中。

首先是一个例子:

{
  "parameters": {
    "anim_cycle": ["/", "#cycle_length"]
  },
  "clips": {
    "default": ["apply", "forgedebugmodelanimation:block/rotatest@default", "#anim_cycle" ]
  },
  "states": [
    "default"
  ],
  "transitions": {},
  "start_state": "default"
}

如上所述,文件具有参数,剪辑,状态和转换,以及ASM的起始状态。

所有这些标签都是必需的,即使它们是空的。

参数(Parameters)

{
    "name": <parameter_definition>
}

<parameter_definition>不同类型的参数有不同的格式,简单的参数是:

  • IdentityValue:字符串#identity,
  • ParameterValue: 要引用的参数,前缀为#,例如#my_awesome_parameter
  • ConstValue: 一个数字用作返回的常量

数学表达式 (SimpleExprValue)

格式: [ regex("[+\\-*/mMrRfF]+"), <parameter_definition>, ... ]

示例:
[ "+", 4 ]
[ "/+", 5, 1]
[ "++", 2, "#other" ]
[ "++", "#other", [ "compose", "#cycle", 3] ]
说明

SimpleExprValue获取其输入并对其应用操作。 第一个参数是要应用的操作序列,其余参数表示这些操作的操作数。每个操作的输入是整个参数的输入(对于第一个操作)或前一个操作的结果。

操作(区分大小写):
操作 含义
+ 输出 = 输入 + 参数
- 输出 = 输入 - 参数
* 输出 = 输入 * 参数
/ 输出 = 输入 / 参数
m 输出 = min(输入, 参数)
M 输出 = max(输入, 参数)
r 输出 = floor(输入 / 参数) * 参数 (向下取整)
R 输出 = ceil(输入 / 参数) * 参数 (向上取整)
f 输出 = 输入 - floor(输入 / 参数) * 参数 (取余)
F 输出 = ceil(输入 / 参数) * 参数 - 输入 (参数减余数)
示例说明:
  • 输入 + 4
  • (输入 / 5) + 1
  • 输入 + 2 +参数 other的值
  • 输入 + 参数other 的值+ 参数 cycle的值 赋值为 3

功能组件 (CompositionValue)

格式: [ "compose", <parameter_definition>, <parameter_definition> ]

示例:
[ "compose", "#cycle", 3]
[ "compose", "#test", "#other"]
[ "compose", [ "+", 3], "#other"]
[ "compose", [ "compose", "#other2", "#other3"], "#other"]
说明

CompositionValue将两个 参数定义 作为输入,并执行value1(value2(input))。 换句话说,它连接两个输入,用给定的输入调用第二个函数,用第二个输出调用第一个函数。

示例说明:
  • cycle(3)
  • test(other(输入))
  • 3 + other(输入)
  • other2(other3(other(输入))) 因为 value1 = other2(other3(输入)) ,value2 = other(输入)

剪辑(Clips)

{
    "name": <clip_definition>
}

与参数一样,不同类型的剪辑`格式不同,但简单的剪辑是:

  • IdentityClip: 字符串 #identity
  • ClipReference: 要引用的剪辑名,前缀为#,例如#my_amazing_clip
  • ModelClip: 模型资源位置+@+骨骼剪辑的名称,例如 mymod:block/test@default ,mymod:block/test#facing=east@moving

覆盖输入 (TimeClip)

格式: [ "apply", <clip_definition>, <parameter_definition> ]

示例:
["apply", "mymod:block/animated_thing@moving", "#cycle_time"]
["apply", [ "apply", "mymod:block/animated_thing@moving", [ "+", 3 ] ], "#cycle"]
说明

TimeClip采用另一个剪辑并使用自定义参数而不是当前时间来调用它。 通常用于使用参数而不是当前时间来调用ModelClip。

示例说明:
  • mymod:block/animated_thing@moving(#cycle_time)
  • mymod:block/animated_thing@moving(#cycle + 3)

触发事件 (TriggerClip)

格式: [ "trigger_positive", <clip_definition>, <parameter_definition>, "<event_text>"]

示例
[ "trigger_positive", "#default", "#end_cycle", "!transition:moving" ]
[ "trigger_positive", "mymod:block/animated_thing@moving", "#end_cycle", "boop" ] 
说明

TriggerClip在看起来上相当于TimeClip,但当parameter_description变为正时,也会在event_text中触发事件。 同时,它将clip_definition中的剪辑应用于相同的parameter_description。

示例说明
  • 在给定参数end_cycle的输入的情况下应用名为default的剪辑,当end_cycle为正变为到moving状态
  • 在给定参数end_cycle的输入的情况下应用名为mymod:block/animated_thing@moving的剪辑,当end_cycle为正触发boop事件

两个剪辑之间的混合 (SlerpClip)

格式: [ "slerp", <clip_definition>, <clip_definition>, <parameter_definition>, <parameter_definition> ]

示例
[ "slerp", "#closed", "#open", "#identity", "#progress" ]
[ "slerp", [ "apply", "#move", "#mover"], "#end", "#identity", "#progress" ]
说明

SlerpClip在两个独立的剪辑之间执行球形线性混合(spherical linear blend)。 换句话说,它会将一个剪辑平滑地变换为另一个剪辑。

两个clip_definition分别是要混合的剪辑。 第一个parameter_definition是“输入”。 from和to剪辑都以当前动画时间传递此参数的输出。 第二个parameter_definition是“progress”,一个介于0和1之间的值,表示我们在混合中的距离。 将此剪辑与trigger_positive和转换特殊事件组合可以允许两个固态之间的简单转换。

示例说明
  • 将“关闭”剪辑混合到“打开”剪辑中,为两个剪辑提供未更改的时间作为输入并混合进度#progress。
  • 当输入参数mover给定结束剪辑时,将移动剪辑的结果混合,其中未改变的时间作为混合进度#progress的输入。

状态(States)

状态部分只是所有可能状态的列表。

例如

"states": [
  "open",
  "closed",
  "opening",
  "closing",
  "dancing"
]
定义5 种状态: open, closed, opening, closing 和 dancing.

转换(Transitions)

The transitions section defines which states can go to what other states. A state can go to 0, 1, or many other states. To define a state as going to no other states, omit it from the section. To define a state as going to only one other state, create a key with the value of the state it can go to, for example "open": "opening". To define a state as going to many other states, do the same as if it were going to only one other state but make the value a list of all possible recieving states instead, for example: "open": ["closed", "opening"].

转换部分定义哪些状态可以转到其他状态。 状态可以进入0,1或许多其他状态。 若要一个状态不能进入其他状态,请从该部分中省略它。 若要一个状态仅能转到另一个状态,请创建一个具有其可以进入的状态值的键,例如"open": "opening"。 要将状态定义为转到许多其他状态,请执行相同的操作,就好像它只转到另一个状态,而是将值作为所有可能的接收状态的列表,例如:"open": ["closed", "opening"]。

一个完整的例子:

"transitions": {
  "open": "closing",
  "closed": [ "dancing", "opening" ],
  "closing": "closed",
  "opening": "open",
  "dancing": "closed"
}

这个例子是说:

  • open状态可以进入closing状态
  • closed状态可以进入dancing和opening状态
  • closing状态可以进入closed状态
  • opening状态可以进入open状态
  • dancing状态可以进入closed状态
基于 MkDocs 使用自定义主题构建. 托管于 Read the Docs.
启用夜间模式