♬~
今日は
executeの仕組みについて
知っておこう
はじめに
この記事ではMinecraft Java Editionのexecuteコマンドの実行処理をざっくりと解説します。
クイズ
プレイヤが2人いるワールドで、スコアボードオブジェクトobjのスコアホルダholderのスコアが0の状況で、以下のコマンドを実行するとholderのスコアはどうなるでしょうか?
execute as @a if score holder obj matches 0 run scoreboard players add holder obj 1
少し考えてみてください。
答えはこちら
答えは「holderのスコアは2になる」です。「スコアが1になるとifが条件を満たさなくなるから、それ以上addはされなくて1のままになるはず」と思った方も多いのではないでしょうか。
実際、Twitterで取ってみたアンケートでも「1になる」が最多でした。
【アドカレ用のアンケート】
— こま (@komaramune) December 8, 2025
あまり考えず気楽に答えてください
マイクラJEで、プレイヤが2人いて、スコアオブジェクト"obj"のホルダ"holder"のスコアが0の時、以下のコマンドを実行するとどうなるでしょうか?
execute as @.a if score holder obj matches 0 run scoreboard players add holder obj 1
一体どうしてこうなるのかは、executeコマンドの仕組みを知ると分かります。
サブコマンドの役割
executeコマンドには様々なサブコマンド(asとかifとかstoreとかのこと)があります。
asやonで指定できる実行エンティティや、atやpositionedで指定できる実行位置などの実行情報は、コマンドの実行結果に様々な影響を及ぼすということは、ご存知かと思います。
これらのコマンドの実行情報をまとめたコマンドソースと呼ばれるデータ構造があります。
コマンドソースには実行エンティティと実行位置の他にも、実行者名、実行角度、storeの対象などの多くの実行情報が含まれますが、本記事では説明の簡略化のため、実行エンティティと実行位置の二つの実行情報にのみ注目することとします。
サブコマンドの役割は、ざっくり言うとコマンドソースを操作することなのです。
サブコマンドの処理の流れ
asやatなどのサブコマンドには、コマンドソースの実行情報を変更する役割があります。
後述しますが複数のコマンドソースが扱われる都合から、コマンドソースはリストに格納して管理されています。
1つのサブコマンドの処理ごとに、現在のリストの状態を元に、状態を更新した新しいリストが生成されます。
処理の流れは以下のようになります:
- 現在のリストからコマンドソースが取り出される
- 取り出されたコマンドソース内の実行情報がサブコマンドに従って変更される
- コマンドソースが新しいリストへ格納される
asであれば、現在のリスト内のコマンドソースから、実行エンティティの実行情報だけが変更されたコマンドソースが作られて、新しいリストに格納される訳です。
例として、以下のようなシチュエーションを考えます。
- 座標
[1,1,0]にコマンドブロックがある - 座標
[3,1,0]にプレイヤSteveがいる - コマンドブロックから以下のコマンドを実行する
execute as @a at @s run tp @s ~ ~2 ~
この、プレイヤを現在位置から2ブロック上にテレポートさせる、よくあるコマンドの仕組みを見ていきましょう。
まず、1番目のサブコマンドであるas @aの処理が行われます。
コマンドブロックからコマンドを実行すると「実行エンティティ:無し, 実行位置:[1,1,0](コマンドブロックの位置)」という実行情報のコマンドソースが1つだけ入ったリストが生成されます。
このコマンドソースにas @aの処理が行われると、実行エンティティが@aの対象となるSteveに変更されたコマンドソース「実行エンティティ:Steve, 実行位置:[1,1,0]」が作られて、新しいリストに格納されます。
続いて、2番目のサブコマンドであるat @sの処理が行われます。
リストに格納されているコマンドソースから、実行位置が[3,1,0](@s=Steveの位置)に変更されたコマンドソース「実行エンティティ:Steve, 実行位置:[3,1,0]」が作られ、新しいリストに格納されます。
最後に、runの処理が行われ、リスト内のコマンドソースの実行情報を基にコマンドtp @s ~ ~2 ~が実行されます。
@sつまり実行エンティティであるSteveが、実行位置の[3,1,0]から~ ~2 ~である[3,3,0]にtpするという処理が行われます。
コマンドの分岐
asやatなどのサブコマンドで、@aや@eなどの複数の対象を取り得るエンティティセレクタを使うと、複数の対象に対して以降のサブコマンドやコマンドを実行することができる、ということはご存じかと思います。
この挙動は、コマンドの分岐(フォーク)と呼ばれています。
先ほど説明したサブコマンドの処理の流れの中で、取り出したコマンドソースを分岐の数だけコピーすることによって分岐が起こります。
この分岐の仕組みを見ていきましょう。
例として、以下のようなシチュエーションを考えます。
- 座標
[1,1,0]にコマンドブロックがある - 座標
[3,1,0]にプレイヤSteveがいる - 座標
[5,1,0]にプレイヤAlexがいる - コマンドブロックから以下のコマンドを実行する
execute as @a at @s run tp @s ~ ~2 ~
コマンドは先程と同じですが今度はプレイヤが複数います。
そのためas @aで分岐が発生し、それぞれのプレイヤが元いた位置から3ブロック上にtpします。
まず、1番目のサブコマンドであるas @aの処理が行われます。
先程と同じく、コマンドブロックからコマンドを実行すると「実行エンティティ:無し, 実行位置:[1,1,0](コマンドブロックの位置)」という実行情報を持ったコマンドソースが1つだけ入ったリストが用意されます。
このコマンドソースにas @aの処理が行われると、今回は@aの対象となるプレイヤがSteveとAlexの2人いるため、コマンドソースが2つにコピーされます。
そのうち、片方のコマンドソースの実行エンティティがSteveに変更され、もう片方のコマンドソースの実行エンティティがAlexに変更されます。
こうして作られた2つのコマンドソース「実行エンティティ:Steve, 実行位置:[1,1,0]」と「実行エンティティ:Alex, 実行位置:[1,1,0]」が新しいリストに格納されます。
続いて、2番目のサブコマンドであるat @sの処理が行われます。
この時点でリストには2つのコマンドソースが入っていますが、2つのコマンドソースそれぞれにat @sの処理が行われます。
Steveを実行エンティティとしたコマンドソースにat @sの処理を行うと、@sはSteveを示すため、実行位置がSteveの位置に変更されたコマンドソースが作られます。
同様に、Alexを実行エンティティとしたコマンドソースからは、実行位置が[5,1,0](Alexの位置)に変更されたコマンドソースが作られます。
この2つのコマンドソースが新しいリストに格納されます。
最後に、runの処理が行われ、2つのコマンドソースそれぞれにコマンドtp @s ~ ~2 ~が実行されます。
コマンドソース「実行エンティティ:Steve, 実行位置:[3,1,0]」は、@sが示すSteveを[3,1,0]から~ ~2 ~の位置の[3,3,0]へtpするという処理が行われます。
同様に、コマンドソース「実行エンティティ:Alex, 実行位置:[5,1,0]」は、@sが示すAlexを[5,1,0]から~ ~2 ~の位置の[5,3,0]へtpするという処理が行われます。
if/unless
ifとunlessの2つのサブコマンドには、リスト内のコマンドソースを条件によって減らす役割があります。
元となるリスト内の各コマンドソースの実行情報を基に条件の判定を行い、判定が通った場合はそのコマンドソースをそのまま新しいリストに移し、通らなかった場合は破棄する、という処理が行われます。
asやatなどとは異なり、コマンドソース内の実行情報が変更されることはありません。
また、現在のリストから新しいリストにかけて、コマンドソースが減ることはありますが、分岐して増えることはありません。
リスト内のコマンドソースが0個になるとexecuteコマンドの処理は終了します。
例として、以下のようなシチュエーションを考えます。
- 座標
[1,1,0]にコマンドブロックがある - 座標
[3,0,0]に石ブロックがある - 座標
[3,1,0]にプレイヤSteveがいる - 座標
[5,1,0]にプレイヤAlexがいる - コマンドブロックから以下のコマンドを実行する
execute as @a at @s if block ~ ~-1 ~ stone run tp @s ~ ~2 ~
Steveの足元にのみ石ブロックがあります。
特定ブロックの上に立っているプレイヤだけを選ぶよくあるコマンドだと思います。
execute as @a at @sまでは先ほどと同じなので省略します。
ここからがifの処理です。
この時点でリストには2つのコマンドソースが入っていますが、2つのコマンドソースそれぞれにif block ~ ~-1 ~ stoneの処理が行われます。
[3,1,0]を実行位置としたコマンドソースにif block ~ ~-1 ~ stoneの処理が行われると、[3,1,0]を基準とした~ ~-1 ~のブロックが石ブロックであるかの判定が行われ、判定が成功するため、このコマンドソースは新しいリストに格納されます。
同様に、[5,1,0]を実行位置としたコマンドソースにif block ~ ~-1 ~ stoneの処理が行われると、[5,1,0]を基準とした~ ~-1 ~のブロックが石ブロックであるかの判定が行われ、判定が失敗するため、このコマンドソースは新しいリストに格納されません。
この結果、リスト内のコマンドソースが1つに減ります。
最後に、runの処理が行われ、実行エンティティがSteveのコマンドソース1つにのみコマンドtp @s ~ ~2 ~が実行されます。
その結果、足元に石ブロックがあるSteveだけがtpします。
クイズの解説
最初のクイズのコマンドの動作を見ていきましょう。
以下のようなコマンドでした。
execute as @a if score holder obj matches 0 run scoreboard players add holder obj 1
まず、初期状態のリストが作られます。
コマンドが分岐します。
(問題ではプレイヤ名の指定はありませんでしたが、プレイヤは仮にSteveとAlexの2人として説明します。)
そしてif score holder obj matches 0の処理が行われます。
この時点でリストには2つのコマンドソースが入っていますが、holderのスコアは0なので、両方のコマンドソースで判定が成功し、新しいリストに格納されます。
最後に、runの処理が行われ、2つのコマンドソースそれぞれにコマンドscoreboard players add holder obj 1が実行されます。
このコマンドが2回実行されるのでholderのスコアは2になる訳です。
これでお分かりでしょうか?
サブコマンドの処理は必ず左のサブコマンドから右のサブコマンドにかけて行われるのです。
そのため、ifの判定はscoreboardコマンドによってスコアの加算が行われる前に2回とも行われてしまい、2回とも判定が成功してしまうのです。
これは余談ですが、統合版のexecuteコマンドはこの処理順番の仕様が違うため、同じコマンドを実行しても結果は1になります。
間違われた方が多いのはこの影響もあるのではないかと思われます。
さいごに
以上がexecuteコマンドの実行処理のざっくり解説でした。
説明のために省略したり、単純に自分の理解不足などのせいで、間違っている部分もあるかもしれません。
間違いに気づかれた場合にはご指摘をお願いします。
この記事を読んで、皆様のコマンドの理解が少しでも深まったなら幸いです。
じゃ! ♬~
参考資料








