SPGoding
Minecraft Vanilla 中,拉弓有动画,抛钓竿有动画…然而我们自己拿胡萝卜钓竿改的武器没有动画!
今天咱就来做这么个东西:



首先了解一下动画的原理:许多帧的连续播放。
为了制作模型动画,每一帧都需要是一个单独的模型文件。胡萝卜钓竿的耐久度太低(25),用来制作动画实属浪费,应该尽量把它留给需要进行右键判定的物品。本教程中使用钻石斧(diamond_axe,耐久 1561,足够我们浪了)作为动画模型的载体。
* 9.10 更新,可以把胡萝卜钓竿的材质修改为透明并放置在玩家副手。这样所有的帧模型就都可以用钻石斧来制作了,省去了区分胡萝卜钓竿、钻石斧的麻烦,并且将能够引入动画打断机制。教程后文并未更改,仍区分了胡萝卜钓竿和钻石斧,如有特殊需求请自行更改。


我们还需要一个计分项来记录动画播放到的位置。本文中使用 cd(cooldown,设定上在动画播放过程中是不能使用武器的,属于“冷却”阶段)进行记录。
* 9.10 更新,不同的动画可以通过新建记分板分数进行记录,甚至可以通过检测记分板的值来做到打断前摇/后摇的效果,瞬间提升游戏操作流畅感与操作上限。所谓的流畅感,就是在玩家按下按键以后能够迅速获得响应(制作动画本身就是提升流畅感的一种方式)。引入打断机制,响应会更加及时。


制作一个模型动画,大体过程如下:



看着简单,其实还是有不少坑的(主要是在写模型的部分)。


一. 右键「胡萝卜钓竿改的武器」触发。
胡萝卜钓竿的右键检测是基本功,用计分板判据 minecraft.used:minecraft.carrot_on_a_stick 即可,我就不多讲了【跑。


二. 设置 cd 的分数为动画时长。
以下是一个触发以后的函数示例:

代码:

  1. scoreboard players set @s cd 13

该动画将持续 13 刻(0.65 秒)


三. 每刻减少 cd 的值。
在加了 #minecraft:tick 的函数中写上这条命令

代码:

  1. scoreboard players remove @a cd 1



四. 根据 cd 的值放置不同耐久度的钻石斧,实现动画。
本教程中,将制作一个「将火把向后引、迅速向前甩」的动画(如帖子开头动图所示)。
这里开始说本教程第一个重点:钻石斧需要修改攻击速度
为什么呢?因为在使用 replaceitem 更换物品的时候,物品会有一个快速向上移动的动画



事实上,它会严重干扰我们自制动画的效果(想象一下,你的武器快速地上下抽动…噫)
这个动画的速度与玩家的攻击速度属性有关。属性越高,动画越快。因此,想要它不播放这个动画,我们可以把攻击速度设到极高…
然而,经过测试,不管多高都会有一个上升的过程。让我们一起大呼:MJSB(这四个字母是本教程第二个重点)!
极高不行,只能把它设置到极低,使其不会向上移动。玩家默认攻击速度为 4,将其减至小于等于 0 即可彻底禁用该动画。以下是一个示例 NBT:

代码:

  1. {AttributeModifiers:[{AttributeName:"generic.attackSpeed",Operation:0,Amount:-4d,UUIDMost:1L,UUIDLeast:1L}],HideFlags:63,display:{Name:""""},Unbreakable:1b}

接下来我们开始写每一帧的模型。


以下是火把正常状态下的模型 foobar:item/pca/torch/normal(使用胡萝卜钓竿作为载体,使其可以通过右键触发命令。该胡萝卜钓竿也需要设置攻击速度 -4。* 如前文 9.10 更新所言,可以全部使用钻石斧制作。):

代码:

  1. {
  2.     "textures": {
  3.   "torch": "foobar:item/pca/torch"
  4.     },
  5.     "elements": [
  6.   {
  7.    "from": [7, 3, 7],
  8.    "to": [9, 13, 9],
  9.    "faces": {
  10.     "north": {
  11.   "uv": [2, 0, 0, 10],
  12.   "texture": "#torch"
  13.     },
  14.     "east": {
  15.   "uv": [0, 0, 2, 10],
  16.   "texture": "#torch"
  17.     },
  18.     "south": {
  19.   "uv": [2, 0, 0, 10],
  20.   "texture": "#torch"
  21.     },
  22.     "west": {
  23.   "uv": [0, 0, 2, 10],
  24.   "texture": "#torch"
  25.     },
  26.     "up": {
  27.   "uv": [0, 0, 2, 2],
  28.   "rotation": 180,
  29.   "texture": "#torch"
  30.     },
  31.     "down": {
  32.   "uv": [0, 5, 1, 6],
  33.   "texture": "#torch"
  34.     }
  35.    }
  36.   }
  37.     ],
  38.     "display": {
  39.   "firstperson_righthand": {
  40.    "translation": [0, 10, 0],
  41.    "rotation": [-30, 0, 0],
  42.    "scale": [1.5, 1.5, 1.5]
  43.   },
  44.   "thirdperson_righthand": {
  45.    "translation": [0, 0, 0],
  46.    "rotation": [0, 0, 0],
  47.    "scale": [1.3, 1.3, 1.3]
  48.   },
  49.   "gui": {
  50.    "translation": [0, 0, 0],
  51.    "rotation": [0, 45, -45],
  52.    "scale": [1.5, 1.5, 1.5]
  53.   }
  54.     }
  55. }

本文第三个重点,所有帧模型的 display.firstperson_xxxhand.translation[1] 的值需要在原有基础上加 10,这是因为前文我们为了避免那个扰人的上抬动画将攻击速度修改为 0,武器现在永远静止在了正常位置向 y 轴负方向偏移 10 个单位(手动测量,误差 <= 1 个单位)的位置,需要手动矫正,否则会看不到武器。
这是火把的贴图 foobar:item/pca/torch:



这是火把向后引的帧模型 foobar:item/pca/torch/back:

代码:

  1. {
  2.     "parent": "foobar:item/pca/torch/normal",
  3.     "display": {
  4.   "firstperson_righthand": {
  5.    "translation": [0, 10, 0],
  6.    "rotation": [15, 0, -20],
  7.    "scale": [1.5, 1.5, 1.5]
  8.   },
  9.   "thirdperson_righthand": {
  10.    "translation": [0, 0, 0],
  11.    "rotation": [45, 0, 0],
  12.    "scale": [1.3, 1.3, 1.3]
  13.   }
  14.     }
  15. }



这是火把向前伸的帧模型 foobar:item/pca/torch/front:

代码:

  1. {
  2.     "parent": "foobat:item/pca/torch/normal",
  3.     "display": {
  4.   "firstperson_righthand": {
  5.    "translation": [0, 10, 0],
  6.    "rotation": [-60, 0, 20],
  7.    "scale": [1.5, 1.5, 1.5]
  8.   },
  9.   "thirdperson_righthand": {
  10.    "translation": [0, 0, 0],
  11.    "rotation": [-45, 0, 0],
  12.    "scale": [1.3, 1.3, 1.3]
  13.   }
  14.     }
  15. }



然后我们把除了 normal 外的两个帧模型设置到钻石斧 minecraft:item/diamond_axe 上面(normal 设置到胡萝卜钓竿上,因为我们要进行右键检测):

代码:

  1. {
  2.     "overrides": [
  3.   {
  4.    "predicate": {
  5.     "damage": 6.4061499039077514413837283792441e-4
  6.    },
  7.    "model": "foobar:item/pca/torch/back"
  8.   },
  9.   {
  10.    "predicate": {
  11.     "damage": 0.00128122998078155028827674567585
  12.    },
  13.    "model": "foobar:item/pca/torch/front"
  14.   }
  15.     ]
  16. }



以下是实现动画的示例命令,需要由玩家高频执行:

代码:

  1. execute if entity @s[scores={cd=5..13}] run replaceitem entity @s hotbar.0 minecraft:diamond_axe{Damage:1s,display:{Name:""""},AttributeModifiers:[{AttributeName:"generic.attackSpeed",Operation:0,Amount:-4d,UUIDMost:1L,UUIDLeast:1L}],Unbreakable:1b,HideFlags:63}
  2. execute if entity @s[scores={cd=2..4}] run replaceitem entity @s hotbar.0 minecraft:diamond_axe{Damage:2s,display:{Name:""""},AttributeModifiers:[{AttributeName:"generic.attackSpeed",Operation:0,Amount:-4d,UUIDMost:1L,UUIDLeast:1L}],Unbreakable:1b,HideFlags:63}
  3. execute if entity @s[scores={cd=1}] run replaceitem entity @s hotbar.0 minecraft:carrot_on_a_stick{Damage:2s,display:{Name:""""},AttributeModifiers:[{AttributeName:"generic.attackSpeed",Operation:0,Amount:-4d,UUIDMost:1L,UUIDLeast:1L}],Unbreakable:1b,HideFlags:63}



五. 在 cd 为某个值时,产生武器的效果。
可以在上面那个函数中加入以下命令:

代码:

  1. execute if entity @s[scores={cd=4}] run functoin foobar:shoot_fireball

其中 foobar:shoot_fireball 是发射火球的函数。


另外在折腾几天的过程中我还有些小技巧想与大家分享:




⊙v⊙
竟然还有Attribute这种操作...

粘兽
逐渐代替插件

xiaowei233v
游戏技巧命令版简直是一个月发一次=-=

Sakur9
厉害了,很棒。