模型动画
ChaEngine 不传输动画文件。服务端只同步动画资源路径、默认动画名和运行操作,客户端从自己的 resourcepacks/ChaEngine/model/ 或 ChaAssets 资源中读取动画定义。
使用 Blockbench .bbmodel 时,动画可以和模型保存在同一个工程中,不必填写独立的 animation 路径。客户端读取 position、rotation、scale 数值轨道,并将曲线关键帧按 20 Hz 归一化;表达式和事件轨道需要先烘焙为数值关键帧。
完整示例
一个可供方块或物品使用的配置片段:
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。以下命令建立或停止特殊动画状态:
/chaengine block animation play <location> <animation>
/chaengine block animation stop <location>再次播放会直接替换旧名称。执行停止后,该方块进入显式无动画状态,不会立刻回到默认动画。断开世界、资源代次变化或动画状态整体清理后,下一次渲染才重新以配置默认值开始。
方块动画目标由维度和方块位置定位,但模型 ID 始终从方块实体自己的数据读取,不存在坐标到模型 ID 的映射。
物品默认动画
未填写 item-texture、直接渲染三维模型的物品可以播放 default-animation。物品没有服务端“播放一次特殊动画”的公开操作。填写 item-texture 后改用静态平面物品渲染,模型动画字段不参与显示。
实体自动状态动画
客户端按以下优先顺序判断当前状态:死亡、攻击、受伤、使用、游泳、潜行、空中、奔跑、移动、空闲。每种状态依次寻找这些候选名称:
| 状态 | 候选动画 ID |
|---|---|
| 空闲 | idle、animation.idle |
| 移动 | move、walk、walking、animation.move、animation.walk |
| 奔跑 | run、running、sprint、animation.run |
| 攻击 | attack、attacking、swing、animation.attack |
| 受伤 | hurt、hit、damage、animation.hurt |
| 死亡 | death、die、dead、animation.death |
| 空中 | jump、fall、air、animation.jump |
| 游泳 | swim、swimming、animation.swim |
| 潜行 | sneak、crouch、animation.sneak |
| 使用 | use、cast、skill、animation.use |
匹配忽略大小写,并接受完整名称以 .候选名、_候选名 或 /候选名 结尾。当前状态找不到可用动画时,再尝试 idle。
玩家时装同样跟随穿戴者状态选择动画,因此装备配置只需要提供 animation 路径,不配置默认名称。
服务端触发的实体特殊动画
对有效实体执行以下命令后,指定名称会覆盖自动状态动画:
/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,其他模型能力不受影响。
- chaengineanimation{id=animation.slime_common.attack;duration=20} @self| 参数 | 别名 | 默认值 | 说明 |
|---|---|---|---|
id | i | 无 | 必填;动画文件中的完整动画 ID,可使用 MythicMobs 占位符 |
duration | d | 20 | 可使用 MythicMobs 占位符;必须大于 0,单位为服务端 tick |
@self 可以换成 @target 或其他实体目标器;不写目标器时使用施法者。集合目标器会为每个目标分别计时。
同一实体再次执行时,新动画会立即替换旧动画并重新计时。时间结束后恢复 ChaEngine 的实体自动状态动画。实体死亡、MythicMobs despawn、区块卸载、玩家退出或 ChaEngine 关闭时,未结束的计时都会清理;旧计时不会停止后来由命令、Java API 或新技能播放的动画。
mechanic 固定静默执行,不派发命令、不发送玩家消息,也没有 replace 或 silent 参数。配置加载错误和不受支持的 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 文件,并至少提供 idle 或 animation.idle。
物品动画不显示:填写 item-texture 时使用的是平面贴图路径;删除该字段才渲染带动画的三维模型。
猹件开发组