本ページは**アドオン講座#7、「コンポネ編、コンポーネントグループの付与・削除」**です。
目次や、この講座については#1の記事をご覧ください。
#コンポネ編で理解してほしいこと!
コンポネ編はこのアドオン講座の基礎編の次のページに位置し、内容としては応用編の中でも基礎寄りになります。
エンティティの追加には欠かせませんし、特に初回の#5の内容はアニコン編でもお世話になります。
基礎編を終えてとりあえず何かやってみようという方におすすめです!
コンポネ編は3ページからなり、初回#5は基礎編の延長で、書き方(記法)と仕組みの理解について、#6では重要な条件分岐の役割を担う機能について、最後#7では実践としてタグによって体力(HP)が変わるアドオンを作ってみます。
このコンポネ編では、エンティティの持つコンポーネントを自由に追加消去編集することで、エンティティに特殊な性質をもたせる、また特殊な動きをさせられるようになることを目的としています。
- (前提#3~#4)基礎編
- (#5)エンティティとは?
- (#5)
entity.json
とは? - (#5)エンティティのしくみとコンポーネント
- (#5)[実践]プレイヤーの名前を非表示にしてみよう
- (#6)フィルターとは?
- (#6)フィルターの記法
- (#7)コンポーネントを操るには?
- (#7)センサーとは?/コンポーネントグループとは?
- (#7)[実践]プレイヤーの体力をタグで変更してみよう
#コンポーネントを操るには?
今回#7はコンポネ編最終回です!
コンポネ編の目標を達成するため、さっそく材料の解説をしたいところですが、残りの材料はほぼ定型文みたいなもので、フィルターのような記法が複雑な機能ではなく、しくみの方が重要なので、先に**どういうルートで目標を達成するか!**について解説していきます。
前々回#5で実践したように、コンポネを足したり消したりすること自体は簡単です。
しかし、#5で説明した方法ではコンポネを変更するために、ファイルを書き換え、その度にワールドを再起動する必要があります。
今回#7で説明したいのは、あらかじめコンポネのセットを作っておいて、それをゲーム内で切り替える方法です。
前回#6でやった通り、フィルターではタグを検知できます。
それを利用してゲーム内からコンポネを操るのです。
流れはこうです。
- ①ゲーム内でタグの変更
- ②センサー内のトリガー、フィルターでタグを検知
- ③センサーによってイベント発動
- ④イベントでコンポーネントグループに追加
- ⑤コンポーネントグループ内のコンポネが現在のコンポネに適用される
ようは、
タグ
→センサー
→イベント
→コンポーネントグループ
→コンポネ
の順番です!
複雑すぎやろ!!!!
センサー?コンポーネントグループ?
まずはここらへんから解説していきます。
#センサーとは?
センサーはコンポネの一種です。
主に**minecraft:damage_sensor
、minecraft:environment_sensor
**の2つが使われます。
ほかにもいくつかあるようですね。
minecraft:damage_sensor
は、そのエンティティがダメージを受けたときにフィルターを動かして、検知をしてくれます1。
minecraft:environment_sensor
は、フィルターを常時トリガー(≒実行、検知)してくれるもので、トリガーの中にフィルターを書くことで、常時検知してくれます。
今回の[実践]のコーナーではminecraft:environment_sensor
を使用するので、ここではminecraft:damage_sensor
の方を例として挙げておきます。
"minecraft:damage_sensor": {
"triggers": [
{
"on_damage": {
"filters": {
"all_of": [
{ "test": "has_tag", "subject": "self", "value": "t1" },
{ "test": "has_tag", "subject": "other", "value": "t1" }
]
}
},
"deals_damage": false
},
{
"on_damage": {
"filters": {
"all_of": [
{ "test": "has_tag", "subject": "self", "value": "t2" },
{ "test": "has_tag", "subject": "other", "value": "t2" }
]
}
},
"deals_damage": false
}
]
}
minecraft:damage_sensor
ではダメージを受けたエンティティがself
、ダメージを与えたエンティティがother
として扱われます2。
この例のダメージセンサーは、「t1というタグを持っているプレイヤーはt1というタグを持っているプレイヤーに攻撃されたときダメージ無効」と「t2というタグを持っているプレイヤーはt2というタグを持っているプレイヤーに攻撃されたときダメージ無効」という効果を持っています3。
要するに同じチームに同じタグを付ければ、間違って攻撃してもダメージが入らないという、フレンドリーファイア(味方を攻撃してしまうこと)を無くすアドオンが作れます。
#イベントとは?
イベントはそれぞれのエンティティに紐づけられている固有の動作起点です。
例えば、プレイヤーではminecraft:gain_bad_omen
、minecraft:trigger_raid
など、村のレイドイベントが存在します。
他にはエンダークリスタルにminecraft:crystal_explode
というイベントがあったりします。
バニラでもエンティティが何らかの変化をするとき、裏ではイベントが発動しているということです。
<追加情報>
イベントはコマンド/event
で起こすことができるほか、コマンド/summon
でも実行できます。
例えば、エンダークリスタルの爆発だけを起こしたい場合は、
/summon minecraft:ender_crystal ~~~ minecraft:crystal_explode
を実行すれば、エンティティのスポーンと同時にイベントが発動し、すぐに爆発します。
もちろんこの文そのままでは~~~
座標が爆発するので注意。
イベントができることは
- コンポーネントグループの追加、削除
- コマンドの実行
です。
"events": {
"example_event": {
"add": {
"component_groups": [ "new_component_group" ]
},
"remove": {
"component_groups": [ "old_component_group" ]
},
"sequence": [
{
"run_command": {
"command": [
"tell @s event_ok",
"title @s actionbar event_ok"
],
"target": "self"
}
}
]
}
}
こんな感じで記述します。
コンポーネントグループnew_component_group
に入り、コンポーネントグループold_component_group
から抜け、コマンドふたつを実行するイベントです。
コマンド実行の際、アニコンやスクリプトでは必要な/
がいらないっぽいですね(なんで?)。
#コンポーネントグループとは?
コンポーネントグループはその名の通り、コンポーネントのグループ、セットです。
いくつかのコンポネを束ねておくことができます。
"component_groups": {
"グループ名": {
"コンポネ名": {
//コンポネ設定
},
"コンポネ名": {
//コンポネ設定
}
}
}
こんな感じです。
イベントによってコンポーネントグループが追加されると、デフォルトのコンポネ("components"
のカッコの中のコンポネ)に上書きで、そのコンポーネントグループの中のコンポネが適用されます。
コンポーネントグループだけではできることがないので、具体例は実践で見せましょう。
#[実践]プレイヤーの体力をタグで変更してみよう
ではさっそくコンポネ編で解説したことを活かして実践してみましょう。
###①ゲーム内でタグの変更
まずは変更するためのタグの名前を決めましょう。
今回は、
タグ | 効果 |
---|---|
なし | 体力20(♡1列) |
hp2 |
体力40(♡2列) |
hp3 |
体力60(♡3列) |
hp4 |
体力80(♡4列) |
として作っていきます。
###②③センサー内のトリガー、フィルターでタグを検知、イベント発動
minecraft:environment_sensor
は、フィルターを常時トリガーしてくれるもので、トリガーの中にフィルターを書くことで、常時検知してくれます。
先ほど手順に書いたように、センサーではタグを検知し、イベントを発動させます。
"minecraft:environment_sensor": {
"triggers": [
{
"filters": { "all_of": [ { "test": "has_tag", "subject": "self", "operator": "!=", "value": "hp2" },
{ "test": "has_tag", "subject": "self", "operator": "!=", "value": "hp3" },
{ "test": "has_tag", "subject": "self", "operator": "!=", "value": "hp4" } ] },
"event": "hp1"
},
{
"filters": { "all_of": [ { "test": "has_tag", "subject": "self", "operator": "==", "value": "hp2" } ] },
"event": "hp2"
},
{
"filters": { "all_of": [ { "test": "has_tag", "subject": "self", "operator": "==", "value": "hp3" } ] },
"event": "hp3"
},
{
"filters": { "all_of": [ { "test": "has_tag", "subject": "self", "operator": "==", "value": "hp4" } ] },
"event": "hp4"
}
]
}
タグなし→イベントhp1
実行
タグhp2
→イベントhp2
実行
タグhp3
→イベントhp3
実行
タグhp4
→イベントhp4
実行
という対応です。
###④イベントでコンポーネントグループに追加
"events": {
"hp1": {
"add": {
"component_groups": [ "hp1" ]
}
},
"hp2": {
"add": {
"component_groups": [ "hp2" ]
}
},
"hp3": {
"add": {
"component_groups": [ "hp3" ]
}
},
"hp4": {
"add": {
"component_groups": [ "hp4" ]
}
}
}
イベントから同名のコンポーネントグループに追加しています。
###⑤コンポーネントグループ内のコンポネが現在のコンポネに適用される
"component_groups": {
"hp1": {
"minecraft:health": {
"value": 20,
"max": 20
}
},
"hp2": {
"minecraft:health": {
"value": 40,
"max": 40
}
},
"hp3": {
"minecraft:health": {
"value": 60,
"max": 60
}
},
"hp4": {
"minecraft:health": {
"value": 80,
"max": 80
}
}
}
コンポーネントグループをこんな感じに書けば、体力がそれに応じて変わります。
###完成品
{
"format_version": "1.17.10",
"minecraft:entity": {
"description": {
"identifier": "minecraft:player",
"is_spawnable": false,
"is_summonable": false,
"is_experimental": false
},
"component_groups": {
"hp1": {
"minecraft:health": {
"value": 20,
"max": 20
}
},
"hp2": {
"minecraft:health": {
"value": 40,
"max": 40
}
},
"hp3": {
"minecraft:health": {
"value": 60,
"max": 60
}
},
"hp4": {
"minecraft:health": {
"value": 80,
"max": 80
}
}
},
"components": {
//省略
"minecraft:environment_sensor": {
"triggers": [
{
"filters": { "all_of": [ { "test": "has_tag", "subject": "self", "operator": "!=", "value": "hp2" },
{ "test": "has_tag", "subject": "self", "operator": "!=", "value": "hp3" },
{ "test": "has_tag", "subject": "self", "operator": "!=", "value": "hp4" } ] },
"event": "hp1"
},
{
"filters": { "all_of": [ { "test": "has_tag", "subject": "self", "operator": "==", "value": "hp2" } ] },
"event": "hp2"
},
{
"filters": { "all_of": [ { "test": "has_tag", "subject": "self", "operator": "==", "value": "hp3" } ] },
"event": "hp3"
},
{
"filters": { "all_of": [ { "test": "has_tag", "subject": "self", "operator": "==", "value": "hp4" } ] },
"event": "hp4"
}
]
}
},
"events": {
"hp1": {
"add": {
"component_groups": [ "hp1" ]
}
},
"hp2": {
"add": {
"component_groups": [ "hp2" ]
}
},
"hp3": {
"add": {
"component_groups": [ "hp3" ]
}
},
"hp4": {
"add": {
"component_groups": [ "hp4" ]
}
}
}
}
}
できた~~~!!!
#コンポネ編終了!
応用編最初にあたるコンポネ編、いかがだったでしょうか!
マインクラフトの世界に動きを与える存在、エンティティ。
それらを構成するコンポーネントという部品。
それらを操るコンポーネントグループ、センサー、フィルター、イベント。
これらをマスターしたみなさんはマインクラフトの世界に存在する動きを自由に付与することができます!
実はコンポネは私が製作してきたアドオンのほとんどに活用されています。
「[実践]プレイヤーの名前を非表示にしてみよう#5」でやった「名前の非表示」
はほぼすべてのアドオンに使われていますし、
今回#7でやったフレンドリーファイア防止のダメージセンサーは、JustBattleというPvPアドオン
に使われ、
**「[実践]プレイヤーの体力をタグで変更してみよう」でやった「体力変更」**は、雪合戦ワールド
に使われています。
このように、コンポネは様々なアドオンの基礎部分を担っています。
他にも応用編がありますが、コンポネと組み合わせることで威力を発揮できる技術もあるため、他の応用編を読むうえでも、このコンポネ編で得た知識は役に立つと思います!
ここまで読んでくれたみなさんが、このコンポーネントという技術をうまく活かして、作りたいアドオンが作れますように祈っております!
お疲れ様でした~~~~!!
↓目次#1へ↓