Skip to content
On this page

模型动画

ChaEngine 不传输动画文件。服务端只同步动画资源路径、默认动画名和运行操作,客户端从自己的 resourcepacks/ChaEngine/model/ 或 ChaAssets 资源中读取动画定义。

使用 Blockbench .bbmodel 时,动画可以和模型保存在同一个工程中,不必填写独立的 animation 路径。客户端读取 position、rotation、scale 数值轨道,并将曲线关键帧按 20 Hz 归一化;表达式和事件轨道需要先烘焙为数值关键帧。

完整示例

一个可供方块或物品使用的配置片段:

yaml
animated_crystal:
  model: "crystal/crystal.geo.json"
  animation: "crystal/crystal.animation.json" # 客户端动画文件
  texture: "crystal/crystal.png"
  default-animation: "idle"                   # 文件中实际存在的动画 ID
  scale: 1.0
  position: [0, 0, 0]
  rotation: [0, 0, 0]
  collision: [1, 1, 1]

实体与时装没有 default-animation 配置,它们按实体状态从动画文件选择名称。

动画类型

方块默认动画与特殊动画

方块首次渲染时使用 default-animation。以下命令建立或停止特殊动画状态:

text
/chaengine block animation play <location> <animation>
/chaengine block animation stop <location>

再次播放会直接替换旧名称。执行停止后,该方块进入显式无动画状态,不会立刻回到默认动画。断开世界、资源代次变化或动画状态整体清理后,下一次渲染才重新以配置默认值开始。

方块动画目标由维度和方块位置定位,但模型 ID 始终从方块实体自己的数据读取,不存在坐标到模型 ID 的映射。

物品默认动画

未填写 item-texture、直接渲染三维模型的物品可以播放 default-animation。物品没有服务端“播放一次特殊动画”的公开操作。填写 item-texture 后改用静态平面物品渲染,模型动画字段不参与显示。

实体自动状态动画

客户端按以下优先顺序判断当前状态:死亡、攻击、受伤、使用、游泳、潜行、空中、奔跑、移动、空闲。每种状态依次寻找这些候选名称:

状态候选动画 ID
空闲idleanimation.idle
移动movewalkwalkinganimation.moveanimation.walk
奔跑runrunningsprintanimation.run
攻击attackattackingswinganimation.attack
受伤hurthitdamageanimation.hurt
死亡deathdiedeadanimation.death
空中jumpfallairanimation.jump
游泳swimswimminganimation.swim
潜行sneakcrouchanimation.sneak
使用usecastskillanimation.use

匹配忽略大小写,并接受完整名称以 .候选名_候选名/候选名 结尾。当前状态找不到可用动画时,再尝试 idle

玩家时装同样跟随穿戴者状态选择动画,因此装备配置只需要提供 animation 路径,不配置默认名称。

服务端触发的实体特殊动画

对有效实体执行以下命令后,指定名称会覆盖自动状态动画:

text
/chaengine entity animation play <entity> <animation>
/chaengine entity animation stop <entity>

再次播放会替换当前覆盖。执行停止后删除覆盖,立即恢复自动状态选择。

服务端只验证实体有效且名称非空,不会读取客户端动画文件。名称拼写错误时操作仍可能返回成功,但客户端没有可播放内容。

在 MythicMobs 技能中播放

安装 MythicMobs 后,ChaEngine 会注册 chaengineanimation mechanic,并继续使用同一个服务端 Jar。当前 API 编译兼容基线包括 MythicMobs 4.11.1,以及 MythicMobs 5.6.2、5.11.2 与 5.13.0。Minecraft 1.16.5 使用 4.11.1;MythicMobs 5.7 起不再支持 1.16 系列,较新环境使用对应的 5.x 版本。没有安装 MythicMobs 时只是不注册这个 mechanic,其他模型能力不受影响。

yaml
- chaengineanimation{id=animation.slime_common.attack;duration=20} @self
参数别名默认值说明
idi必填;动画文件中的完整动画 ID,可使用 MythicMobs 占位符
durationd20可使用 MythicMobs 占位符;必须大于 0,单位为服务端 tick

@self 可以换成 @target 或其他实体目标器;不写目标器时使用施法者。集合目标器会为每个目标分别计时。

同一实体再次执行时,新动画会立即替换旧动画并重新计时。时间结束后恢复 ChaEngine 的实体自动状态动画。实体死亡、MythicMobs despawn、区块卸载、玩家退出或 ChaEngine 关闭时,未结束的计时都会清理;旧计时不会停止后来由命令、Java API 或新技能播放的动画。

mechanic 固定静默执行,不派发命令、不发送玩家消息,也没有 replacesilent 参数。配置加载错误和不受支持的 MythicMobs 版本仍会在控制台给出诊断。

服务端只检查 id 非空,不能确认客户端是否真的拥有该动画 ID。没有画面时请检查客户端动画文件和完整 ID。真实 ID 写作 animation.slime_common.attack,不要把 Markdown 显示时可能出现的反斜杠写进下划线前。

实体覆盖动画

覆盖动画使用独立动画层,不会替换基础的移动、空闲或普通特殊动画。它适合在实体仍保持行走姿态时叠加受击、施法、挥手等局部动作。

覆盖动画通过 Java API 控制:

  • playCarrierEntityOverlayAnimation(entity, animationName) 播放或重新开始指定覆盖动画;
  • stopCarrierEntityOverlayAnimation(entity) 停止覆盖层,基础动画继续按原状态运行。

同一实体同时只保留一个服务端覆盖动画;再次播放会替换并重新开始。名称仍必须存在于客户端动画文件中,服务端不会校验资源内容。普通的实体动画命令控制基础覆盖状态,不等同于这层叠加能力。

每个独立受伤周期开始时,客户端都会将自动受伤候选动画(例如 hit)重新播放一次;同一受伤周期持续期间不会逐帧重置。该行为属于客户端自动状态,不需要服务端额外调用覆盖动画 API。

事件与顺序

服务端提供实体特殊动画开始、结束事件,普通特殊动画和 API 触发的覆盖动画共用这两个事件类型:

  • 开始事件在发送播放操作前触发,包含实体和本次动画名。
  • 结束事件在发送停止操作前触发,包含实体和服务端最后记录的动画名;此前没有记录时为 null
  • 连续两次播放会触发两次开始事件,后一动画替换前一动画,但不会自动补发前一动画的结束事件。
  • 客户端动画自然播完不会回传服务端,因此不会自动触发结束事件。

方块动画目前没有对应的公开 Bukkit 开始/结束事件。API 用法见Java API

运行规则

  • animation 为空时,模型按静态方式渲染。
  • default-animation 只属于方块和物品配置。
  • OBJ 是静态网格,即使填写动画字段也会忽略并记录一次警告。
  • .bbmodel 的动画名称来自工程内动画列表;default-animation 和实体状态候选名称的选择规则不变。
  • 资源更新、ChaAssets 授权撤销或玩家断开会清理客户端动画状态和相关缓存。
  • 动画名必须与客户端文件实际 ID 对应;服务端不会替客户端纠正名称。
  • 覆盖动画使用独立控制层;停止覆盖动画不会停止基础动画。

常见问题

实体一直播放 idle:确认状态动画 ID 属于上表候选,或使用能以候选名结尾的完整 ID。

方块停止后没有恢复 idle:这是显式停止语义。需要恢复时再次播放 idle,或让客户端重新建立动画状态。

服务端返回成功但没有动画:返回值只说明目标和输入可发送;检查客户端动画文件与动画 ID。

覆盖动画播放后走路停了:确认业务调用的是 playCarrierEntityOverlayAnimation,而不是会替换基础状态的 playCarrierEntityAnimation

时装模型静止:确认装备配置包含有效 animation 文件,并至少提供 idleanimation.idle

物品动画不显示:填写 item-texture 时使用的是平面贴图路径;删除该字段才渲染带动画的三维模型。

相关文档