Minecraft基岩版的附加包开发备忘录

据说在Minecraft BE 1.9.0左右可以添加实体,所以我试了试。我想记下我在那时了解到的东西。虽然这对于熟悉编程的人才有帮助,但希望对某些人能有所帮助。

こんなのを作った。プレイヤーのように振る舞う人型友好モブ。まだいろいろ機能足す必要があるけど……

moonlighter.gif

以前挑戦したときも 1.9.0 だった気がしなくもないが、とにかくその時は上手いことモブを追加することができなかった覚えがある。その時の詰みポイントはリソースパックだった。

因为会涉及到许多重要的术语,所以先简单罗列一下…

    • エンティティ設定

 

    • アニメーション設定、アニメーション名

 

    • アニメーションコントローラ設定、アニメーションコントローラ名

 

    MoLang

环境

    • Windows 10

 

    • Minecraft Bedrock Edition v1.10.0

 

    VSCode(テキストエディタ)

使用资源包来绘制原创生物模型。

以前挑戦したときにビヘイビアパックの作り方は把握したのだけど、リソースパックの設定がうまくいかず、ずっと透明人間がゾンビと戦う様を見ているだけだった。リソースパックの書き方のドキュメントなさすぎ……

最终的实体定义的 JSON 大致如下,后面的节会详细介绍。

{
  "format_version": "1.10.0",
  "minecraft:client_entity": {
    "description": {
      "identifier": "numani:starspread",
      "materials": {
        "default": "entity_alphatest"
      },
      "textures": {
        "default": "textures/entity/starspread/moonlighter-skin"
      },
      "geometry": {
        "default": "geometry.steve"
      },
      "animations": {
        "idle": "animation.humanoid.base_pose",
        "move": "animation.humanoid.move",
        "look_at_target_default": "animation.humanoid.look_at_target.default",
        "look_at_target_gliding": "animation.humanoid.look_at_target.gliding",
        "look_at_target_swimming": "animation.humanoid.look_at_target.swimming",
        "holding": "animtion.humanoid.holding",
        "charging": "animation.humanoid.charging",
        "damage_nearby_mobs": "animation.humanoid.damage_nearby_mobs",
        "swimming": "animation.humanoid.swimming",
        "use_item_progress": "animation.humanoid.use_item_progress",
        "move_controller": "controller.animation.humanoid.move",
        "look_at_target_controller": "controller.animation.humanoid.look_at_target"
      },
      "scripts": {
        "pre_animation": [
          "variable.tcos0 = (Math.cos(query.modified_distance_moved * 38.17) * query.modified_move_speed / variable.gliding_speed_value) * 57.3;",
          "variable.tcos1 = -variable.tcos0;",
          "variable.attack_body_rot_y = Math.sin(Math.sqrt(variable.attack_time) * 360.0) * 11.46;",
          "variable.cos_attack_body_rot_y = Math.cos(variable.attack_body_rot_y);",
          "variable.sin_attack_body_rot_y = Math.sin(variable.attack_body_rot_y);",
          "variable.internal_swim_pos = Math.mod(query.modified_distance_moved, 26.0);",
          "variable.attack = Math.sin((1.0 - (1.0 - variable.attack_time) * (1.0 - variable.attack_time)) * 180.0) * 57.3;",
          "variable.attack2 = Math.sin(variable.attack_time * 180.0) * 57.3;",
          "variable.z_bob = Math.cos(query.life_time * 103.13244) * 2.865 + 2.865;",
          "variable.x_bob = Math.sin(query.life_time * 76.776372) * 2.865;"
        ],
        "animate": [
          "move_controller",
          "look_at_target"
        ]
      },
      "render_controllers": [ "controller.render.steve" ],
      "spawn_egg": {
        "base_color": "#FFFFFF",
        "overlay_color": "#000000"
      },
      "enable_attachables": true
    }
  }
}

塞住的地方

所以,这个JSON中,从先前试过但没有成功的状态到能正常工作的主要差异是什么。

    • format_version が 1.10.0 である必要がある(以前は1.8.0にしてた)

 

    animation_controller オブジェクトは 1.10.0 では使わないので削除する

这一带。

然而…… 如果查看官方提供的 Minecon 2018 资源包中的 Minecon2018Resources 资源包,在浏览“蝎子”实体的 json 时,format_version 是设置为 1.8.0 的……为什么这次改为 1.10.0 就可以成功的原因还不清楚。官方请提供更多的文档~

可以在Minecon2018Resources的官方网站这里获取资源包。

给动画加上

format_version を 1.10.0 にするなどしてエンティティが表示されたので、移動するときに歩きアニメーションが再生されるようにしたい。アニメーションの定義方法は結構複雑で、次のような手順で作成する。

    1. アニメーション設定を書く

 

    1. アニメーション設定をエンティティ設定から参照する

 

    1. エンティティ設定を参照しながらアニメーションコントローラ設定を書く

 

    アニメーションコントローラ設定をエンティティ設定から参照する

定义动画

在资源包中创建一个像animations/starspread.json这样的动画定义文件。顺便说一下,starspread是这次新增的生物的ID,但并不一定非得与之相同。另外,由于这次新增的生物是使用其他动画定义文件的内容来重复利用的,所以实际上并没有创建该文件。

动画定义文件的内容看起来是这样的。

{
    "format_version": "1.8.0",
    "animations": {
        "animation.humanoid.move": {
            "loop": true,
            "bones": {
                "rightArm": { "rotation": [ "variable.tcos1", 0.0, 0.0 ] },
                "leftArm": { "rotation": [ "variable.tcos0", 0.0, 0.0 ] },
                "rightLeg": { "rotation": [ "variable.tcos0 * 1.4", 0.0, 0.0 ] },
                "leftLeg": { "rotation": [ "variable.tcos1 * 1.4", 0.0, 0.0 ] }
            }
        }
    }
}

format_version フィールドとか animations オブジェクトは必須。その中の animation.humanoid.move はアニメーション名で、自分で命名する。これはさっき見せたエンティティ設定の中か、またはアニメーションコントローラ設定で使ってる。

そしてアニメーション名のついたオブジェクトの中身は、アニメーションの内容を書く。rightArm とか leftLeg とかが、右腕や左足の動きを設定する。rotation は回転。このアニメは両手両足を振りながら歩くモーションに使う目的で書かれているので、それぞれのパーツを回転させているというわけ。他にも scale で拡縮したりできるのかな?

さらに rotation の中には、 X, Y, Z 軸それぞれの回転角度を書くわけだけど、X軸(たぶん)のところに variable.tcos1 * 1.4 などと不思議な計算式が書かれている……

Minecraft BE のアドオンの中では、MoLangという文法で計算式を埋め込める部分がある。variable.tcos1 とかいうのは、変数にアクセスする式。この変数がどこで定義されているかというと……エンティティ設定の、minecraft:client_entity/description/scripts/pre_animationのところを探すと、変数の値を編集するスクリプトが書かれているのが見つけられる。それは以下の部分。(jsonってコメントつけられないのだけど、省略や説明のためにつけてます。許してね)

{
  "format_version": "1.10.0",
  "minecraft:client_entity": {
    "description": {

      // (略)

      "scripts": {
        "pre_animation": [
          "variable.tcos0 = (Math.cos(query.modified_distance_moved * 38.17) * query.modified_move_speed / variable.gliding_speed_value) * 57.3;",
          "variable.tcos1 = -variable.tcos0;",
          "variable.attack_body_rot_y = Math.sin(Math.sqrt(variable.attack_time) * 360.0) * 11.46;",
          "variable.cos_attack_body_rot_y = Math.cos(variable.attack_body_rot_y);",
          "variable.sin_attack_body_rot_y = Math.sin(variable.attack_body_rot_y);",
          "variable.internal_swim_pos = Math.mod(query.modified_distance_moved, 26.0);",
          "variable.attack = Math.sin((1.0 - (1.0 - variable.attack_time) * (1.0 - variable.attack_time)) * 180.0) * 57.3;",
          "variable.attack2 = Math.sin(variable.attack_time * 180.0) * 57.3;",
          "variable.z_bob = Math.cos(query.life_time * 103.13244) * 2.865 + 2.865;",
          "variable.x_bob = Math.sin(query.life_time * 76.776372) * 2.865;"
        ],
        // (略)
      },

      // (略)

    }
  }
}

也许是用 JavaScript 写的吧。通过准确的时机调用这个脚本(不知道什么时候调用),以控制动画。

2. アニメーションをエンティティに割り当てる。

前一节所写的动画设置还没有分配给实体。现在我们来尝试将其分配给本次的实体。再次查看之前展示的实体设置,已经分配了动画的部分如下所示。

{
  "format_version": "1.10.0",
  "minecraft:client_entity": {
    "description": {

      // (略)

      // ここでアニメーションを設定
      "animations": {
        "idle": "animation.humanoid.base_pose",
        "move": "animation.humanoid.move",
        "look_at_target_default": "animation.humanoid.look_at_target.default",
        "look_at_target_gliding": "animation.humanoid.look_at_target.gliding",
        "look_at_target_swimming": "animation.humanoid.look_at_target.swimming",
        "holding": "animtion.humanoid.holding",
        "charging": "animation.humanoid.charging",
        "damage_nearby_mobs": "animation.humanoid.damage_nearby_mobs",
        "swimming": "animation.humanoid.swimming",
        "use_item_progress": "animation.humanoid.use_item_progress",
        "move_controller": "controller.animation.humanoid.move",
        "look_at_target_controller": "controller.animation.humanoid.look_at_target"
      },

      // (略)

    }
  }
}

animations オブジェクトの中に、使用したいアニメーションをリストアップする。フィールド名はここで適当に決めて書くが、フィールドの中身は先ほどのアニメーション設定で作成したアニメーション名を指定する。

举例来说,让我们来看看以下的部分:

"move": "animation.humanoid.move"

这意味着我们将使用 “animation.humanoid.move” 动画,并为它添加一个别名叫做 “move”。当从实体设置中引用动画时,我们将以列表形式编写这样的设置。

3. アニメーションコントローラを定義する

一部のアニメーション制御には、アニメーションコントローラが必要になることがある。一部のアニメーションっていうのは、アニメーションを再生する条件を決めたり、アニメーションとアニメーションの間を滑らかに繋ぐなど、複数のアニメーションの組み合わせを適切に制御しないといけないもの。

アニメーション設定ファイルは、リソースパックの animation_controllers フォルダの中にjsonファイルを作って書く。以下のような感じ。

{
    "format_version": "1.8.0",
    "animation_controllers": {
        "controller.animation.humanoid.riding": {
            "states": {
                "default": {
                    "transitions": [
                        { "riding": "query.is_riding" }
                    ]
                },
                "riding": {
                    "animations": [
                        { "riding.arms": [] },
                        { "riding.legs": [] }
                    ],
                    "transitions": [
                        { "default": "!query.is_riding" }
                    ]
                }
            }
        }
    }
}

format_version フィールドと animation_controllers オブジェクトは必須。で、 controller.animation.humanoid.riding とかいうのはアニメーションコントローラ名で、自分でつける。この名前はエンティティ設定の中で使う。ちなみに、このデータはバニラのデータの中身から入手していて、humanoidっていうのは人型モブの間で使いまわされているアニメーションコントローラ設定。

controller.animation.humanoid.riding オブジェクトの中には states オブジェクトが必須で、その中に実際のアニメーション制御の設定が書かれている。

states というだけあって、アニメーションコントローラではステートマシンを使ってアニメーション同士の間を切り替えるための設定が書ける。states オブジェクトの中身は default, riding オブジェクトなので、このアニメーションコントローラには default, riding の2つのステートがあるということになる。それぞれ、「騎乗していない状態」「騎乗している状態」のアニメーションを設定するというわけ。

在状态中可以编写animations和transitions对象。如果实体处于相应的状态,则会播放在animations中编写的动画。在animations中,可以使用实体设置中指定的动画别名进行引用。

"animations": [
    { "riding.arms": [] },
    { "riding.legs": [] }
],

由于这种写法,将会播放名为rinding.arms和riding.legs的别名的动画。虽然将数组作为字段值传递,但似乎可以为动画传递参数。关于这方面的规格还没有深入研究。

关于transitions对象,有一些表示默认状态的对象,其中包括以下的transitions对象:

"transitions": [
    { "riding": "query.is_riding" }
]

在这里,可以指定在满足什么条件时转移到哪个状态。

如果query.is_riding是一种查询方式,那么如果当前的实体正在骑着其他实体,它将返回true。那么,它会顺利地进入骑行状态。

4. 参考动画控制器

アニメーションコントローラ設定も、やはりエンティティ設定から参照しないと意味がない。アニメーションコントローラは、アニメーションと同じように、エンティティ設定の animations オブジェクトの中から参照する。animations オブジェクトの中には、アニメーションとアニメーションコントローラを混在させて書くというわけ。

如果从最初的例子中提取相关部分,则如下所示。

{
  "format_version": "1.10.0",
  "minecraft:client_entity": {
    "description": {

      // (略)

      "animations": {
        // (略)
        "move_controller": "controller.animation.humanoid.move",
        "look_at_target_controller": "controller.animation.humanoid.look_at_target"
      },

      // (略)

    }
  }
}

我明白了,刚才提到的controller.animation.humanoid.move动画控制器正在被引用。

由于实体设置的动画对象中指定了动画控制器,而该动画控制器进一步引用了实体设置的动画对象的内容,所以设置会有些复杂,但应该可以按照以下方式进行设置。

我累了

其实我也改了行为包,但写文章累了,就写到这里吧。说实话,BE版插件制作的日本语资料几乎没有,英语资料也非常有限……虽然插件制作的支持是最近才出现的,所以可以说是理所当然的。

如果这篇文章能对想要制作附加组件的日本人有一点帮助的话……!

广告
将在 10 秒后关闭
bannerAds