アドオン作成 - エンティティ(リソース)
目次は右上の「≡」から!
エンティティのリソースの仕組み
エンティティはビヘイビアもリソースもどちらも複雑です。
リソースパックでは、テクスチャを貼り付けるだけでなく、
アニメーションやジオメトリ、その他細かい要素、任意でパーティクルとサウンドを紐づける必要があります。
「entity_client」がメインとなって、エンティティとそれらの紐づける要素すべての中継となります。
● 略語
この記事では以下のような略語を使います。
Anim:「アニメーション」
AniCon:「アニメーションコントローラ」
RenCon:「レンダーコントローラ」
entity_client
● ファイルの場所
リソース
┣ manifest.json
┣ pack_icon.png
┗ entity
┗ 〇〇.entity.json
ファイル名は他のファイルとの区別のため「〇〇.entity.json」にするのを強くおすすめします。
別に「〇〇.json」でも動作はします。
● 基本構造
{
"format_version": "1.10.0",
"minecraft:client_entity": {
"description": {
"identifier": "ex:my_entity",
"materials": {
// マテリアル
},
"textures": {
// テクスチャ
},
"geometry": {
// ジオメトリ
},
"spawn_egg": {
// スポーンエッグのテクスチャ
},
"scripts": {
"animate": [
// Animキー
]
},
"animations": {
// Anim, AniCon
},
"render_controllers": [
// RenCon
]
}
}
}
● 詳細な構造
{
"format_version": "1.10.0",
"minecraft:client_entity": {
"description": {
"identifier": "ex:my_entity",
"min_engine_version": "1.18.0",
"materials": {
// マテリアル
},
"textures": {
// テクスチャ
},
"geometry": {
// ジオメトリ
},
"queryable_geometry": "Str",
"spawn_egg": {
// スポーンエッグのテクスチャ
},
"particle_effects": {
// パーティクル
},
"particle_emitters": {
// パーティクル・エミッター
},
"sound_effects": {
// サウンド
},
~#r"scripts": {
%%%%%% "variables": {
%%%%%% // Molang変数に関する設定
%%%%%% },
%%%%%% "initialize": "Molng-n",
%%%%%% "pre_animation": "Molang-n",
%%%%%% "scale": "Molang",
%%%%%% "scaleX": "Molang",
%%%%%% "scaleY": "Molang",
%%%%%% "scaleZ": "Molang",
%%%%%% "parent_setup": "Molang",
%%%%%% "animate": [
%%%%%% // Animキー
%%%%%% ],
%%%%%% "should_update_bones_and_effects_offscreen": "Molang",
%%%%%% "should_update_effects_offscreen": "Molang"
%%%%%%},r#~
"animations": {
// Anim, AniCon
},
"render_controllers": [
// RenCon
],
"enable_attachables": "Bool",
"hide_armor": "Bool",
"item": "Str"
}
}
}
● テクスチャ・ジオメトリ・マテリアルの紐づけ
後に説明する「複雑なエンティティ」ではない場合、以下のように紐づけが簡単になります。
"materials": {
"default": "(マテリアルID)"
},
"textures": {
"default": "(テクスチャのファイルパス)"
},
"geometry": {
"default": "(ジオメトリID)"
}
また、これも後に詳しい説明をしますが、RenConの指定も簡単になります。
"render_controllers": [
"(RenConID)"
]
複雑なエンティティとは、複数の状態をもったエンティティのことです。たとえば、村人は様々な職業という形で「状態」をもっています。
村人のように「状態」でテクスチャ、ジオメトリ、マテリアルが変わるエンティティを作る場合には紐づけが難しくなります。
2つの状態A、Bをもつエンティティにリソースを紐づける例で説明します。
まず、entity_clientでテクスチャなどを紐づける用意をします。
"materials": {
// "state1", "state2"の部分は自由
"state1": "(マテリアルID)",
"state2": "(マテリアルID)"
},
"textures": {
// すべて連動するわけではないので、
// 状態によって変わらなければそのまま"default"1つだけでOK
"default": "(テクスチャのファイルパス)"
}
// テクスチャ、ジオメトリ、マテリアルで書き方は変わらない
そして、RenCon側で状態に応じた条件分岐を作ってこれらのキー(上記の
"state1", "state2", "default"の部分)
を指定して、状態でテクスチャなどが切り替わるようにします。
RenConの作りかた/編集のしかたはRenConの章で説明します。
● スポーンエッグのテクスチャ
色を二つ指定するか、アイテムのTerrainID(とインデックス)を指定してテクスチャを決めます。
色を二つ指定する場合は、
"base_color"に下地の色、
"overlay_color"に模様の色を16進カラーコードで指定します。
"spawn_egg": {
"base_color": "#ffffff",
"overlay_color": "#0000ff"
}
テクスチャを指定する場合は、
"texture"にTerrainIDを、必要なら
"texture_index"の項目を追加してインデックスを整数で指定します。
"spawn_egg": {
"texture": "my_entity_spawn_egg"
}
● Animの紐づけ
先に大まかな説明をすると、Animはentity_clientと直接紐づけて常時そのAnimを実行するか、
AniConをはさんでentity_clientと紐づけて、条件に応じてAnimの実行するタイミングをコントロールするといった形になります。
まず、紐づけるAnimまたはAniConをentity_clientの
"animations"
で列挙しておきます。この際、自由にAnimキー名を決めます。
"animations": {
"(Animキー)": "(AnimID/AniConID)",
"(Animキー)": "(AnimID/AniConID)",
"(Animキー)": "(AnimID/AniConID)"
// ...
}
これらのうち、常に実行する/処理するもののAnimキーを
"scripts"の
"animate"に列挙します。
"scripts": {
"animate": [
"(Animキー)",
"(Animキー)",
"(Animキー)"
// ...
]
}
AniConを挟む場合は、そのAniCon内で
"scripts"の
"animate"のような場所があって、そこにAnimキーを書きます。
● RenConの紐づけ
"render_controllers"プロパティにRenConのIDを列挙します。
高度なことをしない限り、指定するのは1つになるはずです。
"render_controllers": [
"(RenConID)",
"(RenConID)"
// ...
]
また、Molang式で条件を添えることができます。
この場合、RenConはテクスチャやジオメトリなど、直接見た目に関わるものをコントロールしているという役割上、
条件を満たさないとエンティティが透明になります。
意図的でないならば、複数紐づけていずれか一つの条件が満たされるようにしましょう。
"render_controllers": [
{ "(RenConID)": "(条件(Molang))" },
{ "(RenConID)": "(条件(Molang))" }
// ...
]
● パーティクルとサウンド
Animと同じ要領でパーティクルとサウンドもAniConを使うことによって、条件に応じてそれらを発生させることができます。
entity_clientではこのような準備をします。
"particle_effects": {
"(パーティクルキー)": "(パーティクルID)"
// ...
},
"sound_effects": {
"(サウンドキー)": "(サウンドID)"
// ...
},
パーティクルキー、サウンドキーはAnimキーと同じで、名前を自由に決めます。
● variable変数の定義
"scripts"内の
"pre_animation"でMolangのvariable変数を定義することができます。
ここで定義した変数はAnimやAniConなど様々な場所で使うことができます。
"scripts": {
"pre_animation": [
"v.foo = math.sin(q.life_time);"
]
},
また、
"initialize"プロパティでそれら変数の初期値を設定できます。
"initialize": [
"v.foo = 0.0;"
]
上級 さらに、
"variables"プロパティでvariable変数をパブリックに設定して、矢印演算子を用いて読み取れるようにします。
"variables": {
"variable.foo": "public"
}
プロパティ名は設定したい変数、値は
"public"しかありません。
● Attachableに関する設定
"enable_attachables"の項目を
trueに設定すると、Attachableを有効にできます。
防具を身に着けるモブなのに防具が表示されないという場合はこの項目の設定を忘れている可能性が高いです。
AniCon
● ファイルの場所
リソース
┣ manifest.json
┣ pack_icon.png
┗ animation_controllers
┗ 〇〇.animation_controllers.json
ファイル名は他のファイルとの区別のため「〇〇.animation_controllers.json」(バニラ準拠)にするのをおすすめします。
別に「〇〇.json」でも動作はします。
● 基本構造
{
"format_version": "1.10.0",
"animation_controllers": {
~#r"~#M(83ffd9)controller.animation.my_entity.mainM#~": {
%%%% "initial_state": "(state名)",
%%%% "states": {
%%%% ~#b"(state名)": {
%%%%%%%% "animations":[
%%%%%%%% "(Animキー)",
%%%%%%%%
%%%%%%%% // または
%%%%%%%% { "(Animキー)": "(条件(Molang式))" }
%%%%%%%%
%%%%%%%% // ...
%%%%%%%% ],
%%%%%%%% "transitions": [
%%%%%%%% { "(state名)": "(条件(Molang式))" }
%%%%%%%% // ...
%%%%%%%% ]
%%%%%%%%}b#~
%%%% }
%%%%}r#~
}
}
● 詳細な構造
{
"format_version": "1.10.0",
"animation_controllers": {
~#r"~#M(83ffd9)controller.animation.my_entity.mainM#~": {
%%%% "initial_state": "(state名)",
%%%% "states": {
%%%% ~#b"(state名)": {
%%%%%%%% "animations":[
%%%%%%%% "(Animキー)",
%%%%%%%%
%%%%%%%% // または
%%%%%%%% { "(Animキー)": "(条件(Molang))" }
%%%%%%%%
%%%%%%%% // ...
%%%%%%%% ],
%%%%%%%% "transitions": [
%%%%%%%% { "(state名)": "(条件(Molang))" }
%%%%%%%%
%%%%%%%% // ...
%%%%%%%% ],
%%%%%%%% "particle_effects": [
%%%%%%%% {
%%%%%%%% "effect": "(パーティクルキー)",
%%%%%%%% "locator": "(Str)",
%%%%%%%% "pre_effect_script": "(Molang)",
%%%%%%%% "bind_to_actor": "(Bool)"
%%%%%%%% }
%%%%%%%% // ...
%%%%%%%% ],
%%%%%%%% "sound_effects": [
%%%%%%%% { "effect": "(サウンドキー)" }
%%%%%%%% // ...
%%%%%%%% ]
%%%%%%%%}b#~
%%%% }
%%%%}r#~
}
}
● AniConのしくみ
AniConは複数のstateの移動と、そのための条件(transition)をもとにAnimをコントロールします。
たとえば「stand」「walk」という2つのstateがあって、初めは「stand」だとします。
「stand」のtransitionに「歩いているか」という条件を設定して、その条件を満たしたら「walk」に移るようにして、
「walk」では歩くAnimが紐づいているAnimキーを指定すれば、歩き始めたときに歩くAnimがスタートするようになります。
「walk」にもtransitionに「立ち止まっているか(=歩いていないか))」の条件を設定して、その条件を満たしたら「stand」に移るようにするのを忘れてはいけません。
でないと立ち止まってもstateが「walk」のまま「stand」に移らず、歩くAnimが立ち止まっても再生されたままになってしまいます。
● 具体的な書き方
まず基本構造のマーカー部分がIDになります。「controller.animation.〇〇」という形でないといけません。
上記の例では〇〇の部分が「(エンティティ名).(どんなAniConか)」のようにさらにドット( . )で区切っています。
IDをプロパティ名とするオブジェクトの中にはまず、初めのstateをどれにするか指定する
"initial_state"と、stateをまとめる
"states"オブジェクトを書きます。
{
"format_version": "1.10.0",
"animation_controllers": {
~#r"controller.animation.my_entity.main": {
%%%% ~#M(83ffd9)"initial_state": "(state名)"M#~,
%%%% ~#M(83ffd9)"states"M#~: {
%%%%
%%%% }
%%%%}r#~
}
}
"states"オブジェクトの中にstateを列挙していきます。
stateは名前を自由に決め、その名前をプロパティ名とするオブジェクトになります。
{
"format_version": "1.10.0",
"animation_controllers": {
~#r"controller.animation.my_entity.main": {
%%%% "initial_state": "(state名)",
%%%% "states": {
%%%% ~#b~#M(83ffd9)"(state名)"M#~: {
%%%%%%%%
%%%%%%%%}b#~
%%%% }
%%%%}r#~
}
}
各stateの中身には
"animations"、
"transition"をプロパティ名とする配列を置きます。
"animations"にはこのstateに入ったときに再生されるAnimキーを列挙し、
"transition"には次はどのstateに移動するかを決める条件を以下のように列挙します。
{
"format_version": "1.10.0",
"animation_controllers": {
~#r"controller.animation.my_entity.main": {
%%%% "initial_state": "(state名)",
%%%% "states": {
%%%% ~#b"(state名)": {
%%%%%%%% "animate": [
%%%%%%%% "(Animキー)",
%%%%%%%% "(Animキー)"
%%%%%%%% // ...
%%%%%%%% ],
%%%%%%%% "transitions": [
%%%%%%%% { "(state名)": "(条件(Molang))" },
%%%%%%%% { "(state名)": "(条件(Molang))" }
%%%%%%%% // ...
%%%%%%%% ]
%%%%%%%%}b#~
%%%% }
%%%%}r#~
}
}
● パーティクルとサウンド
"animations"、
"transition"と並べて、そのstateに入ったときに発生させるパーティクルとサウンドを以下のように指定します。
"particle_effects": [
{
"effect": "(パーティクルキー)",
"pre_effect_script": "(Molang)"
}
// ...
],
"sound_effects": [
{ "effect": "(サウンドキー)" }
// ...
]
"pre_effect_script"ではそのパーティクル内で使うためのvariable変数を定義できます。
RenCon 上級
● ファイルの場所
リソース
┣ manifest.json
┣ pack_icon.png
┗ render_controllers
┗ 〇〇.render_controllers.json
ファイル名は他のファイルとの区別のため「〇〇.render_controllers.json」(バニラ準拠)にするのをおすすめします。
別に「〇〇.json」でも動作はします。
● 基本構造
{
"format_version": "1.8.0",
"render_controllers": {
"controller.render.my_entity": {
"arrays": {
"geometries": {
"Array.XXX": [ "Geometry.XXX", "Geometry.XXX" /* ... */ ]
},
"materials": {
"Array.XXX": [ "Material.XXX", "Material.XXX" /* ... */ ]
},
"textures": {
"Array.XXX": [ "Texture.XXX", "Texture.XXX" /* ... */ ]
}
},
"geometry": "Geometry.XXX",
"materials": [
{ "(ボーン名)": "Material.XXX" }
// ...
],
"textures": [ "Texture.XXX", "Texture.XXX" /* ... */ ]
}
}
}
● 詳細な構造
{
"format_version": "1.8.0",
"render_controllers": {
"controller.render.Str": {
"rebuild_animation_matrices": "Bool",
"arrays": {
"geometries": {
"Array.XXX": [ "Geometry.XXX", "Geometry.XXX" /* ... */ ]
},
"materials": {
"Array.XXX": [ "Material.XXX", "Material.XXX" /* ... */ ]
},
"textures": {
"Array.XXX": [ "Texture.XXX", "Texture.XXX" /* ... */ ]
}
},
"geometry": "Geometry.XXX",
"part_visibility": [
{ "(ボーン名)": "Molang" }
// ...
],
"materials": [
{ "(ボーン名)": "Material.XXX" }
// ...
],
"textures": [ "Texture.XXX", "Texture.XXX" /* ... */ ],
"color": {
"r": "(Molang)",
"g": "(Molang)",
"b": "(Molang)",
"a": "(Molang)"
},
"overlay_color": {
"r": "(Molang)",
"g": "(Molang)",
"b": "(Molang)",
"a": "(Molang)"
},
"on_fire_color": {
"r": "(Molang)",
"g": "(Molang)",
"b": "(Molang)",
"a": "(Molang)"
},
"is_hurt_color": {
"r": "(Molang)",
"g": "(Molang)",
"b": "(Molang)",
"a": "(Molang)"
},
"uv_anim": {
"offset": [ "(Molang)", "(Molang)" ],
"scale": [ "(Molang)", "(Molang)" ]
},
"light_color_multiplier": "(Molang)",
"ignore_lighting": "(Bool)",
"filter_lighting": "(Bool)"
}
}
}
● 具体的な説明
"arrays"でアレイを定義します。
複数のジオメトリ、マテリアル、テクスチャを紐づける場合でなければ定義する必要はありません。
ジオメトリのアレイは
"geometries"で、マテリアルは
"materials"で、テクスチャは
"textures"で定義します。
たとえば、entity_clientで以下のように紐づけていたとします。
"textures": {
"~#M(83ffd9)state1M#~": "(テクスチャのファイルパス1)",
"~#M(83ffd9)state2M#~": "(テクスチャのファイルパス2)"
}
これでアレイを定義すると、
"textures": {
"Array.texture": [ "Texture.~#M(83ffd9)state1M#~", "Texture.~#M(83ffd9)state2M#~" ]
}
左の
"Array.XX"のXXの部分は自由に決められます。
並べる順番も自由です。
ジオメトリやマテリアルも
Texureの部分を
Geometryや
Materialに変えるだけであとは同様です。
次に、ジオメトリやテクスチャなど、どれを適用するかを決める部分です。
直接指定する場合は直接指定するだけですが、状態などによって条件分岐する場合は、アレイから値をMolangで選ぶ必要があります。
アレイの値は1番目から
Array.XX[0]、
Array.XX[1]、
Array.XX[2]......のように指定します。
[ ]の中をMolangで記述することによって条件分岐を実現します。
先ほどのテクスチャの例で
minecraft:variantコンポーネントの値によってテクスチャが変わるとすると、
"textures": [
"Array.texture[q.variant]"
]
のように指定します。このMolang式ができるだけ簡単になるようにアレイの値の順番を決めましょう。
以下、簡単に例を示します。entity_clientは以下のようになっているとします。
"materials": {
"material1": "(マテリアルID1)",
"material2": "(マテリアルID2)"
},
"textures": {
"texture1": "(テクスチャのファイルパス1)",
"texture2": "(テクスチャのファイルパス2)"
},
"geometry": {
"geo1": "(ジオメトリID1)",
"geo2": "(ジオメトリID2)"
}
・直接指定
"geometry": "Geometry.geo1",
"materials": [
{ "*": "Material.material1" }
],
"textures": [ "Texture.texture1" ]
・ジオメトリを切り替わるようにする
"arrays": {
"geometries": {
"Array.geos": [ "Geometry.geo1", "Geometry.geo2" ]
}
},
"geometry": "Array.geos[(Molang式)]"
・ボーンごとに異なるマテリアルを適用する
"materials": [
{ "(ボーン名1)": "Material.material1" },
{ "(ボーン名2)": "Material.material2" }
]
ボーン名を指定するときに、まとめて指定する書き方があります。たとえば、
"bone_head"と
"bone_body"は後半だけが違うので、
"bone_*"というようにまとめて指定できます。
・複数のテクスチャを適用する
"textures": [
"Texture.texture1",
"Texture.texture2"
]
同時にテクスチャを適用するので、当然重なります。
実用するシチュエーションとして、たとえば「顔が変わるエンティティ」を実装する場合は、
顔とそれ以外のテクスチャは別々にして、顔のテクスチャの指定にだけアレイを使うといったような感じです。
● ボーンの表示/非表示をコントロールする
"part_visibility"でボーン名とMolang式を指定します。
"part_visibility": [
{ "(ボーン名)": "Molang" }
// ...
]
● テクスチャに関わる様々な色を変更する
"overlay_color"でオーバーレイする色、
"on_fire_color"で燃えているときにオーバーレイする色、
"is_hurt_color"でダメージを受けた瞬間にオーバーレイする色を決められます。
"overlay_color": {
"r": "(Molang)",
"g": "(Molang)",
"b": "(Molang)",
"a": "(Molang)"
},
"on_fire_color": {
"r": "(Molang)",
"g": "(Molang)",
"b": "(Molang)",
"a": "(Molang)"
},
"is_hurt_color": {
"r": "(Molang)",
"g": "(Molang)",
"b": "(Molang)",
"a": "(Molang)"
}
● テクスチャをアニメーションさせる
"uv_anim"で値を設定することで、テクスチャをアニメーションさせることができます。
方式として、"テクスチャのどこを切り取るか"の長方形を動かしてアニメーションする方式になるので、
ブロックのようにパラパラ漫画式でアニメーションさせたい場合は工夫が必要です。
"uv_anim": {
"offset": [ "(Molang)", "(Molang)" ],
"scale": [ "(Molang)", "(Molang)" ]
}
"offset"でuvを指定し、
"scale"はそのuvのスケールを指定します。
● 特殊発光
"ignore_lighting"を
trueにすることで、周囲の明暗を無視する、
つまり暗さを無視して光っているようになります。
このプロパティが書いてあるRenConで紐づけたテクスチャに適用されるので、
目だけ光らせたい場合は、このRenConでは目だけのテクスチャを指定する必要があります。
Attachable
Attachableとは、防具や手に持っているアイテムなど、エンティティ本体とは別となるモデルではあるが、Animが本体に追従するような部品のことです。
そして、ホットバーや左手スロット、または防具スロットのインベントリのアイテムと連動する必要があります。
一言で正しくするのは難しいです。基本的に「防具」と「手に持っているアイテム」のモデルであると思っても大丈夫です。
● ファイルの場所
リソース
┣ manifest.json
┣ pack_icon.png
┗ attachables
┗ 〇〇.json
● 具体的な説明
JSONの書き方はほとんどentity_clientと同じです。
ただし、IDは対応させるアイテムのIDと一致させてください。