【マインクラフト（統合版）】定義が必要なアイテムアニメーションまとめ

# はじめに

以下のページでご紹介したもののうちネイティブでは再生されない一人称のアニメーションがありましたが、その部分を適用するには自分でアニメーションを定義する必要があります。

https://qiita.com/glasses_seven/items/93ffdf68edb5e1f806bc/

ただ、その部分をゼロから作るとなると大変な作業になりますので、既存アイテムのアニメーションを代用するのがお手軽でしょう。
ここでは弓のアニメーションを例に取り上げて実装する方法をご紹介します。

:::note info
基本的な部分は以下のページでダミーアイテムが実装済みである事を前提に進めていきます。
:::

https://qiita.com/glasses_seven/items/b41797e3df3325c3fab5/


# 定義ファイルの内訳

弓のアニメーションを適用するためには[&gt;&gt; ダミーアイテムの作り方][dummy-item]のページで実装していたファイルに加えて、以下の構成でファイルが必要になります。

:::note info
リソースパック内の`>>> 追加分 START`～`<<< 追加分 END`で囲んだ部分が今回追加で必要になるファイルです。
:::

```text:ビヘイビアパック内で必要になるファイル
/<ビヘイビアパックのルート>
    /items
        dummy_item.json
```

```text:リソースパック内で必要になるファイル
/<リソースパックのルート>

    >>> 追加分 START
    /animations
        dummy_item.animation.json
    /attachables
        dummy_item.json
    /models
        /entity
            dummy_item.geo.json
    /render_controllers
        dummy_item.render_controllers.json
    <<< 追加分 END

    /texts
        en_US.lang
    /textures
        item_texture.json
```


# 定義ファイルの内容

ここでは今回追加となる４つのJSONファイルの内容を順に見ていきます。
全てのファイルはバニラの弓のJSONデータに手を加えたものです。

:::note info
`dummy_item`および`customize:dummy_item`の部分は弓のアイテムIDを置き換えたものです。
:::

:::note info
三人称アニメーションについてはuse_animationで指定されたものが優先されます。
`>>> 不必要箇所 START`～`<<< 不必要箇所 END`で囲んだ部分は三人称アニメーションに関わる部分なので必要ありません。
:::

```json:<リソースパック>/attachables/dummy_item.json
{
    "format_version": "1.10.0",
    "minecraft:attachable": {
        "description": {
            "identifier": "customize:dummy_item",
            "materials": {
                "default": "entity_alphatest",
                "enchanted": "entity_alphatest_glint"
            },
            "textures": {
                "default": "textures/items/dummy_item",

                >>> 不必要箇所 START
                "dummy_item_pulling_0": "textures/items/dummy_item_pulling_0",
                "dummy_item_pulling_1": "textures/items/dummy_item_pulling_1",
                "dummy_item_pulling_2": "textures/items/dummy_item_pulling_2",
                <<< 不必要箇所 END

                "enchanted": "textures/misc/enchanted_item_glint"
            },
            "geometry": {
                "default": "geometry.dummy_item"

                >>> 不必要箇所 START
                "dummy_item_pulling_0": "geometry.dummy_item_pulling_0",
                "dummy_item_pulling_1": "geometry.dummy_item_pulling_1",
                "dummy_item_pulling_2": "geometry.dummy_item_pulling_2"
                <<< 不必要箇所 END

            },
            "animations": {
                "wield": "animation.dummy_item.wield",
                "wield_first_person_pull": "animation.dummy_item.wield_first_person_pull"
            },
            "scripts": {
                "pre_animation": [
                    "variable.charge_amount = math.clamp((query.main_hand_item_max_duration - (query.main_hand_item_use_duration - query.frame_alpha + 1.0)) / 10.0, 0.0, 1.0f);"
                ],
                "animate": [
                    "wield",
                    {
                        "wield_first_person_pull": "query.main_hand_item_use_duration > 0.0f && c.is_first_person"
                    }
                ]
            },
            "render_controllers": [ "controller.render.dummy_item" ]
        }
    }
}
```

このファイルには今回追加しているファイルをマッピングする役割があります。
マッピングしている各データブロックは次の通りです。

<dl>
    <dt>textures</dt>
    <dd>テクスチャファイルが存在する<code>&lt;リソースパック&gt;textures/items/dummy_item</code>へのパスがマッピングされています。</dd>
    <dt>geometry</dt>
    <dd>モデル定義ファイルである<code>&lt;リソースパック&gt;/models/entity/dummy_item.geo.json</code>の定義がマッピングされています。</dd>
    <dt>animations</dt>
    <dd>アニメーション定義ファイルである<code>&lt;リソースパック&gt;/animations/dummy_item.animation.json</code>の定義がマッピングされています。</dd>
    <dt>render_controllers</dt>
    <dd>レンダーコントローラ定義ファイルである<code>&lt;リソースパック&gt;/render_controllers/dummy_item.render_controllers.json</code>の定義がマッピングされています。</dd>
</dl>

```json:<リソースパック>/models/entity/dummy_item.geo.json
{
    "format_version" : "1.16.0",
    "minecraft:geometry" : [

        >>> 不必要箇所 START
        {
        	"description" : {
        		"identifier" : "geometry.dummy_item_pulling_0",
        		"texture_width" : 16.0,
        		"texture_height" : 16.0
        	},
        	"bones" : [
        		{
        			"name" : "rightitem",
        			"texture_meshes" : [
        				{
        					"local_pivot" : [ 6.0, 0.0, 6.0 ],
        					"position" : [ 2.0, 1.0, -1.0 ],
        					"rotation" : [ 0.0, -135.0, 90.0 ],
        					"texture" : "dummy_item_pulling_0"
        				}
        			]
        		}
        	]
        },
        {
        	"description" : {
        		"identifier" : "geometry.dummy_item_pulling_1",
        		"texture_width" : 16.0,
        		"texture_height" : 16.0
        	},
        	"bones" : [
        		{
        			"name" : "rightitem",
        			"texture_meshes" : [
        				{
        					"local_pivot" : [ 6.0, 0.0, 6.0 ],
        					"position" : [ 2.01, 1.0, -1.0 ],
        					"rotation" : [ 0.0, -135.0, 90.0 ],
        					"texture" : "dummy_item_pulling_1"
        				}
        			]
        		}
        	]
        },
        {
        	"description" : {
        		"identifier" : "geometry.dummy_item_pulling_2",
        		"texture_width" : 16.0,
        		"texture_height" : 16.0
        	},
        	"bones" : [
        		{
        			"name" : "rightitem",
        			"texture_meshes" : [
        				{
        					"local_pivot" : [ 6.0, 0.0, 6.0 ],
        					"position" : [ 2.01, 1.0, -1.0 ],
        					"rotation" : [ 0.0, -135.0, 90.0 ],
        					"texture" : "dummy_item_pulling_2"
        				}
        			]
        		}
        	]
        },
        <<< 不必要箇所 END

        {
            "description" : {
                "identifier" : "geometry.dummy_item",
                "texture_width" : 16.0,
                "texture_height" : 16.0
            },
            "bones" : [
                {
                    "name" : "rightitem",
                    "texture_meshes" : [
                        {
                            "local_pivot" : [ 6.0, 0.0, 6.0 ],
                            "position" : [ 2.0, 1.0, -2.0 ],
                            "rotation" : [ 0.0, -135.0, 90.0 ],
                            "texture" : "default"
                        }
                    ]
                }
            ]
        }
    ]
}
```

```json:<リソースパック>/animations/dummy_item.animation.json
{
    "format_version": "1.10.0",
    "animations": {
        "animation.dummy_item.wield": {
            "loop": true,
            "bones": {
                "rightitem": {
                    "position": [ "c.is_first_person ? -5.5 : 0.5", "c.is_first_person ? -3.0 : -2.5", "c.is_first_person ? -3.0 : 1.0" ],
                    "rotation": [ "c.is_first_person ? 38.0 : 0.0", "c.is_first_person ? -120.0 : 0.0", "c.is_first_person ? -63.0 : 0.0" ]
                }
            }
        },
        "animation.dummy_item.wield_first_person_pull": {
            "loop": true,
            "bones": {
                "rightitem": {
                    "position": [ -1.5, " 2.5 + ( variable.charge_amount  >= 1.0 ? math.sin( (q.life_time) * 1000.0 * 1.3) * 0.1 - math.sin(q.life_time * 45.0) * 0.5 : 0.0)", -4.8 ],
                    "rotation": [ -53.0, 8.0, 35.0 ]
                }
            }
        }
    }
}
```

```json:<リソースパック>/render_controllers/dummy_item.render_controllers.json
{
    "format_version": "1.10",
    "render_controllers": {
        "controller.render.dummy_item": {
            "arrays": {
                "textures": {
                    "array.dummy_item_texture_frames": [
                        "texture.default",

                        >>> 不必要箇所 START
                        "texture.dummy_item_pulling_0",
                        "texture.dummy_item_pulling_1",
                        "texture.dummy_item_pulling_2"
                        <<< 不必要箇所 END

                    ]
                },
                "geometries": {
                    "array.dummy_item_geo_frames": [
                        "geometry.default",

                        >>> 不必要箇所 START
                        "geometry.dummy_item_pulling_0",
                        "geometry.dummy_item_pulling_1",
                        "geometry.dummy_item_pulling_2"
                        <<< 不必要箇所 END

                    ]
                }
            },
            "geometry": "array.dummy_item_geo_frames[query.get_animation_frame]",
            "materials": [ { "*": "variable.is_enchanted ? material.enchanted : material.default" } ],
            "textures": [ "array.dummy_item_texture_frames[query.get_animation_frame]", "texture.enchanted" ]
        }
    }
}
```

今回追加したファイル内の不必要部分は、テクスチャファイルも含め参照されないので、あってもなくても構いません。
また、`attachable`を定義するとアイテムの持ち方は`hand_equipped`の定義よりも優先されますので、こちら（”hand_equipped”）もあってもなくても構いません。


# テストしてみる

まずは[&gt;&gt; ダミーアイテムの作り方][dummy-item]のページでご紹介させて頂いた方法でテストしてみてください。
もしJSONファイルが正しく認識されない場合は、対応する括弧の過不足かないかどうかとカンマの位置が正しいかどうかを先に確認しておいた方がいいでしょう。

以下ではJSONファイルが正しく認識されている前提で動作を確認しています。

`use_animation`を"bow"で設定している場合は以下のようになります。
![一人称アニメーション](https://socket-manager.github.io/document/minecraft-contents/img/custom-item-animation-definition/bow.gif "一人称アニメーション")

ちなみに今回定義したアニメーションは`use_animation`の設定如何に関わらず、一人称では今回定義したアニメーションが優先して再生されます。
但し"eat"にした場合は、これに加えて食片が飛び散るエフェクトが以下のように表示されます。
![食べるアニメーション](https://socket-manager.github.io/document/minecraft-contents/img/custom-item-animation-definition/eat.gif "食べるアニメーション")


# おわりに

トライデントを投げる動作についても同じようにしてバニラからJSONデータを取ってくる事で定義できますが、一人称の画面ではトライデントの先の部分が見えるだけなので、実装するアイテムの見た目がトライデントより短い場合には画面に全く表示されない事も考えられます。

とは言え何も動きがなければボタンに反応しているのかどうかも判断できないので、見た目にこだわらずに簡易的に済ませたい場合には、とりあえず一人称のアニメーションが存在するもので代用しておくのがいいでしょう。


[dummy-item]: https://qiita.com/glasses_seven/items/b41797e3df3325c3fab5/