3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Minecraft BE Addon講座#7】コンポーネントグループの付与・削除

Last updated at Posted at 2021-11-04

本ページは**アドオン講座#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_sensorminecraft:environment_sensor**の2つが使われます。
ほかにもいくつかあるようですね。

minecraft:damage_sensorは、そのエンティティがダメージを受けたときにフィルターを動かして、検知をしてくれます1
minecraft:environment_sensorは、フィルターを常時トリガー(≒実行、検知)してくれるもので、トリガーの中にフィルターを書くことで、常時検知してくれます。

今回の[実践]のコーナーではminecraft:environment_sensorを使用するので、ここではminecraft:damage_sensorの方を例として挙げておきます。

[センサー解説]behavior/entities/player.json
"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_omenminecraft:trigger_raidなど、村のレイドイベントが存在します。
他にはエンダークリスタルにminecraft:crystal_explodeというイベントがあったりします。
バニラでもエンティティが何らかの変化をするとき、裏ではイベントが発動しているということです。

<追加情報>
イベントはコマンド/eventで起こすことができるほか、コマンド/summonでも実行できます。
例えば、エンダークリスタルの爆発だけを起こしたい場合は、
/summon minecraft:ender_crystal ~~~ minecraft:crystal_explode
を実行すれば、エンティティのスポーンと同時にイベントが発動し、すぐに爆発します。
もちろんこの文そのままでは~~~座標が爆発するので注意。

イベントができることは

  • コンポーネントグループの追加、削除
  • コマンドの実行

です。

[イベント解説]behavior/entities/[entity].json
"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から抜け、コマンドふたつを実行するイベントです。
コマンド実行の際、アニコンやスクリプトでは必要な/がいらないっぽいですね(なんで?)。

#コンポーネントグループとは?
コンポーネントグループはその名の通り、コンポーネントのグループ、セットです。
いくつかのコンポネを束ねておくことができます。

[コンポーネントグループ解説]behavior/entities/[entity].json
"component_groups": {
  "グループ名": {
    "コンポネ名": {
      //コンポネ設定
    },
    "コンポネ名": {
      //コンポネ設定
    }
  }
}

こんな感じです。
イベントによってコンポーネントグループが追加されると、デフォルトのコンポネ("components"のカッコの中のコンポネ)に上書きで、そのコンポーネントグループの中のコンポネが適用されます

コンポーネントグループだけではできることがないので、具体例は実践で見せましょう。

#[実践]プレイヤーの体力をタグで変更してみよう
ではさっそくコンポネ編で解説したことを活かして実践してみましょう。

###①ゲーム内でタグの変更
まずは変更するためのタグの名前を決めましょう。
今回は、

タグ 効果
なし 体力20(♡1列)
hp2 体力40(♡2列)
hp3 体力60(♡3列)
hp4 体力80(♡4列)

として作っていきます。

###②③センサー内のトリガー、フィルターでタグを検知、イベント発動

minecraft:environment_sensorは、フィルターを常時トリガーしてくれるもので、トリガーの中にフィルターを書くことで、常時検知してくれます。

先ほど手順に書いたように、センサーではタグを検知し、イベントを発動させます。

[environment_sensor]behavior/entities/player.json
"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実行
という対応です。

###④イベントでコンポーネントグループに追加

[event]behavior/entities/player.json
"events": {
  "hp1": {
     "add": {
        "component_groups": [ "hp1" ]
     }
  },
  "hp2": {
     "add": {
        "component_groups": [ "hp2" ]
     }
  },
  "hp3": {
     "add": {
        "component_groups": [ "hp3" ]
     }
  },
  "hp4": {
     "add": {
        "component_groups": [ "hp4" ]
     }
  }
}

イベントから同名のコンポーネントグループに追加しています。

###⑤コンポーネントグループ内のコンポネが現在のコンポネに適用される

[component_groups]behavior/entities/player.json
"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
    }
  }
}

コンポーネントグループをこんな感じに書けば、体力がそれに応じて変わります。

###完成品

behavior/entities/player.json
{
  "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へ↓

  1. on_damageがダメージが発生したとき、という意味合いを持っており、ダメージを受けるとon_damageのカッコの中が実行されるよって感じです。

  2. フィルターについて、詳しくは前回#6をご覧ください。

  3. 英単語dealは「~(攻撃)を加える」という意味です。deals_damageは「ダメージを加える」。これをfalse(=偽、無効)にすることで、攻撃を無効にしています。英単語を知っているだけでアドオンが「読める…!読めるぞ…!」になったりします。

3
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?