6
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

今日はexecuteの仕組みについて知っておこう

Last updated at Posted at 2025-12-22

♬~

image.png

今日は

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

(イメージ図)
scene1-1.png

少し考えてみてください。

答えはこちら 答えは「holderのスコアは2になる」です。

scene1-2.png

「スコアが1になるとifが条件を満たさなくなるから、それ以上addはされなくて1のままになるはず」と思った方も多いのではないでしょうか。

実際、Twitterで取ってみたアンケートでも「1になる」が最多でした。

一体どうしてこうなるのかは、executeコマンドの仕組みを知ると分かります。

サブコマンドの役割

executeコマンドには様々なサブコマンドasとかifとかstoreとかのこと)があります。
asonで指定できる実行エンティティや、atpositionedで指定できる実行位置などの実行情報は、コマンドの実行結果に様々な影響を及ぼすということは、ご存知かと思います。

これらのコマンドの実行情報をまとめたコマンドソースと呼ばれるデータ構造があります。
コマンドソースには実行エンティティ実行位置の他にも、実行者名実行角度storeの対象などの多くの実行情報が含まれますが、本記事では説明の簡略化のため、実行エンティティ実行位置の二つの実行情報にのみ注目することとします。

サブコマンドの役割は、ざっくり言うとコマンドソースを操作することなのです。

サブコマンドの処理の流れ

asatなどのサブコマンドには、コマンドソースの実行情報を変更する役割があります。

後述しますが複数のコマンドソースが扱われる都合から、コマンドソースはリストに格納して管理されています。
1つのサブコマンドの処理ごとに、現在のリストの状態を元に、状態を更新した新しいリストが生成されます。

処理の流れは以下のようになります:

  1. 現在のリストからコマンドソースが取り出される
  2. 取り出されたコマンドソース内の実行情報がサブコマンドに従って変更される
  3. コマンドソースが新しいリストへ格納される

asであれば、現在のリスト内のコマンドソースから、実行エンティティの実行情報だけが変更されたコマンドソースが作られて、新しいリストに格納される訳です。

例として、以下のようなシチュエーションを考えます。

  • 座標[1,1,0]にコマンドブロックがある
  • 座標[3,1,0]にプレイヤSteveがいる
  • コマンドブロックから以下のコマンドを実行する
    execute as @a at @s run tp @s ~ ~2 ~

scene2-1.png

この、プレイヤを現在位置から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するという処理が行われます。

scene2-2.png

コマンドの分岐

asatなどのサブコマンドで、@a@eなどの複数の対象を取り得るエンティティセレクタを使うと、複数の対象に対して以降のサブコマンドやコマンドを実行することができる、ということはご存じかと思います。

この挙動は、コマンドの分岐(フォーク)と呼ばれています。

先ほど説明したサブコマンドの処理の流れの中で、取り出したコマンドソースを分岐の数だけコピーすることによって分岐が起こります。
この分岐の仕組みを見ていきましょう。

例として、以下のようなシチュエーションを考えます。

  • 座標[1,1,0]にコマンドブロックがある
  • 座標[3,1,0]にプレイヤSteveがいる
  • 座標[5,1,0]にプレイヤAlexがいる
  • コマンドブロックから以下のコマンドを実行する
    execute as @a at @s run tp @s ~ ~2 ~

scene3-1.png

コマンドは先程と同じですが今度はプレイヤが複数います。
そのためas @aで分岐が発生し、それぞれのプレイヤが元いた位置から3ブロック上にtpします。

まず、1番目のサブコマンドであるas @aの処理が行われます。
先程と同じく、コマンドブロックからコマンドを実行すると「実行エンティティ:無し, 実行位置:[1,1,0](コマンドブロックの位置)」という実行情報を持ったコマンドソースが1つだけ入ったリストが用意されます。

このコマンドソースにas @aの処理が行われると、今回は@aの対象となるプレイヤがSteveAlexの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するという処理が行われます。

scene3-2.png

if/unless

ifunlessの2つのサブコマンドには、リスト内のコマンドソースを条件によって減らす役割があります。

元となるリスト内の各コマンドソースの実行情報を基に条件の判定を行い、判定が通った場合はそのコマンドソースをそのまま新しいリストに移し、通らなかった場合は破棄する、という処理が行われます。

asatなどとは異なり、コマンドソース内の実行情報が変更されることはありません。
また、現在のリストから新しいリストにかけて、コマンドソースが減ることはありますが、分岐して増えることはありません。
リスト内のコマンドソースが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 ~

scene4-1.png

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します。

scene4-2.png

クイズの解説

最初のクイズのコマンドの動作を見ていきましょう。

以下のようなコマンドでした。
execute as @a if score holder obj matches 0 run scoreboard players add holder obj 1

まず、初期状態のリストが作られます。

コマンドが分岐します。
(問題ではプレイヤ名の指定はありませんでしたが、プレイヤは仮にSteveAlexの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コマンドの実行処理のざっくり解説でした。

説明のために省略したり、単純に自分の理解不足などのせいで、間違っている部分もあるかもしれません。
間違いに気づかれた場合にはご指摘をお願いします。

この記事を読んで、皆様のコマンドの理解が少しでも深まったなら幸いです。



じゃ! ♬~

参考資料

6
0
0

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
6
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?