

Verse解説の続きを教えてほしいです!

初心者向けにわかりやすく解説してほしいですね!
こんなお悩みを解決します。
本記事の内容この記事を書いている僕は、クリエイター兼ブロガーです。実際に現在進行形でUEFNを学んでいます。
今回は、UIボタンの作り方のVerse(2)について解説します。
なお、1を見ていない方は先に1から進めましょう。
-
-
【UEFN】UIボタンの作り方を画像付きで徹底解説【Verse言語】
続きを見る
※以下のコードの解説文は、プログラミング初心者の主が調べながら記述したものです。
コードの解釈に誤りがありましたら恐縮ですm(_ _)m
参考程度にどうぞ。
それでは、さっそくやっていきましょう。

もくじ
- 1 UIボタンの作り方(2ページ目)│Verse解説の続き
- 1.1 (Agent : agent).SaveEnabledState(State : logic):void=の詳細
- 1.2 ShowWidget(Agent : ?agent):void=の詳細
- 1.3 HideWidget(Agent : ?agent):void=の詳細
- 1.4 (Agent : agent).SaveVisibleState(State : logic):void=の詳細
- 1.5 ButtonUI_UserOptions_Functionsクラスについて
- 1.6 ButtonUI_UserOptions_Eventsクラスについて
- 1.7 ボタンやUIの初期化、およびイベントの購読(Subscribe)
- 1.8 InitButtonFunctions()の詳細
- 1.9 ThisButtonUI.ButtonSignal_Recieve.EnableButtonOnTrigger~の詳細
- 1.10 ButtonSignal_Recieveの定義
- 1.11 OpenUI(Agent : ?agent):void=~の詳細
- 2 まとめ
UIボタンの作り方(2ページ目)│Verse解説の続き
(Agent : agent).SaveEnabledState(State : logic):void=の詳細
# ボタンが現在有効な状態を保存します
(Agent : agent).SaveEnabledState(State : logic):void=
if(CurrentState := EnabledStateMap[Agent]):
if(set EnabledStateMap[Agent] = State){}
else:
set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
クリックすると開きます。
(Agent : agent).SaveEnabledState(State : logic) : void =
# ボタンが現在有効な状態を保存します
if (CurrentState := EnabledStateMap[Agent]):
# 既にエージェントの状態が存在する場合、新しい状態で上書きします
if (set EnabledStateMap[Agent] = State){} # マップの値を更新します
else:
# エージェントの状態が存在しない場合は、新しいマップを作成し、エージェントと状態を追加します
set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State}) # マップを結合して新しいマップを作成します
上記のコードは、ボタンの現在の有効/無効の状態を保存するための関数です。
まず、関数のシグネチャを見てみましょう:
(Agent : agent).SaveEnabledState(State : logic): void =
これは、(Agent : agent)
という引数を取り、(State : logic)
という引数を受け取る SaveEnabledState
という関数であることを示しています。関数の戻り値の型は void
です。
次に、関数の本体の内容を見てみましょう:
if (CurrentState := EnabledStateMap[Agent]):
if (set EnabledStateMap[Agent] = State) {}
else:
set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
このコードの目的は、EnabledStateMap
という変数にボタンの有効/無効の状態を保存することです。
EnabledStateMap
は、Agent
(エージェント)とその状態 State
の組み合わせを保持するマップ(連想配列)です。
まず、EnabledStateMap[Agent]
という式を評価します。これは、EnabledStateMap
から Agent
をキーとして状態を取得する操作です。
もし取得した値が存在する(真である)場合は、以下のブロックに入ります。
if (set EnabledStateMap[Agent] = State) {}
この行はボタンの状態を更新するためのコードです。EnabledStateMap[Agent]
に State
の値を設定しています。
この操作によって、ボタンのステート(有効/無効)が保存されます。
次に、もしボタンの状態が存在しない場合は(偽である場合)、以下のブロックに入ります。
set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
この行は、新しいボタンのエージェントと状態の組み合わせを EnabledStateMap
に追加するためのコードです。ConcatenateMaps
関数は、既存の EnabledStateMap
と新しいマップ {Agent => State}
を結合することで、マップに新しいエントリを追加します。
この関数は、ボタンの有効/無効の状態を保存するために使用され、既存の状態を更新するか新たに追加するかを決定します。

# ボタンが現在有効な状態を保存します
(Agent : agent).SaveEnabledState(State : logic):void=
if(CurrentState := EnabledStateMap[Agent]):
if(set EnabledStateMap[Agent] = State){}
else:
set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
# 関数の宣言です。引数として Agent と State を受け取り、戻り値の型は void(何も返さない)です。
# if 文の始まりです。EnabledStateMap の中から Agent に対応する値を取得し、CurrentState という変数に代入します。
# 内部の if 文の始まりです。EnabledStateMap[Agent] に State の値を設定します。この行は空のブロックであり、処理が行われません。
# else 文の始まりです。前の if 文の条件が偽の場合に実行される処理を指定します。
# EnabledStateMap に新たなマップ {Agent => State} を追加するために、ConcatenateMaps 関数を使用してマップを結合します。結果のマップを EnabledStateMap に代入します。
まず、このコードでは EnabledStateMap
という変数に、ボタンのエージェントとその有効/無効の状態を保持したいとします。
関数 SaveEnabledState
は、引数としてエージェントの情報 Agent
と状態の情報 State
を受け取ります。
Step 1: EnabledStateMap[Agent]
にアクセス
EnabledStateMap[Agent]
は、マップEnabledStateMap
においてキーとしてAgent
を指定した値を取得します。
Step 2: if
条件式の処理
if(CurrentState := EnabledStateMap[Agent])
は、EnabledStateMap[Agent]
をCurrentState
という新しい変数に代入し、同時にその値を評価します。- もし
EnabledStateMap[Agent]
が存在する(真の値)であれば、以下のブロックの処理が実行されます。
Step 3: 2重の if
条件式の処理
if(set EnabledStateMap[Agent] = State){}
は、EnabledStateMap[Agent]
にState
の値を設定します。- この行の
set
は変数への代入を意味し、EnabledStateMap[Agent]
にState
の値を設定します。 - この行の結果は無視され、ブロック内の処理が終了します。
Step 4: else
ブロックの処理
- もし
EnabledStateMap[Agent]
が存在しない(偽の値)であれば、else
ブロックの処理が実行されます。 EnabledStateMap
に新しいマップ{Agent => State}
を追加するために、ConcatenateMaps
関数を使用します。ConcatenateMaps(EnabledStateMap, map{Agent => State})
は、既存のEnabledStateMap
と新たなマップ{Agent => State}
を組み合わせて新しいマップを作成し、EnabledStateMap
に代入します。
このコードは、ボタンのエージェントとその有効/無効の状態を保存するためのものであり、既存の状態を更新するか、新たに追加するかを決定します。
【深掘り】
if(CurrentState := EnabledStateMap[Agent]):
- この行は、
EnabledStateMap
という名前のマップ(キーと値のペアのコレクション)から、Agent
という特定のキーに関連する値を取得しています。 - 取得された値は
CurrentState
という変数に格納されます。
- この行は、
if(set EnabledStateMap[Agent] = State):
- この行は、
EnabledStateMap
マップの中にAgent
をキーとするエントリが存在する場合に実行されます。 - 条件式
set EnabledStateMap[Agent] = State
は、エントリの値をState
に設定する意味です。
- この行は、
set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
- この行は、
EnabledStateMap
マップの中にAgent
をキーとするエントリが存在しなかった場合に実行されます。 ConcatenateMaps
は、2つのマップを結合する関数です。ここでは、EnabledStateMap
と新しいマップmap{Agent => State}
を結合して、EnabledStateMap
を更新しています。
- この行は、
以上の手順により、ボタンの有効な状態を保存するためのロジックが実現されます。
EnabledStateMap
マップは、ボタンのエージェント(または識別子)をキーとし、そのボタンの有効状態を値として持っています。
【さらにわかりやすく】
このコードは、ボタンに対して有効な状態を保存するためのものです。
例えば、「ボタン1」が「有効」の状態であるか、「ボタン2」が「無効」の状態であるかなどを保存することができます。
コードの解説をしますね。
- 「エージェント」とは、特定のボタンを指します。エージェントとは、「ボタン1」「ボタン2」など、ボタンの名前のことです。
- 「有効な状態」とは、ボタンがどのような状態であるかを表します。例えば、「有効」「無効」などの状態が考えられます。
このコードでは、次のようなことが行われています。
- エージェント(ボタン)の現在の状態を保存するために、「EnabledStateMap」というデータ構造(辞書やマップのようなもの)を使用します。
EnabledStateMap
には、エージェント(ボタン)とその有効な状態(例えば、「ボタン1」が「有効」)の組み合わせが保存されます。
具体的なコードの解説です。
- もし、
EnabledStateMap
の中にエージェント(Agent)の状態(CurrentState)が保存されている場合:CurrentState := EnabledStateMap[Agent]
で、エージェントの現在の状態を取得します。
- もし、既に保存されている状態と新しい状態(State)が同じであれば、特に何もしません。
- 新しい状態を保存する必要がないからです。
- それ以外の場合(
EnabledStateMap
にエージェントの状態が保存されていない場合):EnabledStateMap
に、新しいエージェントとその状態を追加します。- これにより、新しいエージェントとその状態の組み合わせが保存されます。
これによって、エージェント(ボタン)が現在有効な状態であるかを確認し、必要な場合は状態を保存することができます。
例えば、「ボタン1」が「有効」の状態であるとします。その場合、次のようにコードを使うことができます。
Agent := "ボタン1"
State := "有効"
if(CurrentState := EnabledStateMap[Agent]):
if(set EnabledStateMap[Agent] = State){}
このコードは、すでに「ボタン1」の状態がEnabledStateMap
に保存されている場合、新しい状態("有効")と既存の状態を比較します。
同じ状態であれば何もしませんが、違う状態であれば新しい状態を保存します。
このようにして、「エージェント」とそれに対する「有効な状態」を管理することができます。
【重要】(Agent : agent).SaveEnabledState(State : logic):void=のまとめ
クリックすると開きます。
# ボタンの現在の有効状態を保存します。
(Agent : agent).SaveEnabledState(State : logic):void=
if(CurrentState := EnabledStateMap[Agent]):
if(set EnabledStateMap[Agent] = State){}
else:
set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
# 関数の宣言です。引数として Agent と State を受け取り、戻り値の型は void(何も返さない)です。
# if 文の始まりです。EnabledStateMap の中から Agent に対応する値を取得し、CurrentState という変数に代入します。
# 内部の if 文の始まりです。EnabledStateMap[Agent] に State の値を設定します。この行は空のブロックであり、処理が行われません。
# else 文の始まりです。前の if 文の条件が偽の場合に実行される処理を指定します。
# EnabledStateMap に新たなマップ {Agent => State} を追加するために、ConcatenateMaps 関数を使用してマップを結合します。結果のマップを EnabledStateMap に代入します。
順序は以下のとおり。
EnabledStateMap
はボタンエージェントの有効状態を保持するためのマップまたはデータ構造です。(Agent: agent).SaveEnabledState(State: logic): void
は、エージェントの現在の有効状態を保存するためのメソッドです。if (CurrentState := EnabledStateMap[Agent])
は、EnabledStateMap
内のAgent
キーに対応する値をCurrentState
に代入し、その値が存在するかを評価しています。- もし
CurrentState
が真であれば(値が存在していれば)、ブロック内の処理に進みます。 set EnabledStateMap[Agent] = State
は、EnabledStateMap
のAgent
キーに対応する値をState
に設定するための行です。- 最後の空の括弧
{}
は、条件式が真の場合に実行する処理がスキップされることを示しています。 - もし
CurrentState
が偽であれば(値が存在しなければ)、EnabledStateMap
に新しいマッピング{Agent => State}
を追加するための行が実行されます。
つまり、このコードは次のような動作をします。
EnabledStateMap
内で、特定のボタンエージェントAgent
の有効状態を保存します。- もし
EnabledStateMap
内にAgent
キーが既に存在していれば、その値をState
で上書きします。 - もし
EnabledStateMap
内にAgent
キーが存在しなければ、新しいマッピング{Agent => State}
をEnabledStateMap
に追加します。
if(set EnabledStateMap[Agent] = State){}でset CurrentState を使わない理由
クリックすると開きます。
# ボタンが現在有効な状態を保存します
(Agent : agent).SaveEnabledState(State : logic):void=
if(CurrentState := EnabledStateMap[Agent]):
if(set EnabledStateMap[Agent] = State){}
else:
set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
このコードの目的は、ボタンの現在の有効状態をEnabledStateMapというマップデータ構造に保存することです。
以下、コードの該当部分の解説です。
if(CurrentState := EnabledStateMap[Agent]):
この行では、EnabledStateMapからAgentというキーに関連する値を取得し、CurrentStateという変数に格納しています。
次の行で、ボタンの有効状態の更新が行われます。
if(set EnabledStateMap[Agent] = State){}
この行は、EnabledStateMap[Agent]
にState
という値を設定するための代入文です。
なぜCurrentState
ではなく、EnabledStateMap[Agent]
に値を設定するのかという点を具体的に説明します。
CurrentState
はEnabledStateMap[Agent]
の値を一時的に参照するための変数です。つまり、CurrentState
に値を設定しても、それはEnabledStateMap[Agent]
そのものには影響を与えません。
そのため、ボタンの有効状態を正確に更新するには、EnabledStateMap[Agent]
に直接値を代入する必要があります。
具体的に言うと、もしCurrentState
に値を代入しても、それはEnabledStateMap内のAgentキーに影響を与えません。
CurrentState
はEnabledStateMapの値の一時的なコピーであり、そのコピーの値を変更しても元のマップには反映されません。
そのため、EnabledStateMapのAgentキーの値を更新するには、set EnabledStateMap[Agent] = State
という形式で直接代入する必要があります。
要するに、このコードではCurrentState
を使ってEnabledStateMap[Agent]への参照を一時的に短縮していますが、実際の値の更新はEnabledStateMap[Agent]に対して行われます。
つまり、set CurrentState
ではなく、set EnabledStateMap[Agent]
が必要なのです。
このようにして、ボタンの有効状態を正確にマップに保存しているわけです。
CurrentStateを一時的に変数として格納する理由CurrentStateに代入する理由は、ボタンの現在の有効状態を保持するためです。
このコードでは、EnabledStateMapというマップを使用して、各エージェント(ボタン)の有効状態を管理しています。EnabledStateMapはエージェントをキーとし、そのエージェントの有効状態を値として持つマップです。
CurrentState := EnabledStateMap[Agent] という行は、EnabledStateMapから指定されたエージェントの値をCurrentStateに代入しています。これにより、指定されたエージェントの現在の有効状態をCurrentStateとして保持し、後の処理で使用することができます。
その後、if文でCurrentStateが評価されます。もしCurrentStateが真(有効な状態)であれば、EnabledStateMapの値がStateと等しくなるように設定します。これにより、既存のエージェントの有効状態を更新することができます。
一方、CurrentStateが偽(無効な状態)であれば、EnabledStateMapに新たなエージェントとその有効状態を追加します。これにより、新しいボタンの有効状態を保存します。
つまり、CurrentStateを使用することで、既存のエージェントの有効状態を更新したり、新しいエージェントの有効状態を保存したりすることができます。

if(set EnabledStateMap[Agent] = State){}についての詳細
クリックすると開きます。
# ボタンが現在有効な状態を保存します
(Agent : agent).SaveEnabledState(State : logic):void=
if(CurrentState := EnabledStateMap[Agent]):
if(set EnabledStateMap[Agent] = State){}
else:
set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
if(set EnabledStateMap[Agent] = State){}という行は、EnabledStateMapのエージェントに対する有効状態をStateに設定するためのコードです。
EnabledStateMapはマップであり、エージェント(ボタン)をキーとして、そのエージェントの有効状態を値として保持しています。
この行の目的は、指定されたエージェントの有効状態をStateに更新することです。
詳細は以下のとおり。
EnabledStateMap[Agent]
:- EnabledStateMap内の指定されたエージェントの現在の有効状態を取得します。
CurrentState := EnabledStateMap[Agent]
:- CurrentStateに現在の有効状態を代入します。
if (set EnabledStateMap[Agent] = State) {}
:- この行は、EnabledStateMap内の指定されたエージェントの有効状態をStateに設定します。
set EnabledStateMap[Agent] = State
: EnabledStateMap内の指定されたエージェントの有効状態をStateに更新します。if (set EnabledStateMap[Agent] = State) {}
: この行は空のブロックです。実際のコードは存在しません。- ただし、この行を使用することで、エージェントの有効状態がStateに設定されるように制御フローを設定できます。
このコードの目的は、指定されたエージェントの有効状態をStateに変更することです。もし指定されたエージェントが既にEnabledStateMap内に存在する場合、そのエージェントの有効状態をStateに更新します。
指定されたエージェントがEnabledStateMap内に存在しない場合は、新しいエージェントとその有効状態をEnabledStateMapに追加します。
したがって、このコードはエージェントの有効状態を管理し、変更するためのものであると言えます。

EnabledStateMap[Agent]
:- これは、
EnabledStateMap
から指定されたエージェント(ボタン)の現在の有効状態を取得します。
- これは、
set EnabledStateMap[Agent] = State
:- この行は、指定されたエージェントの有効状態を新しい
State
の値に設定します。 set
:「set」というキーワードは、変数やマップのエントリに新しい値を割り当てるために使用されます。EnabledStateMap[Agent]
:EnabledStateMap
内の指定されたエージェントのエントリにアクセスします。=
:等号は代入演算子であり、等号の右側の値を左側の変数やマップエントリに代入します。State
:エージェントの有効状態を設定する新しい値です。
- この行は、指定されたエージェントの有効状態を新しい
if (set EnabledStateMap[Agent] = State) {}
:この行は、条件付きでコードのブロックを実行するためのif文を使っています。if
:「if」というキーワードは、条件に基づいてコードのブロックを条件付きで実行するために使用されます。set EnabledStateMap[Agent] = State
:これはif文の条件部分です。EnabledStateMap
内の指定されたエージェントの有効状態が新しいState
の値に設定されます。
{}
:これは、何も含まない空のコードブロックを表します。- ここでは特定のコードが実行されないことを示すプレースホルダとして使用されます。
要約すると、「if (set EnabledStateMap[Agent] = State) {}」の行では、EnabledStateMap
内で指定されたエージェントの有効状態を新しいState
の値に更新します。
if文自体は追加のアクションを実行しません。条件が真の場合に特定のコードを実行するのではなく、単に代入が行われることを確認します。
Stateの役割Stateは、状態や状況を表すために使用される変数や値のことです。
これを身近なものに例えると、以下のような状況を考えてみましょう。
例えば、あなたが部屋にいるとします。その部屋には明るさを制御するスイッチがあります。
このスイッチには2つの状態があります。
- State 1(スイッチがON):
- 部屋が明るい状態
- State 2(スイッチがOFF):
- 部屋が暗い状態
この場合、Stateは部屋の明るさの状態を表しています。プログラミングの文脈では、Stateは変数や値を使って特定の状態を示すために使用されます。
したがって、set EnabledStateMap[Agent] = State
という行は、指定されたエージェント(例えばボタン)の有効状態を新しいStateの値に設定するという意味です。
具体的には、そのエージェントがアクティブ(有効)な状態なのか、非アクティブ(無効)な状態なのかを表すために使われます。
実際のコードでは、State変数にはオンやオフなどの具体的な値が代入され、それに基づいてエージェントの有効状態が制御されます。
このような制御は、例えばGUIアプリケーションでボタンのクリック可能な状態を制御する場合や、デバイスのオン・オフ状態を管理する場合によく使用されます。
上記の例では、Stateが部屋の明るさを表していましたが、他のシナリオではStateは異なる意味を持つこともあります。
重要なのは、Stateが特定の状態を表し、その値に基づいてプログラムが制御されることです。
マップの要素を追加、変更することについて
クリックすると開きます。
マップは、キーと値のペアを格納するデータ構造です。マップに要素を追加したり、既存の要素を変更したりする方法を以下に解説します。
以下の例を使って解説します:
var ExampleMap: [string]int = map{"a" => 1, "b" => 2, "c" => 3}
ここで、ExampleMap
という名前のマップを作成し、既存のキーと値を設定しています。
- 既存の要素を修正する例:
if (set ExampleMap["b"] = 3, ValueOfB := ExampleMap["b"]):
Print("Updated key b in ExampleMap to {ValueOfB}")
上記のコードでは、ExampleMap
のキー "b"
の値を 3
に変更しています。set
の結果、要素の変更が成功した場合(既存のキー "b"
が存在する場合)、指定したコードが実行されます。
ValueOfB
という変数に、変更後の要素の新しい値が格納されます。
この例では、「key b in ExampleMapを3に更新しました」と表示されることになります。
- 新しい要素を追加する例:
if (set ExampleMap["d"] = 4, ValueOfD := ExampleMap["d"]):
Print("Added a new key-value pair to ExampleMap with value {ValueOfD}")
上記のコードでは、ExampleMap
に新しいキー "d"
と値 4
のペアを追加しています。set
の結果、要素の追加が成功した場合(既存のキー "d"
が存在しない場合)、指定したコードが実行されます。
ValueOfD
という変数に、追加された要素の値が格納されます。
この例では、「ExampleMapに新しいキーと値が追加されました。値は4です」と表示されることになります。
上記の例では、if
ステートメントで set
を使用して要素の追加や変更を行っています。
これは、「失敗コンテキスト」で実行される制御フローです。要素の追加や変更が成功した場合にのみ指定されたコードが実行されます。
要するに、上記のコードは、「マップの特定のキーの値を変更するか、新しいキーと値のペアをマップに追加する」という動作を行っています。
このようにマップを操作することで、プログラム内でデータの管理や更新ができます。

set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})の詳細
クリックすると開きます。
# ボタンが現在有効な状態を保存します
(Agent : agent).SaveEnabledState(State : logic):void=
if(CurrentState := EnabledStateMap[Agent]):
if(set EnabledStateMap[Agent] = State){}
else:
set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
は、EnabledStateMap
という辞書またはマップに新しいエントリを追加するための処理です。
詳細は以下のとおり。
EnabledStateMap
:- これは現在のエージェントの有効な状態を保持している辞書またはマップです。
- キーはエージェントを表し、値はそのエージェントの有効な状態(
true
またはfalse
)を表します。
ConcatenateMaps(EnabledStateMap, map{Agent => State})
:- これは2つの辞書またはマップを結合するための操作です。
- 具体的には、
map{Agent => State}
という新しいエントリをEnabledStateMap
に追加することを意味します。 map{Agent => State}
:これは1つの要素を持つ新しい辞書またはマップです。- キーは
Agent
であり、値はState
です。この新しいエントリは、新しいエージェントとその有効な状態を表します。 ConcatenateMaps(EnabledStateMap, map{Agent => State})
:- この操作は、既存の
EnabledStateMap
とmap{Agent => State}
を結合して新しい辞書またはマップを作成します。 - これにより、
EnabledStateMap
に新しいエージェントとその有効な状態が追加されます。
- この操作は、既存の
set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
:- この処理は、変数
EnabledStateMap
に新しいエントリを追加した結果を代入する操作です。 - 新しいエントリは
map{Agent => State}
で表され、既存のエントリと結合された辞書またはマップが作成されます。 - これにより、
EnabledStateMap
は更新され、新しいエージェントの有効な状態が追加されます。
- この処理は、変数
つまり、set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
は、EnabledStateMap
に新しいエージェントとその有効な状態を追加するための操作です。
この操作により、プログラムは辞書またはマップに新しいエントリを追加し、現在のエージェントの有効な状態を保存することができます。

set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
具体的な論理は以下のとおりです。
- もし
EnabledStateMap
にAgent
というキーのエントリがすでに存在する場合: EnabledStateMap[Agent]
を評価し、その結果をCurrentState
という変数に代入します。- もし
CurrentState
が存在する(true
またはfalse
)場合:EnabledStateMap[Agent]
の値をState
の値で更新します。
- 否正の場合(すなわち、
CurrentState
が存在しない場合):EnabledStateMap
とmap{Agent => State}
を結合して新しい辞書またはマップを作成します。- 作成された新しい辞書またはマップを
EnabledStateMap
に代入し、既存の辞書またはマップを更新します。
つまり、コードのset EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
は、既存のEnabledStateMap
と新しいエージェントとその有効な状態を結合して更新する処理を行います。
もし既存のエージェントが存在する場合は、その有効な状態を更新します。もし既存のエージェントが存在しない場合は、新しいエージェントとその有効な状態を追加します。
まとめるとset EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
は、次の作業を行います。
EnabledStateMap
は、エージェント(Agent)とその状態(State)のマッピング(関連付け)を保持する変数(またはデータ構造)です。map{Agent => State}
は、新しいエージェントとその有効な状態を表すマッピングです。- 具体的なエージェントと状態の値がこのマップに含まれます。
ConcatenateMaps
は、2つのマップを結合する関数(または操作)です。- 既存の
EnabledStateMap
と新しいマップを結合して、更新されたマップを作成します。
- 既存の
具体的な手順は以下のとおり。
- 既存の
EnabledStateMap
から既存のエージェントと状態のマッピングを取得します。 - 新しいマップである
map{Agent => State}
に新しいエージェントと状態のマッピングが含まれている場合、それを取得します。 - 既存のマップと新しいマップを結合し、更新されたマップを作成します。
- 結果として、エージェントとその有効な状態の最新のマッピングが得られます。
- 最後に、変数
EnabledStateMap
に更新されたマップを代入して、元の変数の内容を更新します。
このようにして、EnabledStateMap
は既存のエージェントと状態の情報を保持しながら、新しいエージェントと状態の情報を結合して更新されます。
【例】
連絡先リスト(Address Book)には、友人や家族などの人々の名前と電話番号が保存されています。これをEnabledStateMap
としましょう。
- 最初の状態では、連絡先リスト(
EnabledStateMap
)にはいくつかの友人や家族の名前と電話番号が既に登録されています。 - 新たな友人を追加する必要がある場合、新しい友人の名前と電話番号を
map{Agent => State}
として作成します。- ここでは、友人の名前をキー(Agent)とし、電話番号を値(State)とします。
ConcatenateMaps
関数を使用して、既存の連絡先リスト(EnabledStateMap
)と新しい友人のマッピングを結合します。- これによって、連絡先リストは更新され、新しい友人の情報が追加されます。
- 更新された連絡先リスト(
EnabledStateMap
)には、既存の友人や家族の名前と電話番号に加えて、新しい友人の名前と電話番号が含まれています。- これにより、連絡先リストが最新の情報を保持しつつ、新しい情報が追加されます。
例えば、以下のような連絡先リストがあったとします。
EnabledStateMap:
{
"John": "555-1234",
"Alice": "555-5678"
}
新しい友人として"Bob"の名前と"555-7890"の電話番号を追加する場合、次のようになります。
map{Agent => State}:
{
"Bob": "555-7890"
}
EnabledStateMap
とmap{Agent => State}
を結合すると、更新された連絡先リストが得られます。
EnabledStateMap(更新後):
{
"John": "555-1234",
"Alice": "555-5678",
"Bob": "555-7890"
}
これにより、既存の連絡先リストに新しい友人の情報を結合し、連絡先リストを最新の状態に保ちつつ更新することができます。

マップ(連想配列)を作成する式map{Agent => State}について
クリックすると開きます。
map{Agent => State}
は、AgentとStateのペアを要素とするマップ(連想配列)を作成する式です。
具体的には、Agent
をキーとし、State
を値とする要素が1つ入ったマップを作成します。
例えば、Agent
が"John"でState
が"active"だった場合、マップは以下のようになります:
{
"John": "active"
}
マップは、キーと値のペアを利用して様々なデータの関連付けを行うために使用されます。
上記の式では、AgentとStateの関連を記録するために使われています。
=>とは=>
は、計算式で特定の要素(Agent)を対応する値(State)にマッピングする際に使用される記号です。
この記号は一般的に、キーと値を結びつける関係や対応を表すために使われます。
具体的には、Agent => State
は、「Agent」をキーとし、「State」を値とするマッピング(関連付け)を示しています。
このマッピングは、マップ(連想配列)や関数などのデータ構造内で使われます。
例えば、Agent
が"John"でState
が"active"だった場合、Agent => State
は「John」をキーとし、「active」を値とするマッピングを表します。
以下のように表現されます:
Agent => State
= "John" => "active"
このマッピングは、Agent("John")とそれに対応するState("active")を関連付ける役割を果たします。
他のAgentとStateの対応関係を表現するためにも、同様のマッピングを追加することができます。
たとえば、Agentが「ボタンA」で、Stateが「有効」とすると、Agent => State は「ボタンAというキーに対して、有効という値を関連付ける」という意味になります。
このようなマッピングを使用することで、特定のキー(エージェント)に対応する値(有効状態)を取得したり、更新したりすることができます。

「要素」と「値」の違い
クリックすると開きます。
要素(Element)は、データ構造内の個々の単位であり、一つの単位として扱われます。
要素は、データ構造内で位置を持ち、特定の操作や処理の対象となります。
値(Value)は、個々の要素が持つ具体的なデータそのものを表します。
値は、要素に関連付けられたデータの実際の値であり、そのデータ構造自体の特定の位置ではなく、単一のデータ単位として扱われます。
【例】
考えてみてください、あなたが果物のバスケットを持っているとします。
このバスケットは、複数の要素(果物)を持つことができます。それぞれの果物は、バスケット内で個別の位置に配置されます。
- 要素(Element):
- バスケット内の各々の果物(りんご、バナナ、オレンジなど)
- 値(Value):
- それぞれの果物の具体的な種類や属性(りんご、バナナ)
バスケットが以下のような果物を保持しているとします。
[りんご, バナナ, オレンジ]
このバスケットは3つの要素(果物)を持っています。
それぞれの要素(果物)はバスケット内の位置に関連付けられています。
例えば、バスケット内の最初の要素(インデックス0)は「りんご」、次の要素(インデックス1)は「バナナ」、そして最後の要素(インデックス2)は「オレンジ」となります。
それぞれの要素は特定の値(果物の具体的な種類や属性)を持っています。
例えば、インデックス1の要素は「バナナ」という値を持ちます。
要素と値の関係をこの例に当てはめると、要素は果物が置かれた特定の位置(バスケット内)を表し、値はその要素が保持している実際の果物の種類や属性を表すといえます。
set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})はEnabledStateMapが空である場合に実行される
クリックすると開きます。
# ボタンが現在有効な状態を保存します
(Agent : agent).SaveEnabledState(State : logic):void=
if(CurrentState := EnabledStateMap[Agent]):
if(set EnabledStateMap[Agent] = State){}
else:
set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
は、EnabledStateMap
が空である場合に実行されます。
つまり、EnabledStateMap
にエージェントの状態がまだ保存されていない場合に使用されることが想定されています。
このコードは、「EnabledStateMap」が空の場合に、新しいエージェントとその状態を追加して初期化するためのものです。
ConcatenateMaps
は、既存のEnabledStateMap
と新しいマップ(map{Agent => State}
)を結合し、最終的なEnabledStateMap
を作成します。
したがって、EnabledStateMap
が空であるか、まだエージェントの状態が保存されていない場合に、新しいエージェントとその状態を追加して初期化するためにこのコードが実行されます。
既存の EnabledStateMap
も結合する必要がある理由は、新しいエージェントとその状態を保存するためです。
例えば、EnabledStateMap
に「ボタン1」の状態が保存されているとします。このとき、新しいエージェント「ボタン2」の状態を保存したい場合は、EnabledStateMap
に新しいエージェントとその状態を追加する必要があります。
しかし、EnabledStateMap
に新しいエージェントとその状態を追加すると、既存のエージェントとその状態が削除されてしまいます。
そのため、ConcatenateMaps
関数を使用して、既存の EnabledStateMap
と新しいマップを結合し、最終的な EnabledStateMap
を作成する必要があります。
プログラミング初心者向けにわかりやすく解説すると、ConcatenateMaps
関数は、2つのマップを結合し、新しいマップを作成する関数です。
例えば、EnabledStateMap
に「ボタン1」の状態が保存されているとします。このとき、新しいマップ map{Agent => State}
に「ボタン2」の状態が保存されているとします。
このとき、ConcatenateMaps
関数を使用して、EnabledStateMap
と map{Agent => State}
を結合すると、新しいマップ map{Agent => State}
が作成されます。
この新しいマップ map{Agent => State}
には、「ボタン1」の状態と「ボタン2」の状態が保存されます。
このようにして、既存の EnabledStateMap
と新しいマップを結合することで、新しいエージェントとその状態を保存することができます。
EnabledStateMap[Agent]をCurrentState に代入する必要性&条件式を使う理由
クリックすると開きます。
# ボタンが現在有効な状態を保存します
(Agent : agent).SaveEnabledState(State : logic):void=
if(CurrentState := EnabledStateMap[Agent]):
if(set EnabledStateMap[Agent] = State){}
else:
set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
EnabledStateMap[Agent]
をCurrentState
に代入するのは、EnabledStateMap
内の特定のエージェントの現在の状態を変数として保持するためです。これにより、現在の状態を後続の処理で使うことができます。
条件式を使用する理由は、EnabledStateMap
に指定したエージェントの状態が既に存在するかどうかを確認するためです。条件式EnabledStateMap[Agent]
は、エージェントのキーを使用してEnabledStateMap
内の状態を取得し、その結果を評価します。
条件式の評価結果がtrue
である場合、すでにエージェントの状態がEnabledStateMap
に存在していることを意味します。その場合、後続のif
文で状態の更新が行われます。
一方、条件式の評価結果がfalse
である場合、エージェントの状態がまだEnabledStateMap
に存在しないことを意味します。
この場合、新しいエージェントと状態の組み合わせをEnabledStateMap
に追加する必要があります。これは後続のelse
節で行われます。
要約すると、条件式を使用して既存の状態の有無を確認し、EnabledStateMap
内のエージェントの状態を適切に更新または追加することが目的です。

# ボタンが現在有効な状態を保存します
(Agent : agent).SaveEnabledState(State : logic):void=
if(CurrentState := EnabledStateMap[Agent]):
if(set EnabledStateMap[Agent] = State){}
else:
set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
EnabledStateMap[Agent]
をCurrentState
に代入しない場合、後続のコードで現在の状態を使用することができません。
CurrentState
という変数が存在しないため、その後の処理で現在の状態を参照することはできません。
これにより、以下のような問題が発生する可能性があります。
- 状態の更新が正しく行われない:
- 現在の状態を取得せずに更新処理を行うと、既存の状態が正確に反映されない可能性があります。
- 代入を行わずに直接
EnabledStateMap[Agent]
を更新したり追加したりすると、更新前の古い状態や追加前の存在しない状態に基づいて処理が行われる可能性があります。
- 不正な状態のチェックができない:
- 代入を行わずに条件式を使用せずに新しいエージェントと状態を追加すると、既に存在する状態の上書きや重複追加が発生する可能性があります。
- 条件式を使用することにより、既存の状態が存在する場合にのみ更新が行われるため、不正な状態のチェックが行えます。
したがって、EnabledStateMap[Agent]
をCurrentState
に代入することによって、現在の状態を変数として保持し、後続の処理で使用することが重要です。
これにより、正確な状態の更新や不正な状態のチェックが可能になります。

これ代入しないと現在の状態が新しい状態に変わり、現在の状態をもつ変数がなくなってしまうということですよね?
おっしゃる通りです。
EnabledStateMap[Agent]
をCurrentState
に代入しない場合、現在の状態は新しい状態に変更されてしまいます。
そして、その変数を持っていたり後続の処理で使用することができなくなってしまいますね。


これによって、現在の状態を追跡したり、適切な判断や処理を行ったりすることができるわけですね🌸
# ボタンが現在有効な状態を保存します
(Agent : agent).SaveEnabledState(State : logic):void=
if(CurrentState := EnabledStateMap[Agent]):
if(set EnabledStateMap[Agent] = State){}
else:
set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
条件式を使用せずにEnabledStateMap[Agent]
の状態を取得しようとすると、以下のようなエラーが発生する可能性があります。
- キーが存在しない場合のエラー:
EnabledStateMap
内に指定したエージェントのキーが存在しない場合、そのキーでのアクセスは無効となります。- これにより、プログラムはキーが存在しないことを示すエラーをスローするか、
null
や未定義の値を返すか、その他のエラー処理を行うかもしれません。
- エージェントの状態が未定義の場合のエラー:
- 条件式を使用せずに状態を取得した場合、エージェントの状態が定義されていない可能性があります。
- そのため、状態が未定義のままであれば、結果としてエラーが発生するか、意図しない結果が返される可能性があります。
条件式を使用することによって、エージェントの状態が存在するかどうかを確認することができます。これにより、エラーを避けることができます。
条件式を使用しない場合、エージェントのキーの有無や状態の定義の有無を確認せずにアクセスするため、エラーが発生する可能性が高まります。
ConcatenateMaps関数を使用してマップを結合する理由
クリックすると開きます。
ConcatenateMaps
関数を使用してマップを結合する理由は以下のとおりです。
- 再利用性:
ConcatenateMaps
関数を使用することで、同じ結合操作を他の部分でも利用できます。- 結合を直接行う代わりに、関数を使用することでコードの再利用が促進されます。
- 同じ結合処理を複数の場所で行う必要がある場合に便利です。
- 抽象化と簡潔さ:
ConcatenateMaps
関数を使用することで、結合操作を単一の関数呼び出しにまとめることができます。- これにより、コードの可読性が向上し、結合の詳細な実装を意識しなくても済みます。
- 関数呼び出しによって、コードをより抽象化し、短く簡潔に表現することができます。
- 保守性と拡張性:
ConcatenateMaps
関数を使用することで、将来の変更や拡張がしやすくなります。- 新しいエージェントと状態を追加する場合や、他のマップの結合操作を行う場合にも、既存の関数を利用することができます。
- これにより、コードの保守性が向上し、将来の変更に対応しやすくなります。
以上の理由から、ConcatenateMaps
関数を使用してマップを結合しているのです。
直接結合を行う方法も可能ですが、関数を介して結合を行うことで、可読性、保守性、拡張性などの観点でメリットが得られるからです。

ConcatenateMaps
関数を使用せずにマップを結合する場合には、次のような問題が発生する可能性があります。
- 情報の上書き:
- マップを直接操作して結合を行う場合、キーが重複すると後の値で上書きされる可能性があります。
- つまり、新しいマップのキーが既存のマップと重複している場合、既存のキーと関連付けられていた値が失われる可能性があります。
- これは意図しないデータの上書きや情報の損失につながります。
- エラーの発生:
- マップを直接操作すると、キーの重複や無効な操作によるエラーが発生する可能性があります。
- 例えば、適切なエラーチェックや制約の確認が行われていない場合、誤ったキー操作が行われる可能性があります。
- これによって意図せぬ結果やプログラムのクラッシュが発生するかもしれません。
- コードの可読性と保守性の低下:
- マップを直接操作して結合を行うと、コードの可読性が低下し、保守性が損なわれる場合があります。
- 結合操作が複数の場所で行われる場合、同じ結合ロジックを繰り返し記述する必要があり、重複やミスのリスクが高まります。
- また、マップ操作の詳細が直接コードに現れるため、理解や変更が困難になる場合があります。
- 再利用性の低下:
- マップの結合が複数の場所で必要な場合、同じ結合処理を再利用することが難しくなります。
- 結合操作が直接埋め込まれている場合、各所で結合を手動で行う必要があります。
- これにより、コードの重複が生じ、保守性や変更への対応性が低下します。
これらの問題を回避するために、ConcatenateMaps
関数のような抽象化された方法を使用することが推奨されます。
関数を介してマップを結合することで、上記の問題を最小限に抑え、可読性、保守性、再利用性を向上させることができます。
保守性を高めるには、できる限り値を変更しないことが望まれますね。

if(set EnabledStateMap[Agent] = State){}がスキップされる条件
クリックすると開きます。
# ボタンが現在有効な状態を保存します
(Agent : agent).SaveEnabledState(State : logic):void=
if(CurrentState「現在の状態」) := EnabledStateMap「エージェントの有効状態を保存する辞書」[Agent]):
# エージェントの有効状態の更新
if(set EnabledStateMap[Agent] = State){}
else:
set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
# エージェント(Agent)の有効状態を保存するための関数 "SaveEnabledState" を定義します。
この関数は、エージェントと状態の情報を受け取り、特定の手順で処理を行います。
# 最初に、現在のエージェントの状態を変数 "CurrentState" に取得します。
これは、EnabledStateMap(エージェントの有効状態を保存する辞書)からエージェントに関連付けられた値を取得することで行われます。
# 次に、取得した状態 "CurrentState" を評価し、真偽値(真か偽か)を確認します。
# もし "CurrentState" が真(すでにエージェントの有効状態が存在する)である場合、さらに条件分岐が行われます。
# "EnabledStateMap[Agent]" に新しい状態 "State" を代入するような文 "set EnabledStateMap[Agent] = State" を実行します。
これにより、エージェントの有効状態が更新されます。
ただし、この行はスキップされることもあります。
スキップされる場合は、すでにエージェントの状態が要求された状態と一致している場合です。
# もし "CurrentState" が偽(エージェントの有効状態が存在しない)である場合、他の条件分岐が行われます。
# 新しいエージェント(Agent)と状態(State)のペアを作成し、EnabledStateMap(エージェントの有効状態を保存する辞書)に追加します。
これは、既存の EnabledStateMap と新しいペアを結合する "ConcatenateMaps" 関数を使用して行われます。
「if(set EnabledStateMap[Agent] = State){}」の部分は、指定したボタン(Agent)の有効状態を変更するための行です。
この行がスキップされる条件は、以下の2つ。
- もともとのボタンの有効状態(CurrentState)が、新しい有効状態(State)と同じである場合:
- すでにボタンの状態が望んだ状態(State)と一致している場合に、この行はスキップされます。
- つまり、既にボタンの状態が正確に設定されている場合、同じ値を再度保存する必要がないためです。
- ボタン(Agent)がまだ有効状態(EnabledStateMap)に含まれていない場合:
- もし指定したボタンが EnabledStateMap に存在しない場合、新しいエージェント(ボタン)を EnabledStateMap に追加する必要があります。
- そのため、この行はスキップされず、新しいエージェントと有効状態(AgentとState)のペアを EnabledStateMap に追加することになります。
要するに、"if(set EnabledStateMap[Agent] = State){}" 行は、既に正しい状態である場合やエージェントが未登録の場合に、スキップされることを意味します。
どんな状況かによって行動が変わるので、プログラムは状態に応じて処理をスキップする場合もあります。

スキップしない場合は、両者の値が等しくない。つまり、現在の状態と新しい状態の値に違いがある場合に実行されるということですか?
はい、おっしゃる通りです。
指定した行がスキップされない場合は、次の条件が成り立つときです:
現在の状態(CurrentState)と新しい状態(State)の値が等しくない場合に、set EnabledStateMap[Agent] = State の行が実行されます。
要するに、エージェントの現在の状態と新しい状態が異なる場合にのみ、エージェントの状態を更新するための行が実行されます。


エージェントの状態とは、有効状態であるか否かのことですか?
はい、正確です。
エージェントの状態は、ボタンが有効(Enabled)または無効(Disabled)であるかを示す、いわば有効状態のことを指しています。
保存されたエージェントの状態(EnabledStateMap)は、各エージェントに関連付けられた値として保持され、ボタンの有効状態を示します。
関数 "SaveEnabledState" は、現在のエージェントの状態(EnabledStateMap内の値)と新しい状態(State)を比較し、異なる場合にのみ状態を更新します。
つまり、エージェントの有効状態が変更された場合にのみ、状態の更新が行われます。

if(set EnabledStateMap[Agent] = State){}がスキップされる条件:エージェントの有効状態の更新の詳細
クリックすると開きます。
エージェントの有効状態の更新は、以下の行で行われます。
set EnabledStateMap[Agent] = State
この行では、辞書 EnabledStateMap
のキーにエージェント Agent
を使用して、対応する値を State
で更新しています。
つまり、エージェントの状態が新しい値で置き換えられます。

if(set EnabledStateMap[Agent] = State){}がスキップされる条件:else ブロックの条件
クリックすると開きます。
else
ブロックは、以下の条件を満たす場合に実行されます:
- エージェントの現在の状態である
CurrentState
が存在せず、新しい状態を追加する必要がある場合。
具体的には、以下の部分で else
ブロックが使用されています:
else:
set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
この部分では、EnabledStateMap
のキーとしてエージェント Agent
、値として新しい状態 State
のペアを作成し、EnabledStateMap
に追加しています。
つまり、エージェントの状態が記録されたマップに新しいエントリが追加されます。
このように、else
ブロックは現在のエージェントの状態が存在しない場合の処理フローを担当し、新しい状態を追加するための操作を実行します。

set EnabledStateMap[Agent] = Stateの論理
クリックすると開きます。
set EnabledStateMap[Agent] = State
は、辞書 (マップ) である EnabledStateMap
のキー Agent
に対して、新しい値 State
を設定する操作を行う計算式です。
具体的には、EnabledStateMap
のキー Agent
の値が State
で上書きされます。この操作は、EnabledStateMap
内の特定のエージェントに関連する有効状態を更新するために使用されます。
例えば、EnabledStateMap
が以下のようなマップであった場合:
EnabledStateMap = {"Agent1": "Enabled", "Agent2": "Disabled"}
上記の計算式を実行すると、キー "Agent"
の値が State
に置き換わります。
例えば、State
が "Enabled" の場合は:
EnabledStateMap = {"Agent1": "Enabled", "Agent2": "Disabled", "Agent": "Enabled"}
このように、EnabledStateMap
内の特定のエージェントの状態を更新するために set
演算子を使用しています。

はい、正しいです。set EnabledStateMap[Agent] = State
の計算式を使用することで、エージェントと関連する値が最新の状態に更新されます。
この計算式は、EnabledStateMap
内のエージェントに関連する値を変更するために使用されます。
エージェントの新しい状態を指定することで、そのエージェントに関連付けられた値が更新されます。
例えば、EnabledStateMap
が次のように定義されていたとします:
EnabledStateMap = {"Agent1": "有効", "Agent2": "無効"}
もし、Agent1
の状態を "無効" に変更する場合、計算式を次のように使用します:
set EnabledStateMap["Agent1"] = "無効"
その結果、EnabledStateMap
は次のようになります:
EnabledStateMap = {"Agent1": "無効", "Agent2": "無効"}
したがって、set EnabledStateMap[Agent] = State
を使用することで、エージェントと関連する値を最新の状態に更新することができます。

CurrentState に代入する意味
クリックすると開きます。
# ボタンが現在有効な状態を保存します
(Agent : agent).SaveEnabledState(State : logic):void=
if(CurrentState := EnabledStateMap[Agent]):
if(set EnabledStateMap[Agent] = State){}
else:
set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
このコードの SaveEnabledState
メソッドでは、与えられたエージェント(Agent
)の現在のボタンの有効/無効の状態を EnabledStateMap
という辞書で管理しています。
コードの意味は以下のとおり。
EnabledStateMap[Agent]
に現在の状態をCurrentState
として代入します。- これにより、エージェントが既に
EnabledStateMap
内に存在する場合、その現在の状態がCurrentState
に保存されます。
- これにより、エージェントが既に
if
文を使用してCurrentState
の値が存在するか確認します。- もし
CurrentState
の値が存在する場合、つまり既にエージェントがEnabledStateMap
内に存在している場合、そのエージェントの状態を新しいState
の値に更新します。- これにより、ボタンの有効/無効の状態が最新のものに更新されます。
- もし
CurrentState
の値が存在しない場合、つまりエージェントがまだEnabledStateMap
内に存在しない場合、新しいエージェントとその状態をEnabledStateMap
に追加します。
このコードの目的は、個々のエージェントごとにボタンの有効/無効の状態を保存し、必要に応じてそれを更新することです。
EnabledStateMap
はエージェントをキーとし、それぞれのエージェントのボタンの有効/無効の状態を値として持つ辞書です。
if (set EnabledStateMap[Agent] = State){}
の部分は、EnabledStateMap
のエントリーを更新するための構文ですが、提供されたコードでは if
文だけでなく set
も記述されているため、意味がない一連の文です。
【重要】EnabledStateMap の値を設定する際に括弧 {}を使用している理由
クリックすると開きます。
このコードの一部は、変数 EnabledStateMap
の値を設定する際に括弧 {}
を使用していますが、これにはいくつかの理由があります。
- Syntaxの要件:
- コードの文法的な要件に準拠するためです。
if
文の本体(then
ブロック)は必要ですが、何も実行するコードがない場合でも、空のブロック{}
が必要です。- この空のブロックは、何も行われないことを明示的に示します。
- シンボルの作成:
- このコードの場合、
EnabledStateMap
は可変なマップです。 if
の本体にブロック{}
を追加することで、新しい値をマップに割り当てることができます。- つまり、
EnabledStateMap[Agent]
というシンボルが存在しない場合は、新しいエントリをマップに追加するための記号として使われています。
- このコードの場合、
実際に何も実行されないこのブロックを追加することで、コードの明確性が向上し、可読性が高まります。読者は、この行の意図が新しい値を EnabledStateMap
に設定することであることを理解しやすくなります。
つまり、端的に言えば、無いのと同然ということです。

「エージェントに対する有効状態のエントリが既に存在していない」とは、EnabledStateMap
というマップ(連想配列)において、指定したエージェントに対するエントリがまだ存在しない状態を指します。
エージェントが新しく追加された場合や、既存のエージェントに対して初めて有効状態を設定する場合には、そのエージェントに対するエントリはまだ存在しません。このような場合、現在の EnabledStateMap
には指定したエージェントのキーが存在しないか、存在していてもその値が null
やデフォルト値である可能性があります。
そのため、コードの中の else
ブロックは、新しいエージェントに対してエントリを追加するために使われます。EnabledStateMap
というマップに、エージェントをキーとして、その有効状態を表す State
を値として追加します。
要約すると、エージェントに対する有効状態のエントリが存在しないとは、指定したエージェントのキーが EnabledStateMap
中にまだ存在しない状態を指します。

新しいエージェントとは、既存のエージェントとは異なり、過去に EnabledStateMap
に関連付けられたことがない、まったく新しいエンティティやエンティティのインスタンスを指します。
エージェントは、通常、特定の動作や状態を持つオブジェクトやプレイヤーなどを表すために使用されます。
例えば、ゲーム内のキャラクターがエージェントとして扱われる場合、新しいエージェントは新しく作成されたキャラクターのことを指します。
具体例として、ゲーム内のボタンの有効状態を管理するシステムを考えてみましょう。
ここでは、ゲーム内のプレイヤーがエージェントとして扱われます。最初のプレイヤーは既に存在しており、彼らに対してはすでに有効状態が関連付けられているかもしれません。
しかし、新しいプレイヤーがゲームに参加した場合、彼らはまだ EnabledStateMap
にエントリが存在しない新しいエージェントとなります。
新しいエージェントとは、既存のエージェントとは関連付けられていない、システム内で新たに追加されたエンティティやエンティティのインスタンスを指す言葉です。

エンティティ(Entity)は、データモデリングやプログラミングの文脈で使用される用語で、独自の属性や振る舞いを持つ実体を指します。エンティティは、システム内で識別可能であり、データや機能を表現するために使用されます。
エンティティのインスタンス(Instance)は、特定のエンティティの具体的な個体を指します。エンティティがクラスとして表現されるのに対し、エンティティのインスタンスは実際のオブジェクトや存在として具現化されます。
例えば、自動車データベースを考えてみましょう。エンティティとして「車」があります。
この場合、「車」は属性(例:メーカー、モデル、色)や振る舞い(例:走行、停止、加速)を持つ特定の存在を表します。
そして、実際の道路上にある各車は「車」エンティティのインスタンスです。
つまり、あるメーカーの特定のモデルであり、特定の色を持つ具体的な車は「車」エンティティのインスタンスとなります。
要約すると、エンティティは属性や振る舞いを持つ実体を指し、エンティティのインスタンスは特定のエンティティの現実世界での具体的な存在を表します。

{}
は、空のブロック(block)を表すものです。この中には実行するコードが含まれません。
if (set EnabledStateMap[Agent] = State){}
の中の{}
は、特定のコードの実行を指定するためのものですが、この場合は空のため、コードを実行する部分がないことを表しています。
具体的には、if
ステートメントの条件が真(true)と評価された場合に実行するコードを{}
内に書くことができます。
しかし、この例では、if
ステートメントが成立した場合の実行するコードがないため、{}
は空となっています。
従って、if (set EnabledStateMap[Agent] = State){}
を使用すると、条件が真の場合でも何も実行せずにスルーするという意味になります。

【確認】
「新しい状態はセットされるが、それ以降に実行するコードはない」というのが、if (set EnabledStateMap[Agent] = State){}
の意味です。
set EnabledStateMap[Agent] = State
によって、EnabledStateMap
内の特定のエージェントの有効状態が新しい値で更新されます。
しかし、if
ステートメントの中には実行するコードがないため、更新後の状態に基づいて追加の操作や処理を行うことはありません。
このコードを使用する場合、エージェントの有効状態を更新することが主な目的であり、更新後の処理や操作を行う場合には、if
ステートメントの中に実行するコードを追加する必要があります。

確認と保険のための条件式*2
クリックすると開きます。
# Saves the enabled state the button is currently in
(Agent : agent).SaveEnabledState(State : logic):void=
if(CurrentState := EnabledStateMap[Agent]):
if(set EnabledStateMap[Agent] = State){}
else:
set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
上記のコードでは2つの条件式が使用されていますが、それは確認と保険のために行われている可能性があります。
最初の条件式 if(CurrentState := EnabledStateMap[Agent])
は、EnabledStateMap
内にAgentの有効状態が既に存在するかどうかを確認しています。
もし既に存在する場合、現在の状態をCurrentStateに代入します。この条件式により、既存の状態を取得してそれに基づいた処理を行うことができます。
2つ目の条件式 if(set EnabledStateMap[Agent] = State){}
は、新しい状態をEnabledStateMapに設定します。
ただし、この条件式は常に真となるため、実際には条件を満たすかどうかの確認よりも、EnabledStateMapに新しい状態を設定しているという処理のための目的があると考えられます。
このような設計は、変数の存在確認とその値の更新を厳密に制御するために行われることがあります。
もしAgentの状態が既に存在する場合は既存の状態を取得し、新しい状態をEnabledStateMapに設定することで、データの整合性を保つことができます。
if(CurrentState := EnabledStateMap[Agent]):部分の目的
クリックすると開きます。
if(CurrentState := EnabledStateMap[Agent])
の部分は、Agentの有効状態がEnabledStateMap内に既に存在するかどうかを確認するために記述されています。
EnabledStateMap
は、異なるAgentに対してそれぞれの有効状態を保持するためのマップ(連想配列)のようなデータ構造と仮定します。
したがって、特定のAgentに対して既に有効状態が設定されている場合、その現在の状態を変数CurrentState
に代入します。この変数は後続のコードで使用されるため、既存の状態を取得し、それに基づいた処理を行うために使用されています。
もしAgentの有効状態が既に存在しない場合、すなわちEnabledStateMap[Agent]
が未定義、null、または空の場合、if
文の条件は偽となり、その分岐内のコードは実行されません。
それに代わり、else
節の中にあるset EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
が実行され、新しいエージェントとその有効状態がEnabledStateMap
に追加されます。
要するに、if(CurrentState := EnabledStateMap[Agent])
は既存の状態の取得を行うための処理です。
エージェントの有効状態の重複を防ぐため、または既存の状態を参照して追加の処理を行うために記述されています。

【例】
想像してみてください。
あなたが家で複数の家電製品を管理しているとします。各家電製品には「オン」と「オフ」という有効状態があります。例えば、電気ストーブ、テレビ、エアコンなどです。
あなたはそれぞれの家電製品の有効状態を追跡するためにマップ(連想配列)を使用することにしました。このマップをEnabledStateMap
と呼ぶことにします。
さて、ある日、エアコンの有効状態を保存しようとしています。以下のコードに対応する存在確認と更新の手順になります。
# 各家電製品にはエージェント(例えばエアコン)とその有効状態が対応しています
エアコン.Agent = 'エアコン'
# エアコンの現在の有効状態を取得します
if(CurrentState := EnabledStateMap[エアコン.Agent]):
# エアコンの状態が既に存在する場合は、その状態をCurrentStateに代入します
...
else:
# エアコンの状態がまだ存在しない場合は、新しい状態をEnabledStateMapに追加します
...
これを例え話に当てはめて説明すると、あなたは家の中を回って各家電製品の状態を確認し、その情報をメモに記録しています。
エアコンの状態を確認すると、既に記録された状態があるか確認します。もし以前に記録された状態があれば、それをCurrentStateというメモに書き留めます(CurrentStateに代入します)。
もしエアコンの状態がまだ記録されていない場合、新しいメモを作り、エアコンの状態をメモに記録します。
このような手順で、各家電製品の状態を管理し、重複を防ぎながら新しい状態を追加することができます。
これにより、エアコンの状態を含む他の家電製品の状態も同様の手順で保存できます。
要するに、if(CurrentState := EnabledStateMap[Agent])は、エージェントの有効状態の値の存在を確認するためのコードです。
もし値が存在する場合、それを利用して後続の処理を行い、存在しない場合は新しい値を追加するための処理を行います。

set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})の詳細
クリックすると開きます。
set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
は、EnabledStateMap
というマップに新しいエージェントとその有効状態を追加する処理を行っています。
具体的には、ConcatenateMaps
という関数は、2つのマップを結合する操作を行います。第1引数には既存のマップ EnabledStateMap
を指定し、第2引数には新しく追加するエージェントと有効状態の組み合わせを持つマップ map{Agent => State}
を指定します。
新しいエージェントと有効状態の組み合わせを表現するために、map{Agent => State}
という記法が使用されています。ここで Agent
はエージェントを表す変数であり、 State
は有効状態を表す変数です。
=>
は「右側の値を左側のキーに関連付ける」という意味で、map{Agent => State}
はエージェントと有効状態の組み合わせを持つマップを表すことになります。
したがって、set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
の処理では、既存の EnabledStateMap
に新しいエージェントと有効状態の組み合わせを追加しています。
これにより、EnabledStateMap
は更新され、新しいエージェントに対する有効状態の情報が格納されることになります。

一時的な関数という概念はありません。ConcatenateMaps
は、引数として与えられた2つのマップを結合して新しいマップを生成する関数です。
set EnabledStateMap = ConcatenateMaps(EnabledStateMap, map{Agent => State})
の処理では、EnabledStateMap
と map{Agent => State}
を結合し、新しいマップを生成しています。
この新しいマップが EnabledStateMap
に代入され、それによって EnabledStateMap
の内容が更新されます。
つまり、ConcatenateMaps
関数を使うことで、2つのマップを結合して、新しいマップを作成できます。
この新しいマップには、既存のマップ (EnabledStateMap
) のエントリーと、新しいエージェントと有効状態の組み合わせ (map{Agent => State}
) のエントリーが含まれます。
したがって、ConcatenateMaps
を使用してエージェントと有効状態の組み合わせを追加することで、EnabledStateMap
を更新することができます。

ShowWidget(Agent : ?agent):void=の詳細
ShowWidget(Agent : ?agent):void=
if(ValidAgent := Agent?, ThisButtonWidget := ButtonWidgetPerPlayer[ValidAgent]):
ThisButtonWidget.SetVisibility(widget_visibility.Visible)
if(SaveButtonState?):
ValidAgent.SaveVisibleState(true)
クリックすると開きます。
このコードは、ShowWidget
という関数の定義です。
# エージェントに関連するボタンウィジェットを表示する関数
ShowWidget(Agent : ?agent):void=
# エージェントが有効であるかチェックし、対応するボタンウィジェットを取得する
if(ValidAgent := Agent?, ThisButtonWidget := ButtonWidgetPerPlayer[ValidAgent]):
# ボタンウィジェットの表示状態を可視に変更する
ThisButtonWidget.SetVisibility(widget_visibility.Visible)
# ボタンの状態を保存する必要がある場合は処理を実行する
if(SaveButtonState?):
# ボタンの可視性の状態をエージェントに保存する
ValidAgent.SaveVisibleState(true)
ShowWidget(Agent : ?agent):void=
:
ShowWidget
は関数の名前であり、(Agent : ?agent)
は引数の宣言です。Agent
はエージェントを表す変数であり、?agent
はAgent
の型がオプション(nullable)であることを示しています。
:void
は関数の戻り値の型がvoid
(何も返さない)であることを示しています。
if(ValidAgent := Agent?, ThisButtonWidget := ButtonWidgetPerPlayer[ValidAgent]):
:
if
文は条件分岐を行うための制御構文です。- 条件式の結果が真である場合にのみブロック内の処理が実行されます。
ValidAgent := Agent?
はValidAgent
という新しい変数を定義し、それにAgent
の値を代入しています。Agent?
はAgent
の値が存在する場合に真となり、その値をValidAgent
に代入します。
ThisButtonWidget := ButtonWidgetPerPlayer[ValidAgent]
はButtonWidgetPerPlayer
という辞書(マップ)からValidAgent
に対応する値を取得し、ThisButtonWidget
に代入します。
ThisButtonWidget.SetVisibility(widget_visibility.Visible)
:
ThisButtonWidget
は前のステップで取得したボタンウィジェットを指します。SetVisibility(widget_visibility.Visible)
はThisButtonWidget
の表示状態を可視(表示される)に設定するメソッド呼び出しです。
if(SaveButtonState?):
if
文は再び使われています。条件式の結果が真である場合にのみブロック内の処理が実行されます。
SaveButtonState?
はSaveButtonState
の値が存在する場合に真となります。
ValidAgent.SaveVisibleState(true)
:
ValidAgent
は前のステップで定義された変数です。- この行では
SaveVisibleState
というメソッドを呼び出しています。 - 引数
true
は可視性の状態を表し、ValidAgent
に対して可視性の状態を保存するためのメソッド呼び出しです。
要約すると、このコードは指定したエージェントに関連するボタンウィジェットを表示させ、必要な場合にその状態を保存する処理を行っています。
エージェントの有無をチェックし、対応するボタンウィジェットを取得して表示します。必要に応じて、エージェントの状態を保存するメソッドを呼び出します。

ButtonWidgetPerPlayer[ValidAgent]):のValidAgentに関連する値とは
クリックすると開きます。
# エージェントに関連するボタンウィジェットを表示する関数
ShowWidget(Agent : ?agent):void=
# エージェントが有効であるかチェックし、対応するボタンウィジェットを取得する
if(ValidAgent := Agent?, ThisButtonWidget := ButtonWidgetPerPlayer[ValidAgent]):
# ボタンウィジェットの表示状態を可視に変更する
ThisButtonWidget.SetVisibility(widget_visibility.Visible)
# ボタンの状態を保存する必要がある場合は処理を実行する
if(SaveButtonState?):
# ボタンの可視性の状態をエージェントに保存する
ValidAgent.SaveVisibleState(true)
その処理はValidAgent(有効なエージェント)に関連するボタンウィジェットを取得するためのものです。ValidAgent := Agent?
という式は、Agent
の値が存在する場合に ValidAgent
にその値を代入します。
その後、ButtonWidgetPerPlayer[ValidAgent]
は ValidAgent
に対応するボタンウィジェットを取得します。
つまり、ValidAgent
はエージェントを表し、そのエージェントに関連する特定のボタンウィジェットを指すための変数です。
この処理によって、エージェントごとに異なるボタンウィジェットを取得することができます。

このクエリ式は、エージェントに関連するボタンウィジェットを検索しています。
具体的には、次の手順を実行しています。
Agent
が有効かどうかをチェックし、ValidAgent
に代入します。ValidAgent
には、Agent
が有効な場合はその値が入り、無効な場合はnull
または別の適切な値が入ります。
ButtonWidgetPerPlayer
からValidAgent
に対応するボタンウィジェットを取得し、ThisButtonWidget
に代入します。ThisButtonWidget
の表示状態(可視性)を可視に変更します。SaveButtonState
が真(true
)の場合、次の手順を実行します。ValidAgent
の可視性の状態をtrue
に保存します。
したがって、このクエリ式はエージェントに関連するボタンウィジェットを検索し、その表示状態を変更したり、必要に応じて保存するための処理を実行しています。

SetVisibility関数の詳細
クリックすると開きます。
SetVisibility
関数は、ウィジェットの表示状態を制御するための関数です。この関数を使用することで、ウィジェットを表示したり非表示にしたりすることができます。
以下に、SetVisibility
関数の詳細をプログラミング初心者向けに解説します。
関数名: SetVisibility
型: void(何も返さない)
パラメータ:
- InVisibility: widget_visibility(ウィジェットの可視性を表す列挙型)
SetVisibility
関数は、パラメータ InVisibility
に渡された値に基づいてウィジェットの表示状態を変更します。
widget_visibility
列挙型は、以下のような値を取ります:
widget_visibility.Visible
: ウィジェットを表示します。widget_visibility.Hidden
: ウィジェットを非表示にしますが、スペースを確保します。widget_visibility.Collapsed
: ウィジェットを非表示にし、スペースも確保しません。
例えば、以下のように SetVisibility
を使ってウィジェットを表示することができます:
ThisButtonWidget.SetVisibility(widget_visibility.Visible);
このコードでは、ThisButtonWidget
という名前のウィジェットを表示しています。
SetVisibility
の第一引数に widget_visibility.Visible
を指定することで、ウィジェットが可視状態になります。

if(SaveButtonState?):~クエリ式の詳細
クリックすると開きます。
if(SaveButtonState?):
この行では、SaveButtonState
(保存ボタンの状態)の値がtrueかどうかをクエリ式でチェックしています。
もしSaveButtonState
がtrueであれば、以下の処理を実行します。
ValidAgent.SaveVisibleState(true)
この行は、ValidAgent
が持つSaveVisibleState
という関数を呼び出しています。具体的には、ValidAgent
に対してSaveVisibleState
関数を呼び出し、引数としてtrueを渡しています。
この関数は、ボタンの可視性の状態をエージェントに保存するためのものです。
関数内の処理は、引数で与えられたエージェントの有効性をチェックし、対応するボタンウィジェットを表示し、必要な場合にはボタンの状態を保存するという流れです。
HideWidget(Agent : ?agent):void=の詳細
# Completely removes the button ui
HideWidget(Agent : ?agent):void=
if(ValidAgent := Agent?, ThisButtonWidget := ButtonWidgetPerPlayer[ValidAgent]):
ThisButtonWidget.SetVisibility(widget_visibility.Collapsed)
if(SaveButtonState?):
ValidAgent.SaveVisibleState(false)
クリックすると開きます。
# Completely removes the button ui
HideWidget(Agent : ?agent): void =
# エージェントが有効であるかチェックし、対応するボタンウィジェットを取得する
if (ValidAgent := Agent?, ThisButtonWidget := ButtonWidgetPerPlayer[ValidAgent]):
# ボタンウィジェットの表示状態を非表示に変更する
ThisButtonWidget.SetVisibility(widget_visibility.Collapsed)
# ボタンの状態を保存する必要がある場合は処理を実行する
if (SaveButtonState?):
# ボタンの可視性の状態をエージェントに保存する
ValidAgent.SaveVisibleState(false)
このコードは、エージェントに関連するボタンウィジェットを完全に削除するための関数です。
まず、関数の引数 Agent
に ?agent
という型が指定されています。この ?agent
は、エージェントという意味で、関数の呼び出し時に与えられるエージェントを指定します。
次に if
文が使用されています。これは、エージェントが有効であるかをチェックし、対応するボタンウィジェットを取得するための条件分岐です。このチェックは ValidAgent := Agent?
という行で行われています。
ここで :=
は、エージェントが null
でない場合に ValidAgent
に Agent
の値を割り当てることを意味します。
条件式が真である場合、ボタンウィジェットの表示状態を非表示に変更するために ThisButtonWidget.SetVisibility(widget_visibility.Collapsed)
が実行されます。
ここで SetVisibility
は、ボタンウィジェットの可視性を設定する関数です。
widget_visibility.Collapsed
は、非表示を表す値です。
さらに、if (SaveButtonState?):
の行では、SaveButtonState
という変数が true
である場合に処理が実行されます。この部分のコードは、ボタンの状態を保存する必要がある場合に使用されます。
最後に、ValidAgent.SaveVisibleState(false)
の行では、ボタンの可視性の状態をエージェントに保存します。この処理は、もし必要な場合に限り実行されます。
つまり、この関数は与えられたエージェントに関連するボタンウィジェットを完全に削除します。
もしボタンの状態を保存する必要がある場合は、それも行います。

SetVisibilityの詳細
クリックすると開きます。
SetVisibility関数は、Widget(ウィジェット)を表示または非表示にするための関数です。
この関数は、プレイヤーのUIからウィジェットを取り除かずに表示状態を切り替えることができます。
関数のシグネチャ:
SetVisibility<修飾子><アクセス権限>(InVisibility: widget_visibility): void
パラメータ:
InVisibility
(widget_visibility型):- ウィジェットの表示状態を指定するパラメータです。このパラメータは、以下の値を取ることができます:
widget_visibility.Visible
:- ウィジェットを表示します。
widget_visibility.Hidden
:- ウィジェットを非表示にします。
widget_visibility.Collapsed
:- ウィジェットを非表示にし、レイアウトからも取り除きます。
返り値:
void
:- SetVisibility関数は返り値を持ちません。
SetVisibility関数は、渡されたInVisibilityパラメータに基づいてウィジェットの表示状態を切り替えます。
ウィジェットを表示する場合はwidget_visibility.Visible
パラメータ、非表示にする場合はwidget_visibility.Hidden
パラメータ、非表示かつレイアウトから取り除く場合はwidget_visibility.Collapsed
パラメータを使用します。

(Agent : agent).SaveVisibleState(State : logic):void=の詳細
# Saves the visible state the button is currently in
(Agent : agent).SaveVisibleState(State : logic):void=
if(CurrentState := VisibleStateMap[Agent]):
if(set VisibleStateMap[Agent] = State){}
else:
set VisibleStateMap = ConcatenateMaps(VisibleStateMap, map{Agent => State})
クリックすると開きます。
# ボタンの現在の可視状態を保存します。
(Agent: agent).SaveVisibleState(State: logic): void =
if (CurrentState := VisibleStateMap[Agent]):
# エージェントに関連付けられた現在の状態を取得
if (set VisibleStateMap[Agent] = State) {}
# 現在の状態を新しい状態で更新
else:
set VisibleStateMap = ConcatenateMaps(VisibleStateMap, map{Agent => State})
# 新しいエージェントと状態をVisibleStateMapに追加
このコードはボタンの可視性の状態を保存し、必要に応じて更新するための関数です。
# ボタンの現在の可視状態を保存します。
(Agent: agent).SaveVisibleState(State: logic): void =
if (CurrentState := VisibleStateMap[Agent]):
# エージェントに関連付けられた現在の状態を取得
この行では、関数の定義が始まっています。SaveVisibleState
という関数は、引数として Agent
(エージェントの識別子)と State
(ボタンの可視性の状態)を受け取ります。
この関数は何も返さないことを void
で表しています。
if (CurrentState := VisibleStateMap[Agent])
は条件文です。エージェントに関連付けられた現在の状態 (VisibleStateMap[Agent]
) を取得し、それを CurrentState
という変数に代入しています。
また、:=
は代入式であり、現代のプログラミング言語で使われる代入演算子です。
if (set VisibleStateMap[Agent] = State) {}
# 現在の状態を新しい状態で更新
上記のブロックは、すでにエージェントの状態が存在する場合の処理です。if
文の中に入ることで、エージェントの状態が既に存在していることが判定されています。
set VisibleStateMap[Agent] = State
は、エージェントの状態 (VisibleStateMap[Agent]
) を新しい状態 (State
) で更新するための代入文です。
この行の目的は、現在の状態を新しい状態に変更することです。
else:
set VisibleStateMap = ConcatenateMaps(VisibleStateMap, map{Agent => State})
# 新しいエージェントと状態をVisibleStateMapに追加
最後のブロックは、エージェントの状態が存在しない場合の処理です。else
文の中に入ることで、エージェントの状態が存在しないことが判定されています。
set VisibleStateMap = ConcatenateMaps(VisibleStateMap, map{Agent => State})
は、VisibleStateMap
に新しいエージェントと状態を追加するための操作です。
これにより、新しいエージェントとその状態が VisibleStateMap
に結合されます。
SaveVisibleStateとVisibleStateMapの関係性
クリックすると開きます。
SaveVisibleStateとVisibleStateMapの関係性については、以下のとおりです。
【SaveVisibleStateメソッドの役割】
SaveVisibleStateメソッドは、ボタンの現在の可視状態を保存するためのメソッドです。
エージェント(ボタンを操作する対象)と状態(ボタンの可視性)の情報を引数として受け取ります。
このメソッドは以下の手順で処理を行います。
- エージェントの現在の状態がVisibleStateMapに存在するか確認します。
- もしエージェントの状態が存在する場合は、現在の状態を取得し、新しい状態で更新します。
- もしエージェントの状態が存在しない場合は、VisibleStateMapに新しいエージェントとその状態を追加します。
つまり、SaveVisibleStateメソッドはVisibleStateMapを操作してボタンの可視性の情報を保持する役割を担っています。

【VisibleStateMapの役割】
VisibleStateMapは、ボタンの可視性の情報を保持するためのデータ構造です。このデータ構造は、エージェント(ボタン)とその可視性の状態を関連付けるために使用されます。
一般的には辞書(またはマップ、連想配列)と呼ばれる形式で実装されます。
VisibleStateMapの具体的な役割は以下のとおり。
- 各エージェントに対して現在の状態を保存します。
- エージェントとその状態の関連付けを提供し、必要に応じて状態を取得したり更新したりするのに役立ちます。
例えば、VisibleStateMapは以下のような情報を保持することができます。
- エージェントAの現在の状態: 可視
- エージェントBの現在の状態: 不可視
- エージェントCの現在の状態: 可視
SaveVisibleStateメソッドでは、可視性の情報をエージェントごとにVisibleStateMapに記録します。既存のエージェントの状態が更新される場合は既存の情報を変更し、新しいエージェントが追加される場合はVisibleStateMapに新しいエントリを追加します。
このように、SaveVisibleStateメソッドとVisibleStateMapは密接に関連しており、ボタンの可視性の情報の保存・管理を行います。

【例】
VisibleStateMapとSaveVisibleStateメソッドの関係性を、家のドアの状態を管理するシステムに例えて説明します。
家にはドアの状態を管理するスマートなシステムがあります。
このシステムにはコントロールパネルがあり、SaveVisibleStateメソッドはそのコントロールパネルの機能の一部で、ドアの現在の状態(開いているか閉じているか)を保存し、特定の利用者や人物に関連付けます。
VisibleStateMapは、ドアの可視状態の記録帳やデータベースのようなものです。各利用者や人物に対して、ドアの可視状態の情報が記録されます。利用者は、あなたや家族、ゲストなどドアとやり取りする人々を表現しています。
以下に具体的な例を挙げながら解説します。
- ドアの状態を保存する:
- 誰かがコントロールパネルを操作して「保存」ボタンを押すと、SaveVisibleStateメソッドが呼び出されます。
- このメソッドでは、VisibleStateMapに利用者ごとのドアの現在の状態が既に記録されているかをチェックします。
- 既存の状態を確認する:
- もし利用者の状態がすでに記録されている場合、VisibleStateMapからその利用者の現在の状態を取得します。
- 例えば、利用者Aの状態が「ドアが閉まっている」と記録されている場合、その情報を取得します。
- 状態を更新する:
- もし利用者の状態がまだ記録されていない場合、VisibleStateMapに新しいエントリを追加します。
- 例えば、新しいゲストがやってきた場合、システムはゲストのために「ドアが開いている」という初期状態のエントリをVisibleStateMapに追加します。
SaveVisibleStateメソッドとVisibleStateMapを一緒に使用することで、スマートドアシステムは各利用者や人物ごとのドアの可視状態を記録できます。VisibleStateMapに保存された情報に基づいて、システムはドアが開いているか閉じているかを知ることができます。
この例えでは、コントロールパネルの「保存」ボタンがSaveVisibleStateメソッドに相当し、記録帳やデータベースがVisibleStateMapで、ドアの可視状態の情報が利用者や人物ごとに保存されています。

もし現在の状態が新しい状態である場合、"現在の状態を新しい状態で更新"という行が実行されます。
具体的には、以下のようになります。
if (set VisibleStateMap[Agent] = State) {}
# 現在の状態を新しい状態で更新
この行は、VisibleStateMap内のAgentに関連付けられた現在の状態を新しい状態で上書きします。つまり、VisibleStateMap内のAgentの値が新しい状態になります。
例えば、Agent Aの現在の状態が "door closed"(ドアが閉まっている)であり、新しい状態も "door closed"(ドアが閉まっている)である場合、この行は実行されますが、何も変化しません。
VisibleStateMap内のAgent Aの値は "door closed" のままです。

Stateの意味
クリックすると開きます。
State
は、ボタンの現在の有効/無効の状態を表す値です。このコードでは、Agent
(ボタンのエージェント) の状態を State
として保存しています。
具体的には、State
は論理値(真偽値)を表す変数であり、ボタンが有効な状態を表す場合は true
、無効な状態を表す場合は false
などの値が格納されます。
例えば、State
が true
の場合、ボタンは有効な状態を示し、State
が false
の場合、ボタンは無効な状態を示すといった具合です。
つまり、Agent
に対して State
の値を保存することで、ボタンの有効/無効の状態を保持・更新しています。

SetEnabled関数の詳細
クリックすると開きます。
SetEnabled関数は、プレイヤーがウィジェットとの対話(インタラクション)が可能かどうかを有効または無効にするための関数です。
以下に、関数の詳細を説明します。
- 関数名: SetEnabled
- 使用例文: 使用例文は与えられていませんが、以下のような形式で使用されることが想定されます。
SetEnabled(InIsEnabled);
- 関数の役割: SetEnabled関数は、プレイヤーによるウィジェットの操作を有効にするか無効にするかを設定します。
- 関数の種類: ネイティブ関数 (native)、公開関数 (public)
- 返り値の型: void (返り値がないことを示します)
パラメータ:
- InIsEnabled: タイプ(型)は"logic"です。
- このパラメータは、ウィジェットの操作を有効(true)または無効(false)にするかを指定します。
- たとえば、InIsEnabledがtrueの場合、プレイヤーはウィジェットと対話することが可能になります。
具体的な例を考えてみましょう。
あるゲームで、プレイヤーがメニューボタンをクリックすることでゲーム内のメニューを表示したり非表示にしたりする場合、SetEnabled関数は次のように使用される可能性があります。
// メニューボタンがクリックされた時に呼ばれる関数
void OnMenuButtonClick()
{
// メニューの有効・無効を切り替える
bool isEnabled = !menuWidget.IsEnabled(); // 現在の状態の反対の値を取得
menuWidget.SetEnabled(isEnabled); // isEnabledの値に基づいてメニューの有効・無効を設定
}
この例では、メニューウィジェット(menuWidget
)の有効状態を切り替えるためにSetEnabled関数が使用されます。
ボタンがクリックされるたびに、現在の有効状態の反対(例: 無効なら有効に、有効なら無効に)を取得して、その値をSetEnabled関数に渡しています。
このようにSetEnabled関数を使うことで、プログラム内でウィジェットの操作を制御することができます。

ButtonPosition,sizeのVector2についての詳細
クリックすると開きます。
@editable var ButtonText : string = ""
この行は、ButtonText
という変数を定義しています。ButtonText
はstring
型であり、プログラミングにおいてstring
は文字列を表します。
文字列は単語や文章など、文字の並びを表します。@editable
は、この変数がエディターやユーザーインターフェースを通じて編集可能であることを示します。
つまり、ボタンに表示されるテキストを変更できるようになります。
@editable var ButtonPosition : vector2 = vector2{}
こちらは、ButtonPosition
という変数を定義しています。ButtonPosition
もvector2
型です。
プログラミングにおいてvector2
は2次元のベクトルを表します。
この場合、vector2{}
でButtonPosition
変数をXとYが両方とも0のデフォルト値で初期化しています。つまり、ボタンの初期位置は原点(画面の左上)になります。
@editable var ButtonSize : vector2 = vector2{X := 475.0, Y:= 80.0}
先の行と同様に、こちらもvector2
型の変数ButtonSize
を定義しています。vector2{X := 475.0, Y:= 80.0}
でButtonSize
変数をXが475.0、Yが80.0のデフォルト値で初期化しています。
これにより、ボタンの初期サイズは横幅475ピクセル、縦幅80ピクセルになります。
Vector2の定義vector2 struct
は、2次元空間におけるベクトルを表現するためのデータ構造です。vector2
は2つの浮動小数点数(float)のコンポーネント、つまりXとYを持ちます。
これによって、2次元平面上の位置や方向を表現することができます。

例えば、画面上の点や長さ・幅を持つ四角形の寸法など、2D空間における位置や大きさを表す際に使用されます。
また、ゲーム開発ではキャラクターやオブジェクトの移動ベクトルや速度ベクトル、衝突の判定にも利用される重要なデータ構造です。
以下がvector2 struct
のメンバーについての解説です。
Data Members(データメンバー)
X
(float型):vector2
のX軸方向の値を表します。- Xは水平方向を意味します。
Y
(float型):vector2
のY軸方向の値を表します。- Yは垂直方向を意味します。
このように、vector2 struct
は2次元の空間上の位置を表すためのデータ構造であり、XとYの2つのコンポーネントを持ちます。これによって、様々な2Dの要素を表現し、操作することができます。
プログラミングにおいて、vector2
は座標を表現するのによく使われます。例えば、ゲーム内のキャラクターの位置や移動速度、画面上のオブジェクトの位置、衝突の検知などに使用されます。
2次元の操作を行う際には、vector2
が非常に便利なデータ構造となります。
例を挙げると、以下のようになります。
// キャラクターの位置を表すvector2
vector2 characterPosition = vector2{X = 10.0, Y = 5.0};
// オブジェクトの移動ベクトルを表すvector2
vector2 objectVelocity = vector2{X = 2.0, Y = -1.0};
上記のように、vector2 struct
を使用することで、位置や方向などの情報を簡潔に表現できます。これにより、プログラムの可読性や保守性が向上し、2次元のデータ操作がより効率的になります。
まとめると、vector2
は2次元空間における位置や方向を表現するためのデータ構造です。

詳しくは以下の記事を参考にしてください。
ButtonUI_UserOptions_Functionsクラスについて
ButtonUI_UserOptions_Functions := class<concrete>():
# このuiボタンを有効にするトリガー
@editable EnableButtonOnTrigger : trigger_device = trigger_device{}
# このuiボタンを無効にするトリガー
@editable DisableButtonOnTrigger : trigger_device = trigger_device{}
# このuiボタンを表示するトリガー
@editable ShowButtonOnTrigger : trigger_device = trigger_device{}
# このuiボタンを非表示にするトリガー
@editable HideButtonOnTrigger : trigger_device = trigger_device{}
クリックすると開きます。
ButtonUI_UserOptions_Functions
は、ボタンUIの動作を制御するためのクラスです。
このクラスには以下のような機能(関数)が含まれています。
@editable EnableButtonOnTrigger : trigger_device = trigger_device{}
この行は、EnableButtonOnTrigger
という変数を定義しています。
EnableButtonOnTrigger
はtrigger_device
という特別なデータ型で、トリガー(イベントの発火を制御する装置)を表します。
@editable
は、この変数がエディターで編集可能であることを示します。つまり、エディター上でどのトリガーを使用するか選択できます。
この変数は、「このUIボタンを有効にするためのトリガー」を指定するために使用されます。ボタンが有効になると、それをクリックして操作できるようになります。
例えば、ある条件が満たされたときにボタンを有効にしたい場合などに使用します。
同様に、以下の変数もあります:
@editable DisableButtonOnTrigger : trigger_device = trigger_device{}
DisableButtonOnTrigger
は、「このUIボタンを無効にするためのトリガー」を指定します。
ボタンが無効になると、クリックしても反応しなくなります。
@editable ShowButtonOnTrigger : trigger_device = trigger_device{}
ShowButtonOnTrigger
は、「このUIボタンを表示するためのトリガー」を指定します。
ボタンが表示されると、プレイヤーがそれを見ることができるようになります。
@editable HideButtonOnTrigger : trigger_device = trigger_device{}
HideButtonOnTrigger
は、「このUIボタンを非表示にするためのトリガー」を指定します。
ボタンが非表示になると、プレイヤーはそれを見ることができなくなり、クリックしても反応しません。
これらの機能を使用することで、プログラマーはトリガーを指定することでボタンの有効・無効や表示・非表示を制御することができます。
たとえば、ある条件が発生した時にボタンを表示させる、クリックされたら特定のアクションを実行するなど、ボタンの動作を細かく制御できます。

ButtonUI_UserOptions_Eventsクラスについて
ButtonUI_UserOptions_Events := class<concrete>():
# 起動するトリガー/送り先
@editable TriggerToActivate : trigger_device = trigger_device{}
# UI ボタンのインスティゲーターは送信しますか?
@editable SendInstigator : logic = true
# インスティゲーターとは、あるイベントを引き起こした原因となるオブジェクトや人物です。
# この場合、UI ボタンをクリックしたユーザーがインスティゲーターとなります。
# SendInstigator は、UI ボタンをクリックしたユーザーを送信するかどうかを指定します。
# SendInstigator が true の場合、UI ボタンをクリックしたユーザーが送信されます。
# SendInstigator が false の場合、UI ボタンをクリックしたユーザーは送信されません。
クリックすると開きます。
ButtonUI_UserOptions_Events
は、ボタンUIのイベントを制御するためのクラスです。
このクラスには以下のような機能(変数)が含まれています。
@editable TriggerToActivate : trigger_device = trigger_device{}
この行は、TriggerToActivate
という変数を定義しています。TriggerToActivate
はtrigger_device
という特別なデータ型で、トリガー(イベントの発火を制御する装置)を表します。
@editable
は、この変数がエディターで編集可能であることを示します。つまり、エディター上でどのトリガーを使用するか選択できます。
この変数は、「このUIボタンをクリックしたときに発火させるトリガー(イベントの目的地)」を指定するために使用されます。
ボタンがクリックされたときに、指定したトリガーが発火して、何らかのアクションが実行されるようになります。
例えば、ボタンがクリックされたら別のスクリプトを実行させたり、特定のオブジェクトをアクティベート(制限の解除)させたりする場合などに使用します。

@editable SendInstigator : logic = true
SendInstigator
は、プログラム上の用語で、何らかのアクションの実行元を指します。この変数の値はlogic
型(論理値)で、trueかfalseの2つの値を取ります。@editable
は、この変数がエディターで編集可能であることを示します。
SendInstigator
がtrueの場合、ボタンがクリックされたときにアクションが発火した際に、そのアクションの実行元(インスティゲーター)を送信します。送信された情報は後続のアクションやスクリプトで利用できます。
例えば、SendInstigatorがtrueで、あるキャラクターがボタンをクリックした場合、そのキャラクターがアクションの実行元として送信されることになります。
この情報を使って、キャラクター固有の処理を行うことができます。
このように、ButtonUI_UserOptions_Eventsクラスは、ボタンUIに関連するイベントを制御するための変数を持っています。これにより、ボタンがクリックされた際にどのトリガーを発火させるか、そしてそのアクションの実行元を送信するかなどを設定することができます。これによって、ボタンのクリックに応じた動作をカスタマイズすることが可能になります。
trigger_deviceクラスについて
クリックすると開きます。
trigger_device
クラスは、イベントを他の関連したデバイスに伝えるために使用されるクラスです。ゲーム開発などで、特定の条件や操作がトリガーされたときに他のデバイスに信号を送るために使われます。
メンバーについては以下のとおり。
データメンバー
TriggeredEvent
(listenable(payload)):- この変数は、デバイスがトリガーされたときに呼び出されるイベントを表します。
- デバイスがトリガーされると、指定したエージェント(キャラクターやオブジェクト)がこのデバイスを使用したことを通知します。
- ただし、エージェントがデバイスをトリガーしなかった場合はfalseが返されます。
- 例えば、特定のトリガー条件が満たされたときにこのイベントが発火し、他の関連デバイスに通知されることがあります。
関数
Disable
:- このデバイスを無効にします。
- デバイスが無効になると、その動作やトリガーが無効になります。
Enable
:- このデバイスを有効にします。
- デバイスが有効になると、その動作やトリガーが有効になります。
GetMaxTriggerCount
:- このデバイスが最大で何回トリガーできるかを取得します。
- 0はトリガー回数に制限がないことを意味します。
GetResetDelay
:- デバイスが再度トリガーできるようになるまでの時間(秒単位)を取得します(MaxTriggerの回数が許容する場合)。
GetTransform
:creative_object
の座標変換を取得します。- この座標変換は、cm(センチメートル)単位で表されます。
- ただし、座標変換を取得する前に
creative_object.IsValid
をチェックする必要があります。 - なぜなら、オブジェクトが破棄されている可能性があるからです。
GetTransmitDelay
:- トリガーが発生してから、このデバイスが他の外部デバイスにトリガーされたことを通知するまでの時間(秒単位)を取得します。
GetTriggerCountRemaining
:- このデバイスがGetMaxTriggerCountに達する前に、まだ何回トリガーできるかを取得します。
- GetMaxTriggerCountが無制限の場合は0を返します。
Reset
:- このデバイスがアクティブ化された回数をリセットします。
- これにより、GetTriggerCountRemainingが0に戻ります。
SetMaxTriggerCount
:- このデバイスがトリガーできる最大回数を設定します。
- 0はトリガー回数に制限がないことを意味します。
- 設定可能な最大回数は0から20までの範囲内でクランプされます。
SetResetDelay
:- トリガーした後、デバイスが再度トリガーできるまでの時間(秒単位)を設定します(MaxTriggerの回数が許容する場合)。
SetTransmitDelay
:- トリガーした後、このデバイスが他の外部デバイスにトリガーされたことを通知するまでの時間(秒単位)を設定します。
Trigger
:- エージェントをエージェントとして渡してこのデバイスをトリガーします。
- このデバイスが特定のエージェントだけで動作するように設定されている場合に使用します。
Trigger
:- このデバイスをトリガーし、
TriggeredEvent
イベントを発火させます。
- このデバイスをトリガーし、
これらの関数を使用することで、プログラマーはトリガーされたときの動作やトリガーの回数制限を設定することができます。
デバイスの有効・無効の切り替えや、トリガーが発生した際のアクションの実行など、デバイスの制御が可能になります。
このように、trigger_device
クラスは、ゲームやアプリケーションで重要なイベントの制御に使用されるクラスです。特定の条件や操作に応じて、関連するデバイスにトリガーを送ることができるため、柔軟で動的な動作を実現することができます。
詳しくは以下の記事を参考にしてください。
ボタンやUIの初期化、およびイベントの購読(Subscribe)
▼ このコードは、特定のイベントが発生したときにUIを表示し、ボタンに関数を割り当てる処理を行う関数の定義です。
OnBegin<override>()<suspends>:void=
InitButtonFunctions()
TriggerToShowUI.TriggeredEvent.Subscribe(OpenUI)
クリックすると開きます。
OnBegin<override>()<suspends>:void=
関数 OnBegin のオーバーライド(親クラスの同名メソッドを上書き)を宣言し、非同期処理として定義します。この関数の戻り値の型は void(何も返さない)です。
InitButtonFunctions()
InitButtonFunctions() という関数を呼び出します。この関数は、ボタンに対して特定の処理を割り当てるための初期化を行います。
TriggerToShowUI.TriggeredEvent.Subscribe(OpenUI)
TriggerToShowUI オブジェクトの TriggeredEvent というイベントに対して、OpenUI 関数を購読(Subscribe)します。イベントが発生すると、OpenUI 関数が呼び出されます。この行の目的は、特定のイベントが発生したときに UI を表示するための処理です。
コードの詳細は以下のとおり。
OnBegin<override>()<suspends>:void
:- これは関数の名前と型を示しています。
- "OnBegin"という名前の関数で、オーバーライド(親クラスの同名メソッドを上書き)し、非同期処理を行います。
- 型は「void」で、戻り値がないことを示しています。
InitButtonFunctions()
:- 「InitButtonFunctions」という関数を呼び出しています。
- この関数は、ボタンに対して特定の処理を割り当てるための初期化を行うものです。
- つまり、ボタンにイベントハンドラやクリックイベントの関数などを設定します。
TriggerToShowUI.TriggeredEvent.Subscribe(OpenUI)
:- 「TriggerToShowUI」の「TriggeredEvent」イベントに対して、OpenUIという関数を購読(Subscribe)しています。
- ここでは、特定のイベントが発生したときにUIを表示するための処理を行います。
- イベントが発生すると、関数OpenUIが呼び出されます。
この関数は、アプリケーションの初期化などのタイミングで呼び出されることを想定しています。ボタンやUIの初期化、およびイベントの購読(Subscribe)を行い、必要な機能を準備しています。
InitButtonFunctions()の詳細
# 各ボタンの「functions」タブを初期化します。
InitButtonFunctions():void=
for(ThisButtonUI : ButtonUI):
ThisButtonUI.ButtonSignal_Recieve.EnableButtonOnTrigger.TriggeredEvent.Subscribe(ThisButtonUI.EnableWidget)
ThisButtonUI.ButtonSignal_Recieve.DisableButtonOnTrigger.TriggeredEvent.Subscribe(ThisButtonUI.DisableWidget)
ThisButtonUI.ButtonSignal_Recieve.ShowButtonOnTrigger.TriggeredEvent.Subscribe(ThisButtonUI.ShowWidget)
ThisButtonUI.ButtonSignal_Recieve.HideButtonOnTrigger.TriggeredEvent.Subscribe(ThisButtonUI.HideWidget)
クリックすると開きます。
# Initializes the 'functions' tab for each button ui
'functions' タブの初期化を行います。この部分は各ボタンのUIに対して処理を割り当てるための初期化を実行します。
InitButtonFunctions():void=
InitButtonFunctions という関数を定義します。戻り値の型は void(何も返さない)です。
for(ThisButtonUI : ButtonUI):
各 ThisButtonUI に対して以下の処理を繰り返します。ButtonUI はボタンのユーザーインターフェイスを示します。
ThisButtonUI.ButtonSignal_Recieve.EnableButtonOnTrigger.TriggeredEvent.Subscribe(ThisButtonUI.EnableWidget)
ThisButtonUI.ButtonSignal_Recieve.DisableButtonOnTrigger.TriggeredEvent.Subscribe(ThisButtonUI.DisableWidget)
ThisButtonUI.ButtonSignal_Recieve.ShowButtonOnTrigger.TriggeredEvent.Subscribe(ThisButtonUI.ShowWidget)
ThisButtonUI.ButtonSignal_Recieve.HideButtonOnTrigger.TriggeredEvent.Subscribe(ThisButtonUI.HideWidget)
各 ThisButtonUI の ButtonSignal_Recieve というイベントに対して、関数を購読(Subscribe)します。
EnableButtonOnTrigger がトリガーされたとき、ThisButtonUI の EnableWidget 関数を呼び出します。
DisableButtonOnTrigger がトリガーされたとき、ThisButtonUI の DisableWidget 関数を呼び出します。
ShowButtonOnTrigger がトリガーされたとき、ThisButtonUI の ShowWidget 関数を呼び出します。
HideButtonOnTrigger がトリガーされたとき、ThisButtonUI の HideWidget 関数を呼び出します。
このコードは、ボタンのUIに関連する機能を初期化するための処理です。
以下に詳細な解説をします。
InitButtonFunctions():void=
InitButtonFunctions
という関数が定義されています。
この関数は値を返さず (void)、ボタンのUIに関する処理を初期化します。
for(ThisButtonUI : ButtonUI):
for
ループを使って、ButtonUI
という要素を持つ各 ThisButtonUI
に対して処理を繰り返します。
ButtonUI
はボタンのユーザーインターフェースを示す変数名です。
ThisButtonUI.ButtonSignal_Recieve.EnableButtonOnTrigger.TriggeredEvent.Subscribe(ThisButtonUI.EnableWidget)
ThisButtonUI
の参照する要素である ButtonSignal_Recieve
の EnableButtonOnTrigger
イベントがトリガーされたとき、ThisButtonUI
の EnableWidget
関数を呼び出すように設定します。
これによって、ボタンが有効になるイベントが発生した際に EnableWidget
関数が実行されます。
ThisButtonUI.ButtonSignal_Recieve.DisableButtonOnTrigger.TriggeredEvent.Subscribe(ThisButtonUI.DisableWidget)
同様に、ThisButtonUI
の DisableButtonOnTrigger
イベントがトリガーされたとき、ThisButtonUI
の DisableWidget
関数を呼び出すように設定します。
これによって、ボタンが無効になるイベントが発生した際に DisableWidget
関数が実行されます。
ThisButtonUI.ButtonSignal_Recieve.ShowButtonOnTrigger.TriggeredEvent.Subscribe(ThisButtonUI.ShowWidget)
同様に、ThisButtonUI
の ShowButtonOnTrigger
イベントがトリガーされたとき、ThisButtonUI
の ShowWidget
関数を呼び出すように設定します。
これによって、ボタンの表示が必要なイベントが発生した際に ShowWidget
関数が実行されます。
ThisButtonUI.ButtonSignal_Recieve.HideButtonOnTrigger.TriggeredEvent.Subscribe(ThisButtonUI.HideWidget)
同様に、ThisButtonUI
の HideButtonOnTrigger
イベントがトリガーされたとき、ThisButtonUI
の HideWidget
関数を呼び出すように設定します。
これによって、ボタンの非表示が必要なイベントが発生した際に HideWidget
関数が実行されます。
このコードの目的は、ボタンのUIごとに特定のイベントが発生した場合に実行される関数を設定することです。
例えば、ボタンが押されたら何らかの処理を実行したり、表示や非表示を切り替えたりする場合に使用できます。

ThisButtonUIがButtonUI型であることの詳細
クリックすると開きます。
変数「ThisButtonUI」は、「ButtonUI」という型を使用しているのは、それぞれのボタンのユーザーインターフェイス(UI)要素を表すインスタンスを指しているためです。
これにより、それぞれのボタンUIのプロパティやメソッドにアクセスして操作することができます。
具体的には、ボタンの有効化や無効化、ウィジェットの表示や非表示、イベントの購読などの操作を特定のUI要素に対して実行するため、「ButtonUI」という型を使用しています。

for(ThisButtonUI : ButtonUI):の詳細
クリックすると開きます。
プログラムの中で、for
ループは同じコードを複数回繰り返すために使われます。
今回は特定の種類のループである「for-each」ループを扱います。
これは、コレクション(集まり)の中の個々のアイテムを一つずつ取り出し、それぞれに対して動作を行うことができます。
「for(ThisButtonUI : ButtonUI):」という行を以下のように解釈します。
for
:- ループが始まることを示すキーワードです。
ThisButtonUI
:- これは一時的な変数の名前で、コレクション内の各アイテムを参照するために使用します。
:
:- 変数名(
ThisButtonUI
)とコレクション名(ButtonUI
)を区切ります。
- 変数名(
ButtonUI
:- これは繰り返し処理を行いたいアイテムの集まりを表します。
したがって、「ButtonUI」のコレクション内の各アイテムについて、その後のコードブロックが実行されます。一時的な変数「ThisButtonUI」には、各繰り返しで現在のアイテムの値が保存されます。
提供されたコードの文脈では、ループ内のコード行(アクション)が「ButtonUI」のコレクション内の各「ThisButtonUI」に対して実行されるという意味です。

この文脈では、ButtonUI
は特定の種類のオブジェクトや要素の集まりを指しています。
for(ThisButtonUI : ButtonUI):
という行では、ButtonUI
という型のオブジェクトの集まりに含まれる各要素をThisButtonUI
という変数で順番に参照しています。
ThisButtonUI.ButtonSignal_Recieve.EnableButtonOnTrigger~の詳細
ThisButtonUI.ButtonSignal_Recieve.EnableButtonOnTrigger.TriggeredEvent.Subscribe(ThisButtonUI.EnableWidget)
ThisButtonUI.ButtonSignal_Recieve.DisableButtonOnTrigger.TriggeredEvent.Subscribe(ThisButtonUI.DisableWidget)
ThisButtonUI.ButtonSignal_Recieve.ShowButtonOnTrigger.TriggeredEvent.Subscribe(ThisButtonUI.ShowWidget)
ThisButtonUI.ButtonSignal_Recieve.HideButtonOnTrigger.TriggeredEvent.Subscribe(ThisButtonUI.HideWidget)
クリックすると開きます。
ThisButtonUI.ButtonSignal_Recieve.EnableButtonOnTrigger.TriggeredEvent.Subscribe(ThisButtonUI.EnableWidget)
ThisButtonUI.ButtonSignal_Recieve.DisableButtonOnTrigger.TriggeredEvent.Subscribe(ThisButtonUI.DisableWidget)
ThisButtonUI.ButtonSignal_Recieve.ShowButtonOnTrigger.TriggeredEvent.Subscribe(ThisButtonUI.ShowWidget)
ThisButtonUI.ButtonSignal_Recieve.HideButtonOnTrigger.TriggeredEvent.Subscribe(ThisButtonUI.HideWidget)
# 各 ThisButtonUI の ButtonSignal_Recieve というイベントに対して、関数を購読(Subscribe)します。
# EnableButtonOnTrigger がトリガーされたとき、ThisButtonUI の EnableWidget 関数を呼び出します。
# DisableButtonOnTrigger がトリガーされたとき、ThisButtonUI の DisableWidget 関数を呼び出します。
# ShowButtonOnTrigger がトリガーされたとき、ThisButtonUI の ShowWidget 関数を呼び出します。
# HideButtonOnTrigger がトリガーされたとき、ThisButtonUI の HideWidget 関数を呼び出します。
上記のコードは、ボタンのUIに関連するイベントと関数の関係を設定しています。
以下に解説します。
ThisButtonUI.ButtonSignal_Recieve.EnableButtonOnTrigger.TriggeredEvent.Subscribe(ThisButtonUI.EnableWidget)
- 「ThisButtonUI」の「ButtonSignal_Recieve」にある「EnableButtonOnTrigger」というイベントがトリガーされた場合に、関数「ThisButtonUI.EnableWidget」を呼び出します。
- このイベントは、ボタンを有効化するトリガーとして設定されています。
ThisButtonUI.ButtonSignal_Recieve.DisableButtonOnTrigger.TriggeredEvent.Subscribe(ThisButtonUI.DisableWidget)
- 「ThisButtonUI」の「ButtonSignal_Recieve」にある「DisableButtonOnTrigger」というイベントがトリガーされた場合に、関数「ThisButtonUI.DisableWidget」を呼び出します。
- このイベントは、ボタンを無効化するトリガーとして設定されています。
ThisButtonUI.ButtonSignal_Recieve.ShowButtonOnTrigger.TriggeredEvent.Subscribe(ThisButtonUI.ShowWidget)
- 「ThisButtonUI」の「ButtonSignal_Recieve」にある「ShowButtonOnTrigger」というイベントがトリガーされた場合に、関数「ThisButtonUI.ShowWidget」を呼び出します。
- このイベントは、ボタンのウィジェットを表示するトリガーとして設定されています。
ThisButtonUI.ButtonSignal_Recieve.HideButtonOnTrigger.TriggeredEvent.Subscribe(ThisButtonUI.HideWidget)
- 「ThisButtonUI」の「ButtonSignal_Recieve」にある「HideButtonOnTrigger」というイベントがトリガーされた場合に、関数「ThisButtonUI.HideWidget」を呼び出します。
- このイベントは、ボタンのウィジェットを非表示にするトリガーとして設定されています。
これらの設定により、各ボタンのUIに対して、特定のイベントが発生した場合に関連する関数が実行されるようになります。
例えば、ボタンが押された時に関数が実行されたり、ボタンの表示状態が変わった時に関数が実行されたりします。

ButtonSignal_Recieveの定義
@editable
ButtonSignal_Recieve : ButtonUI_UserOptions_Functions = ButtonUI_UserOptions_Functions{}
クリックすると開きます。
このコードは、ButtonUI
クラスの中で定義されたButtonSignal_Recieve
という変数についての説明です。
ButtonSignal_Recieve
は、ButtonUI_UserOptions_Functions
という型のオブジェクトです。この変数は@editable
属性が付いており、編集可能なプロパティとして扱われます。
ButtonUI_UserOptions_Functions
は、おそらくButtonUI
のユーザーオプションに関する機能を格納するためのカスタムデータ型(もしくはクラス)です。この型のインスタンスは、ButtonSignal_Recieve
に代入されています。ButtonSignal_Recieve
は、ボタンUIの受信側のユーザーオプションに関連する機能を提供します。
具体的には、以下の関数の定義がButtonUI_UserOptions_Functions
型内に存在することを想定しています。
EnableWidget(Agent : ?agent):void
DisableWidget(Agent : ?agent):void
ShowWidget(Agent : ?agent):void
HideWidget(Agent : ?agent):void
これらの関数は、ボタンの表示や状態の制御に関連する操作を行うものです。ButtonSignal_Recieve
を通じてイベントの受信や関数の実行が可能になります。
このコードでは、初期値としてButtonUI_UserOptions_Functions{}
(空のインスタンス)が設定されていますが、この後、アプリケーションのロジックに基づいて適切な関数が追加されることが想定されます。
要するに、ButtonSignal_Recieve
は、ボタンUIが受け取るユーザーオプションの機能を格納するプロパティであり、後で関数が追加されることが期待されています。

ButtonUI_UserOptions_Functions := class<concrete>():
# The trigger that will enable this ui button, making it 'un-fade' and clickable
@editable EnableButtonOnTrigger : trigger_device = trigger_device{}
# The trigger that will disable this ui button, making it 'fade' and unclickable
@editable DisableButtonOnTrigger : trigger_device = trigger_device{}
# The trigger that will show this ui button, making it visible and clickable
@editable ShowButtonOnTrigger : trigger_device = trigger_device{}
# The trigger that will hide this ui button, making it not visible at all and therefore unclickable
@editable HideButtonOnTrigger : trigger_device = trigger_device{}
このコードは、ButtonUI_UserOptions_Functions
クラスの定義です。このクラスは、ボタンUIのユーザーオプションに関連する機能を格納するためのカスタムデータ型(もしくはクラス)です。
以下は、ButtonUI_UserOptions_Functions
クラス内の各プロパティの説明です。
EnableButtonOnTrigger
:- 編集可能なプロパティ(
@editable
属性が付いています)です。 - 型は
trigger_device
となっています。 - これは、ボタンの有効化(クリック可能にする)をトリガーするためのトリガーデバイスを指定するための変数です。
- 編集可能なプロパティ(
DisableButtonOnTrigger
:- 編集可能なプロパティです。
- 型は
trigger_device
で、ボタンの無効化(クリック不可にする)をトリガーするためのトリガーデバイスを指定するための変数です。
ShowButtonOnTrigger
:- 編集可能なプロパティです。
- 型は
trigger_device
で、ボタンの表示をトリガーするためのトリガーデバイスを指定するための変数です。 - ボタンが可視化され、クリック可能になります。
HideButtonOnTrigger
:- 編集可能なプロパティです。
- 型は
trigger_device
で、ボタンの非表示化をトリガーするためのトリガーデバイスを指定するための変数です。 - ボタンが完全に非表示になり、クリックもできなくなります。
これらのプロパティは、異なるトリガーデバイスをボタンUIに関連付けることにより、ボタンの有効化、無効化、表示、非表示などの動作を制御します。
ボタンUIの動作をカスタマイズする際に、これらのトリガーデバイスを特定のトリガーイベントに関連付けることができます。
例えば、EnableButtonOnTrigger
に適切なトリガーデバイスを設定すると、そのトリガーデバイスが発火するときにボタンがクリック可能になります。
Subscribe関数の詳細
クリックすると開きます。
Subscribe
関数は、コールバックを登録し、指定されたsignable.Signal
に対して呼び出しがマッチした場合にそのコールバックを実行するためのものです。
技術的な詳細は以下のとおり。
Subscribe
関数は、signable.Signal
と呼ばれる特定の呼び出しに対してコールバックを登録するために使用されます。- 関数の戻り値は「unsubscriber」オブジェクトであり、これを使って登録したコールバックを解除することができます。
- 解除するためには、unsubscriberオブジェクトの
cancelable.Cancel
関数を呼び出します。
- 解除するためには、unsubscriberオブジェクトの
以下は、Subscribe
関数の例の使用方法です。
Subscribe<public>(Callback:(t), , , :void)<varies><transacts>:cancelable
この例では、以下のようなパラメータを持つSubscribe
関数が呼び出されています。
Callback
:- 登録するコールバック関数です。
:(t)
という形式で指定されており、t
はコールバック関数の引数の型を示しています。- また、
:void
という表記は、コールバック関数が戻り値を持たないことを示しています。
また、関数の使用に関連する重要なポイントは次のとおりです。
Subscribe
関数によって返されるunsubscriberオブジェクトを使用すると、登録したコールバックを後で解除することができます。- このオブジェクトの
cancelable.Cancel
関数を呼び出すことで、コールバック登録を解除できます。
- このオブジェクトの
OpenUI(Agent : ?agent):void=~の詳細
OpenUI(Agent : ?agent):void=
if(ValidAgent := Agent?, Player := player[ValidAgent], PlayerUI := GetPlayerUI[Player]):
if(MyUI := MaybeMyUIPerPlayer[Player]?):
PlayerUI.RemoveWidget(MyUI)
if(set MaybeMyUIPerPlayer[Player] = false) {}
else:
NewUI := CreateMyUI(ValidAgent)
PlayerUI.AddWidget(NewUI, player_ui_slot{InputMode := ui_input_mode.All})
if(set MaybeMyUIPerPlayer[Player] = option{NewUI}) {}
クリックすると開きます。
OpenUI(Agent : ?agent):void=
# エージェントが有効かどうかをチェックし、関連するプレイヤーとプレイヤーのUIを取得する
if(ValidAgent := Agent?, Player := player[ValidAgent], PlayerUI := GetPlayerUI[Player]):
# プレイヤーに対応するMaybeMyUIPerPlayerが存在するかどうかをチェックする
if(MyUI := MaybeMyUIPerPlayer[Player]?):
# PlayerUIから既存のウィジェットを削除する
PlayerUI.RemoveWidget(MyUI)
# MaybeMyUIPerPlayerをfalseに設定する(プレイヤーにUIが存在しない状態)
if(set MaybeMyUIPerPlayer[Player] = false) {}
else:
# エージェントに対して新しいUIを作成する
NewUI := CreateMyUI(ValidAgent)
# PlayerUIに新しいUIを指定したスロットとAllの入力モードで追加する
PlayerUI.AddWidget(NewUI, player_ui_slot{InputMode := ui_input_mode.All})
# MaybeMyUIPerPlayerを新しいUIを含むオプションに設定する
if(set MaybeMyUIPerPlayer[Player] = option{NewUI}) {}
このコードは、OpenUI
という関数の実装です。
以下でそれぞれの行についてわかりやすく解説します。
- 関数
OpenUI
の宣言:OpenUI
は引数Agent
を受け取ります。- 関数の戻り値は
void
(何も返さない)です。
Agent
のバリデーションと変数設定:- 変数
ValidAgent
にAgent?
を代入します。Agent?
はAgent
が存在するかどうかを表します。
Player
にplayer[ValidAgent]
を代入します。player[ValidAgent]
は、Agent
に関連付けられたプレイヤーを表します。
PlayerUI
にGetPlayerUI[Player]
を代入します。GetPlayerUI[Player]
は、Player
のインターフェース(UI)を取得します。
- 変数
MaybeMyUIPerPlayer
のバリデーションと処理:MaybeMyUIPerPlayer[Player]
が存在するかどうかをチェックします。- もし存在する場合、
PlayerUI
からMaybeMyUIPerPlayer[Player]
に対応するウィジェットを削除します。 MaybeMyUIPerPlayer[Player]
にはfalse
を設定します。
MaybeMyUIPerPlayer
の存在しない場合の処理:- 新しい UI を作成し、
NewUI
に代入します。 PlayerUI
にNewUI
をplayer_ui_slot{InputMode := ui_input_mode.All}
のスロットに追加します。MaybeMyUIPerPlayer[Player]
にはoption{NewUI}
を設定します。
- 新しい UI を作成し、
このコードは、与えられた Agent
に関連付けられたプレイヤーの UI に対して、特定の条件に基づいて操作を行います。
具体的には、すでに MaybeMyUIPerPlayer
が存在する場合はそのウィジェットを削除し、存在しない場合は新しい UI を作成して追加します。

player[ValidAgent]
はplayer
というマップ(辞書)からキーValidAgent
に関連付けられた値、つまり関連するプレイヤーを取得しています。
このコードでは、ValidAgent
はエージェントを表し、そのエージェントに関連付けられたプレイヤーを取得するために使用されています。
player[ValidAgent]
はエージェントに関連するプレイヤーを表しています。
正確には有効なエージェントってことですね。

例えば、もし player
辞書が以下のように定義されていた場合:
player = {
"agent1": "player1",
"agent2": "player2",
"agent3": "player3"
}
もし ValidAgent
の値が "agent2"
であった場合、player["agent2"]
の結果は "player2"
になります。
そして、この "player2"
が Player
変数に代入されることになります。
具体的な関連するプレイヤーの値はコード内で定義される player
辞書に依存します。
このコードの最大の目的は、与えられたエージェントに関連するプレイヤーとプレイヤーのUIを処理することです。
以下に、コードの詳細な解説を示します。
if(ValidAgent := Agent?, Player := player[ValidAgent], PlayerUI := GetPlayerUI[Player]):
最初の行では、Agent
という変数をチェックし、有効なエージェントであるかを確認します。
もし有効なエージェントであれば、Player
という変数にそのエージェントに関連するプレイヤーを代入し、PlayerUI
には GetPlayerUI
関数を使用して、そのプレイヤーに関連するUIを取得します。
if(MyUI := MaybeMyUIPerPlayer[Player]?):
次に、MaybeMyUIPerPlayer
という変数を介して、プレイヤーに対応するUIが既に存在するかをチェックします。もし存在する場合は、MyUI
という変数にそのUIを代入します。
PlayerUI.RemoveWidget(MyUI)
if(set MaybeMyUIPerPlayer[Player] = false) {}
UIが存在している場合は、PlayerUI
からそのUIを削除し、MaybeMyUIPerPlayer[Player]
を false
に設定します。これによって、プレイヤーにUIが存在しない状態になります。
else:
NewUI := CreateMyUI(ValidAgent)
PlayerUI.AddWidget(NewUI, player_ui_slot{InputMode := ui_input_mode.All})
if(set MaybeMyUIPerPlayer[Player] = option{NewUI}) {}
UIが存在しない場合は、CreateMyUI
関数を使用して新しいUIを作成します。それを NewUI
という変数に代入し、PlayerUI
に対して AddWidget
関数を使用して新しいUIを追加します。
player_ui_slot{InputMode := ui_input_mode.All}
は、UIを指定したスロットに割り当て、すべての入力モードで有効にするための設定です。最後に、MaybeMyUIPerPlayer[Player]
を新しいUIを含むオプションに設定します。
このコードは、与えられたエージェントに関連するプレイヤーとプレイヤーのUIを管理し、存在する場合は削除し、存在しない場合は新しいUIを作成して追加する役割を果たしています。

AddWidget関数の詳細
クリックすると開きます。
AddWidget
関数は、player_ui
オブジェクトに対してウィジェット(画面上の要素)を追加するための関数です。
以下に、その技術的な詳細と解説を示します。
AddWidget(Widget: widget, Slot: player_ui_slot): void
AddWidget
関数は、Widget
と Slot
の2つのパラメータを受け取ります。
Widget
(ウィジェット)は、追加される画面上の要素です。- これは
widget
型のオブジェクトです。
- これは
Slot
(スロット)は、ウィジェットの配置や設定に関するオプションです。- これは
player_ui_slot
型のオブジェクトです。
- これは
AddWidget
関数は、与えられたウィジェットを指定されたスロットに追加し、その設定に従って player_ui
へ配置します。
ウィジェットは、ユーザーインターフェース(UI)に表示される要素であり、ボタン、テキスト、画像、スライダーなどのさまざまなものを含むことができます。AddWidget
関数を使用することで、作成したウィジェットを画面上に表示することができます。
スロットは、ウィジェットの配置方法や表示方法を指定するためのオプションです。例えば、ウィジェットを特定の位置に配置したり、特定の入力モードで有効にしたりすることができます。
AddWidget
関数は、player_ui
オブジェクトへのウィジェットの追加を行うため、ユーザーインターフェースの構築や更新などにおいて重要な役割を果たします。

player_ui_slot構造体の詳細
クリックすると開きます。
player_ui_slot
は、ウィジェットの作成設定オプションを持つ構造体(struct)です。
技術的な詳細は以下のとおり。
player_ui_slot struct
{
int ZOrder;
ui_input_mode InputMode;
};
player_ui_slot
構造体には、2つのデータメンバがあります。
ZOrder
(Zオーダー)は、ウィジェットの描画順序を制御するための整数値です。- 値が大きいほど手前に描画されます。
- つまり、他のウィジェットよりも手前に表示したい場合に、より大きな値を指定します。
InputMode
(入力モード)は、ウィジェットの入力イベントの処理方法を制御するための列挙型(enum)であるui_input_mode
のオブジェクトです。- 入力モードは、どのようにウィジェットがユーザーの入力を受け入れるかを制御します。
- 例えば、特定の入力モードの場合のみウィジェットが入力を受け付けるようにすることができます。
player_ui_slot 構造体は、ウィジェットの表示や入力処理などを制御する必要がある場合に使用されます。ウィジェットがどのように描画され、どのようにユーザーの入力を処理するかを指定するための重要な役割を果たします。
player_uiクラスとplayer_ui_slot構造体の関係性
クリックすると開きます。
player_ui
クラスと player_ui_slot
構造体は、UEFN内のユーザーインターフェース(UI)の作成や制御に関連する要素です。
player_ui_slot
構造体:
player_ui_slot
構造体は、ウィジェット(画面上の要素)の作成や表示方法を制御するためのオプションを提供します。ZOrder
メンバは、ウィジェットの描画順序を制御します。- より大きな値を指定すると、ウィジェットは他のウィジェットの前面に表示されます。
InputMode
メンバは、ウィジェットの入力イベントの処理方法を制御します。- 特定の入力モードの場合にのみウィジェットが入力を受け付けるようにすることが可能です。
player_ui
クラス:
player_ui
クラスは、プレイヤーのUIにウィジェットを追加したり削除したりするためのメインインターフェースです。AddWidget
関数は、player_ui
にウィジェットを追加するための関数です。- デフォルトの
player_ui_slot
の設定オプションを使用する場合や、別途指定したSlot
の設定オプションを使用する場合があります。
- デフォルトの
RemoveWidget
関数は、player_ui
からウィジェットを削除するための関数です。
関係性:
player_ui
クラスは、player_ui_slot
構造体を使用してウィジェットの作成や表示方法を制御します。player_ui
クラスのAddWidget
関数では、デフォルトのplayer_ui_slot
設定オプションを使用するか、または独自のplayer_ui_slot
オブジェクトを指定することで、ウィジェットの配置・表示方法を制御します。
簡単に言えば、player_ui_slot
構造体はウィジェットの個々の設定オプションを提供し、player_ui
クラスはこれらのオプションを使用してウィジェットを操作します。
このように組み合わせることで、UIの作成や制御を簡単かつ柔軟に行うことができます。
【例】
想像してください、あなたが料理アプリを開発しています。
player_ui
クラスは、アプリのユーザーインターフェース(UI)全体を管理し、player_ui_slot
構造体は各部品(ウィジェット)の配置と表示に関連します。
具体的な例として、アプリのメイン画面にはレシピリスト、検索バー、お気に入りのアイコンなどがあります。
この場合、player_ui
クラスはメイン画面全体を制御し、player_ui_slot
構造体は各部品の配置と表示方法を指定します。
例えば、player_ui_slot
構造体でレシピリストの設定を行うことができます。ZOrder
パラメータを使用して、レシピリストが画面上の他の要素よりも手前に表示されるようにします。
また、InputMode
パラメータを使用して、ユーザーがレシピリストをスクロールやタップで操作できるようにします。
そして、player_ui
クラスは部品の追加や削除を管理します。
たとえば、AddWidget
関数を使用して新しいウィジェット(例: レシピ詳細画面)をメイン画面に追加したり、RemoveWidget
関数を使用してウィジェット(例: お気に入りのアイコン)を削除したりすることができます。
この例では、player_ui
クラスがアプリのメイン画面を管理し、player_ui_slot
構造体が各部品の配置と表示方法を制御します。
料理アプリ開発では、player_ui
クラスと player_ui_slot
構造体の連携によって、メイン画面や部品の操作を柔軟に行うことが可能です。
player_ui
クラスはUI全体を管理し、player_ui_slot
構造体は個々のウィジェットの配置と表示方法の細かい設定を制御します。
player_ui
クラスはUIの構造やウィジェットの追加・削除を担当し、player_ui_slot
構造体は個々のウィジェットに関連するオプション(描画順序、入力モードなど)を指定するといった感じですね。


両者を組み合わせることで、UI全体の制御と個々のウィジェットの詳細設定を分けて管理できるということですね!
「エージェントが有効」の意味
クリックすると開きます。
Agent
が有効かどうかの「有効」とは、Agent
がプレイヤーに関連しており、プレイヤーが存在することを意味します。
以下の行でエージェントの有効性を検証しています。
if(ValidAgent := Agent?, Player := player[ValidAgent], PlayerUI := GetPlayerUI[Player]):
上記のコードでは、Agent
がnullでないかどうかをチェックし、ValidAgent
に代入します。
その後、player[ValidAgent]
を使用して関連するプレイヤーを取得し、GetPlayerUI[Player]
を使用してプレイヤーのUIを取得します。
これにより、エージェントが有効である場合にのみコードブロックが実行されます。
したがって、このコードではエージェントの有効性がプレイヤーの存在に関連していると言えます。
PlayerUI := GetPlayerUI[Player]の詳細
クリックすると開きます。
PlayerUI := GetPlayerUI[Player]
は、GetPlayerUI
関数を使用してPlayer
に関連するplayer_ui
を取得し、それをPlayerUI
変数に代入するコードです。
以下に、コードの詳細な解説を提供します。
PlayerUI := GetPlayerUI[Player]
の意味:PlayerUI
は変数です。- 代入演算子
:=
を使用して、GetPlayerUI[Player]
の結果がPlayerUI
に代入されます。
- 代入演算子
GetPlayerUI
は関数です。- この関数は引数として
Player
を取り、関連するplayer_ui
コンポーネントを返します。
- この関数は引数として
- 引数:
Player
は変数です。- 引数として
GetPlayerUI
関数に渡されます。 - この変数は、関連する
player_ui
を取得したいプレイヤーを指定します。
- 引数として
- 動作:
GetPlayerUI
関数は、与えられたPlayer
に関連するplayer_ui
コンポーネントを取得します。- この関数が成功すると、返された
player_ui
がPlayerUI
変数に代入されます。 - つまり、
PlayerUI
はPlayer
に関連するplayer_ui
を参照することになります。
- この関数が成功すると、返された
例えば、以下のような疑似コードを考えてみましょう:
Player = "player2"
PlayerUI := GetPlayerUI(Player)
上記のコードでは、Player
に"player2"
を指定してGetPlayerUI
関数を呼び出しています。
もし、player2
に関連するplayer_ui
が存在すれば、その関連するplayer_ui
がPlayerUI
に代入されます。
PlayerUI
変数は、以降のコードでそのplayer_ui
を使うことができます。
GetPlayerUI関数の詳細
クリックすると開きます。
GetPlayerUI
関数は、与えられたPlayer
に関連するplayer_ui
コンポーネントを返す関数です。ただし、Player
に関連付けられたplayer_ui
が存在しない場合は失敗します。
GetPlayerUI
関数の技術的な詳細は以下のとおり。
GetPlayerUI
関数の定義:
GetPlayerUI<native><public>(Player: player) -> player_ui
GetPlayerUI
関数は、ネイティブな実装であることを示す<native>
修飾子と、パブリックなアクセスレベルであることを示す<public>
修飾子を持ちます。Player: player
は、Player
という名前のパラメータがplayer
型であることを示しています。- このパラメータは、関連する
player_ui
を取得したいプレイヤーを指定します。
- このパラメータは、関連する
-> player_ui
は、関数の戻り値の型を示しており、player_ui
という型の値を返します。- パラメータ:
GetPlayerUI
関数は、以下のパラメータを取ります: Player
(player型):Player
は、関連するplayer_ui
を取得したいプレイヤーを指定します。- 動作:
GetPlayerUI
関数は、指定されたPlayer
に関連するplayer_ui
コンポーネントを返します。- ただし、もし
Player
に関連付けられたplayer_ui
が存在しない場合、関数は失敗します(エラーや例外を発生させる、または特定の値を返すなどの方法で失敗を示します)。
- ただし、もし
例えば、以下のような疑似コードを考えてみましょう:
Player = "player2"
PlayerUI = GetPlayerUI(Player)
上記のコードでは、Player
に"player2"
を指定してGetPlayerUI
関数を呼び出しています。
もし、player2
に関連するplayer_ui
が存在すれば、関連するplayer_ui
がPlayerUI
に代入されます。
player_ui
が存在しない場合、関数は失敗し、適切なエラーハンドリングが必要になります。
player_uiクラスの詳細
クリックすると開きます。
player_ui
クラスは、プレイヤーのUIにウィジェットを追加したり削除したりするための主要なインターフェースです。
player_ui
クラスの技術的な詳細と関連する情報は以下のとおりです。
player_uiクラスの概要
player_ui
クラスは、プレイヤーのUIに対してウィジェットを追加したり削除したりするためのメソッド(関数)を提供します。- ウィジェットは、プレイヤーのUI上に表示される、ボタンやテキストフィールドなどのインタラクティブな要素です。
player_ui
クラスは、UEFNplayer_ui
という名前のUE4(Unreal Engine 4)のクラスであり、Verse using statement
で使用されます。- 関数:
AddWidget
関数:AddWidget
関数は、デフォルトのplayer_ui_slot
の設定オプションを使用して、指定したウィジェットをplayer_ui
に追加します。player_ui_slot
は、ウィジェットをプレイヤーのUI上の特定のスロットに配置するための構成オプションを指定します。
AddWidget
関数(オーバーロード):AddWidget
関数は、指定したスロットにあるウィジェットを追加します。Slot
は、ウィジェットをプレイヤーのUI上の特定のスロットに配置するための構成オプションを指定します。
RemoveWidget
関数:RemoveWidget
関数は、指定したウィジェットをplayer_ui
から削除します。- ウィジェットは画面上から消え、プレイヤーのUIから関連付けられたウィジェットを取り除きます。
これらの関数を使用することで、プログラム上からプレイヤーのUIにウィジェットを追加したり削除したりすることができます。

MaybeMyUIPerPlayer文を記述する目的
クリックすると開きます。
MaybeMyUIPerPlayer
は、各プレイヤーごとにUIの状態を保持するための変数です。
目的は以下のとおり。
- プレイヤーごとに異なるUIを追跡するため:
MaybeMyUIPerPlayer
は、各プレイヤーが自分自身に関連付けられたUIを持っているかどうかを追跡するための辞書です。- それぞれのプレイヤーに対してUIの状態を保持するために利用されます。
- UIの追加と削除の管理:
OpenUI
関数内で、MaybeMyUIPerPlayer
は現在のプレイヤーに関連付けられたUIを管理し、UIの重複追加を防ぐために使用されます。- 該当プレイヤーがすでに既存のUIを持っている場合、古いUIを削除して新しいUIを追加します。
- プレイヤーのUIの取得:
OpenUI
関数では、MaybeMyUIPerPlayer
を使用して現在のプレイヤーに関連付けられたUIを取得します。- もしプレイヤーが既存のUIを持っている場合、それを取得して操作します。
これらの理由により、MaybeMyUIPerPlayer
は各プレイヤーごとのUIの管理と追跡に必要な変数となっています。
【例】
教室の席替えを管理している状況を想像してみましょう。学生のリストがあり、各学生がどの席に座っているかを追跡したいとします。
このシナリオでは以下のようなイメージです。
- 学生のリストはゲーム内のプレイヤーを表しています。
- 各プレイヤーのUIは教室の席に対応します。
これを実現する手順は以下のとおり。
- プレイヤーごとに異なるUIを追跡する:
- 教室の座席表のような辞書を使用します。
- 各プレイヤー(学生)が割り当てられたUI(席)と関連付けられるようにします。
- これにより、各プレイヤーが自分自身に関連付けられたUI(席)を持っているかどうかを追跡できます。
- UIの追加と削除の管理:
- 例えば、学生が席を変更した場合、座席表を更新します。
- 同様に、プレイヤーが新しいUIを開いた場合、重複したUIが発生しないように管理したいです。
- 教室の座席表(MaybeMyUIPerPlayer)を使用することで、同じUI(席)を複数のプレイヤーに割り当てることを防ぎ、現在のプレイヤーのみがUIにアクセスできるようにします。
- プレイヤーのUIの取得:
- 特定の学生の席にアクセスする必要がある場合、座席表(MaybeMyUIPerPlayer)を参照してそれに割り当てられた席(UI)を見つけることができます。
- プレイヤーが既にUI(席)を持っている場合は、それを取得して操作できます。
MaybeMyUIPerPlayerを座席表のような変数として使用することで、各プレイヤーごとのUIを効果的に管理し、教室の席替えのようにプレイヤーのUIの追跡ができます。

if(MyUI := MaybeMyUIPerPlayer[Player]?):の詳細
クリックすると開きます。
OpenUI(Agent : ?agent):void=
if(ValidAgent := Agent?, Player := player[ValidAgent], PlayerUI := GetPlayerUI[Player]):
if(MyUI := MaybeMyUIPerPlayer[Player]?):
PlayerUI.RemoveWidget(MyUI)
if(set MaybeMyUIPerPlayer[Player] = false) {}
else:
NewUI := CreateMyUI(ValidAgent)
PlayerUI.AddWidget(NewUI, player_ui_slot{InputMode := ui_input_mode.All})
if(set MaybeMyUIPerPlayer[Player] = option{NewUI}) {}
OpenUI(Agent : ?agent):void=
# エージェントが有効かどうかをチェックし、関連するプレイヤーとプレイヤーのUIを取得する
if(ValidAgent := Agent?, Player := player[ValidAgent], PlayerUI := GetPlayerUI[Player]):
# プレイヤーに対応するMaybeMyUIPerPlayerが存在するかどうかをチェックする
if(MyUI := MaybeMyUIPerPlayer[Player]?):
# PlayerUIから既存のウィジェットを削除する
PlayerUI.RemoveWidget(MyUI)
# MaybeMyUIPerPlayerをfalseに設定する(プレイヤーにUIが存在しない状態)
if(set MaybeMyUIPerPlayer[Player] = false) {}
else:
# エージェントに対して新しいUIを作成する
NewUI := CreateMyUI(ValidAgent)
# PlayerUIに新しいUIを指定したスロットとAllの入力モードで追加する
PlayerUI.AddWidget(NewUI, player_ui_slot{InputMode := ui_input_mode.All})
# MaybeMyUIPerPlayerを新しいUIを含むオプションに設定する
if(set MaybeMyUIPerPlayer[Player] = option{NewUI}) {}
上記のコードは、与えられたエージェントに関連するプレイヤーとプレイヤーのUIをチェックし、それに基づいて適切なアクションを実行するものです。
以下では、特定の部分について詳しく説明します。
if(MyUI := MaybeMyUIPerPlayer[Player]?):
PlayerUI.RemoveWidget(MyUI)
if(set MaybeMyUIPerPlayer[Player] = false) {}
この部分の目的は、プレイヤーに関連付けられたUIが存在する場合、それを削除および無効化することです。
具体的な手順を説明します。
MaybeMyUIPerPlayer[Player]
は、Player
に関連付けられたUIを表す変数またはオプションです。MaybeMyUIPerPlayer
は辞書やマップのようなデータ構造を想像してください。Player
がキーとなり、それに対応するUIが値となります。
MaybeMyUIPerPlayer[Player]?
は、MaybeMyUIPerPlayer[Player]
が存在する場合にその値(UI)を取得し、存在しない場合は別の値(通常はnull
またはNone
)を返す演算子です。- これにより、
MyUI
変数に関連するUIが代入されます。
- これにより、
- 条件文
if(MyUI := MaybeMyUIPerPlayer[Player]?):
は、MyUI
変数にUIが存在する場合に入るブロックです。- つまり、プレイヤーに関連付けられたUIが存在することを意味します。
PlayerUI.RemoveWidget(MyUI)
は、PlayerUI
のインスタンス(プレイヤーのUI)から、MyUI
(プレイヤーに関連付けられた既存のウィジェット)を削除するためのメソッドです。if(set MaybeMyUIPerPlayer[Player] = false) {}
は、MaybeMyUIPerPlayer[Player]
をfalse
に設定することによって、プレイヤーに関連付けられたUIが存在しない状態に変更します。- つまり、後続のコードで新しいUIを作成および追加できるようにします。
上記のコードは、プレイヤーに関連付けられたUIが存在する場合にはそれを削除し、存在しない場合には新しいUIを作成および追加するロジックを表しています。
これにより、プレイヤーに関連付けられたUIの状態を適切に管理できます。

set MaybeMyUIPerPlayer[Player] = falseの目的
クリックすると開きます。
OpenUI(Agent : ?agent):void=
# エージェントが有効かどうかをチェックし、関連するプレイヤーとプレイヤーのUIを取得する
if(ValidAgent := Agent?, Player := player[ValidAgent], PlayerUI := GetPlayerUI[Player]):
# プレイヤーに対応するMaybeMyUIPerPlayerが存在するかどうかをチェックする
if(MyUI := MaybeMyUIPerPlayer[Player]?):
# PlayerUIから既存のウィジェットを削除する
PlayerUI.RemoveWidget(MyUI)
# MaybeMyUIPerPlayerをfalseに設定する(プレイヤーにUIが存在しない状態)
if(set MaybeMyUIPerPlayer[Player] = false) {}
else:
# エージェントに対して新しいUIを作成する
NewUI := CreateMyUI(ValidAgent)
# PlayerUIに新しいUIを指定したスロットとAllの入力モードで追加する
PlayerUI.AddWidget(NewUI, player_ui_slot{InputMode := ui_input_mode.All})
# MaybeMyUIPerPlayerを新しいUIを含むオプションに設定する
if(set MaybeMyUIPerPlayer[Player] = option{NewUI}) {}
このプログラムの目的は、プレイヤーごとに関連付けられたUIの状態を管理することです。この特定のコードの目的は、プレイヤーのUIが存在しない状態を表現するためにfalse
を設定することです。
なぜUIが存在しない状態を表現する必要があるのかというと、コードの別の部分でそのプレイヤーに新しいUIを作成し、追加するためです。
具体的には、以下のコードによって新しいUIが作成されます。
NewUI := CreateMyUI(ValidAgent)
PlayerUI.AddWidget(NewUI, player_ui_slot{InputMode := ui_input_mode.All})
if(set MaybeMyUIPerPlayer[Player] = option{NewUI}) {}
最初のif
文のブロック内では、既存のUIを削除してから新しいUIを作成し、追加します。そして、MaybeMyUIPerPlayer[Player]
には新しいUIが含まれるオプション値(NewUI
)が設定されます。
しかし、もしMaybeMyUIPerPlayer[Player]
が既に別のUIを保持していた場合、既存のUIを削除する必要があります。
そのため、set MaybeMyUIPerPlayer[Player] = false
という行が実行されます。
これにより、MaybeMyUIPerPlayer[Player]
にはUIが存在しないことを示すためのfalse
が設定されます。
つまり、この一連のコードは次のような動作を行います。
MaybeMyUIPerPlayer[Player]
をチェックする。- UIが存在する場合は、既存のUIを削除する。
MaybeMyUIPerPlayer[Player]
をfalse
に設定し、プレイヤーのUIが存在しない状態にする。- 新しいUIを作成し、追加する。
このような手順によって、プレイヤーのUIを管理し、必要に応じて削除して再作成することができます。
既存のUIを削除する理由既存のUIを削除する理由は、プレイヤーごとに新しいUIを作成して追加するためです。新しいUIを追加する前に、以前のUIを削除する必要があります。
これにはいくつかの理由があります。
- メモリ管理:
- UIはメモリを使用します。古いUIを削除しないと、メモリリソースが無駄に使われ、プログラムのパフォーマンスが低下する可能性があります。
- 新しいUIを作成して追加する前に、メモリを解放する必要があります。
- 表示の整合性:
- 新しいUIを作成して追加する前に、古いUIを削除することで、画面上の表示が一貫している状態を保つことができます。
- たとえば、プレイヤーがゲーム内の設定を変更し、それに応じてUIの内容が変わる場合、古いUIを削除せずに新しいUIを作成して追加すると、画面上には古いUIと新しいUIが重なって表示されることになり、ユーザーにとって混乱を招く可能性があります。
- リソース消費:
- UIには描画やイベント処理に必要なリソースが関連付けられています。
- 古いUIを削除せずに新しいUIを作成して追加すると、リソースを重複して消費することになります。
- これは効率的なプログラミングの観点から望ましくありません。
以上の理由から、新しいUIを作成して追加する前に、以前のUIを削除しておく必要があります。
これにより、メモリ使用量の最適化や表示の整合性、リソースの効率的な利用が実現されます。

既存のUIを削除しない場合、以下のような問題が発生する可能性があります。
- メモリリーク:
- UIはメモリを使用します。
- 既存のUIを削除せずに新しいUIを作成して追加すると、メモリが解放されずにリークする可能性があります。
- 繰り返しUIを作成する場合、メモリリークが蓄積し、プログラム全体のパフォーマンスに悪影響を及ぼす可能性があります。
- リソースの浪費:
- 既存のUIを削除せずに新しいUIを作成して追加すると、既存のUIと新しいUIの両方が同時にリソースを消費することになります。
- これにより、メモリやグラフィックス処理などの重要なリソースが無駄に使われ、プログラムのパフォーマンスが低下する可能性があります。
- 表示の混乱:
- 既存のUIが残ったまま新しいUIを作成して追加すると、画面上で古いUIと新しいUIが重なって表示される可能性があります。
- これにより、ユーザーが正しく操作できなくなったり、情報が重複して表示されたりして、ユーザーエクスペリエンスが悪化する可能性があります。
- バグの発生:
- 既存のUIを削除せずに新しいUIを追加する場合、プログラムの他の部分が誤ったUIを参照する可能性があります。
- これにより、期待しない動作やエラーが発生し、プログラムが正常に動かなくなる可能性があります。
このため、UIを適切に管理するためには、古いUIを削除してから新しいUIを作成し追加することが重要です。
要するに、既存のUIを削除せずに新しいUIを作成して追加すると、メモリリークやリソースの浪費、表示の混乱、バグなどの問題が発生する可能性があります。

要素にアクセスするための「?」
クリックすると開きます。
OpenUI(Agent : ?agent):void=
# エージェントが有効かどうかをチェックし、関連するプレイヤーとプレイヤーのUIを取得する
if(ValidAgent := Agent?, Player := player[ValidAgent], PlayerUI := GetPlayerUI[Player]):
# プレイヤーに対応するMaybeMyUIPerPlayerが存在するかどうかをチェックする
if(MyUI := MaybeMyUIPerPlayer[Player]?):
# PlayerUIから既存のウィジェットを削除する
PlayerUI.RemoveWidget(MyUI)
# MaybeMyUIPerPlayerをfalseに設定する(プレイヤーにUIが存在しない状態)
if(set MaybeMyUIPerPlayer[Player] = false) {}
else:
# エージェントに対して新しいUIを作成する
NewUI := CreateMyUI(ValidAgent)
# PlayerUIに新しいUIを指定したスロットとAllの入力モードで追加する
PlayerUI.AddWidget(NewUI, player_ui_slot{InputMode := ui_input_mode.All})
# MaybeMyUIPerPlayerを新しいUIを含むオプションに設定する
if(set MaybeMyUIPerPlayer[Player] = option{NewUI}) {}
?
演算子は、辞書やリストなどの要素にアクセスする際に使用されます。上記のコードの場合、MaybeMyUIPerPlayer[Player]
が辞書MaybeMyUIPerPlayer
のキーPlayer
に対応する値を持っているかどうかをチェックしています。
具体的には、次の行でこのチェックが行われています。
if (MyUI := MaybeMyUIPerPlayer[Player]?):
もしMaybeMyUIPerPlayer[Player]
が存在する場合、その値がMyUI
に割り当てられます。もし存在しない場合、MyUI
はnull
またはNone
になります。
このようにして、MyUI
を通じて辞書の値にアクセスし、存在を確認することができます。条件文によってプレイヤーに対応するUIの存在を判断し、適切な処理を行うことができます。
PlayerUI.RemoveWidget(MyUI)とif(set MaybeMyUIPerPlayer[Player] = false) {}:の目的の違い
クリックすると開きます。
両者のコードの目的の違いは以下のとおりです。
PlayerUI.RemoveWidget(MyUI)
:
- 目的:
- プレイヤーのUIから特定のウィジェットを削除することです。
- 実行内容:
PlayerUI
から変数MyUI
が示す既存のウィジェットを削除します。
- 結果:
PlayerUI
上のプレイヤーのUIから、指定されたウィジェットが削除されます。
if(set MaybeMyUIPerPlayer[Player] = false) {}
:
- 目的:
- プレイヤーにUIが存在しない状態を表現することです。
- 実行内容:
MaybeMyUIPerPlayer
辞書のキーPlayer
に対応する値をfalse
に設定します。
- 結果:
- 辞書
MaybeMyUIPerPlayer
において、プレイヤーに対応するUIを示す値がfalse
になります。
- 辞書
要約すると、PlayerUI.RemoveWidget(MyUI)
は実際のUI上の特定のウィジェットを削除する操作ですが、if(set MaybeMyUIPerPlayer[Player] = false) {}
はUIの存在状態を示す辞書値を変更し、プレイヤーにUIが存在しないことを示します。
【例】
仮想的なショッピングアプリを考えてみましょう。プレイヤーはユーザーのことを指し、PlayerUIはユーザーが商品を表示するためのインターフェース(画面やウィンドウ)です。
MaybeMyUIPerPlayerは、各ユーザーに対応するUIの状態を保持するデータ構造であり、プレイヤーごとに存在・非存在を示します。
PlayerUI.RemoveWidget(MyUI)
の例え話:- ユーザーがイメージを持ちやすいショッピングカートの表示を考えてみましょう。
- ショッピングカートには商品が色々と入っていますが、ユーザーが特定の商品を取り除きたいとき、それを
PlayerUI.RemoveWidget(MyUI)
に例えることができます。 - 例えば、ユーザーがカート内のりんごを削除したい場合、この操作はカートからりんごを取り除くイメージです。
- すると、カートの中にはりんごがなくなり、カートの表示が更新されます。
if(set MaybeMyUIPerPlayer[Player] = false) {}
の例え話:- ユーザーがショッピングアプリを終了する時に、カートの表示を消すイメージを考えてみます。
- この場合、ユーザーはカートを表示せずにアプリを閉じますが、次回アプリを開いたときにはカートが初期状態に戻ります。
if(set MaybeMyUIPerPlayer[Player] = false) {}
は、ユーザーがカートを閉じたことを表しています。- これにより、ユーザーにはカートが存在していない状態が示されます。
- そして、アプリを再度開いたときには、アプリ側でカートの情報が初期化(消えて元の状態に戻る)されるイメージです。
以上の例え話により、1つ目のコードは特定の商品をカートから取り除くことを目的としており、2つ目のコードはカートの存在状態を管理することを目的としていることが理解できると思います。
MaybeMyUIPerPlayer
は、プレイヤーごとにUIの存在状態を管理するための辞書やマップのようなものです。
座席表のイメージが近いですね。

座席表では、各席が誰によって占有されているか、あるいは空席であるかを示すことができます。
同様に、MaybeMyUIPerPlayer
は各プレイヤーに対してUIの存在状態を追跡します。
例えば、MaybeMyUIPerPlayer[Player]
がtrue
であれば、そのプレイヤーにはUIが存在することを、false
であればUIが存在しないことを示します。
座席表では、プレイヤーや人々が座席に座ることで場所の利用状況が変化します。
同様に、MaybeMyUIPerPlayer
でもプレイヤーがUIを利用することでUIの存在状態が変化します。
UIを表示してプレイヤーに提供する場合は、MaybeMyUIPerPlayer[Player]
をtrue
に設定します。逆に、UIを削除したい場合はMaybeMyUIPerPlayer[Player]
をfalse
に設定します。
要するに、座席表が各席の利用状況を管理するものであるように、MaybeMyUIPerPlayer
は各プレイヤーごとにUIの存在状態を管理するものです。プレイヤーがUIを利用するかどうかを追跡するために使用されます。
if(MyUI := MaybeMyUIPerPlayer[Player]?):のMaybeMyUIPerPlayerに[Player]とつけて呼び出す理由
クリックすると開きます。
OpenUI(Agent : ?agent):void=
# エージェントが有効かどうかをチェックし、関連するプレイヤーとプレイヤーのUIを取得する
if(ValidAgent := Agent?, Player := player[ValidAgent], PlayerUI := GetPlayerUI[Player]):
# プレイヤーに対応するMaybeMyUIPerPlayerが存在するかどうかをチェックする
if(MyUI := MaybeMyUIPerPlayer[Player]?):
# PlayerUIから既存のウィジェットを削除する
PlayerUI.RemoveWidget(MyUI)
# MaybeMyUIPerPlayerをfalseに設定する(プレイヤーにUIが存在しない状態)
if(set MaybeMyUIPerPlayer[Player] = false) {}
else:
# エージェントに対して新しいUIを作成する
NewUI := CreateMyUI(ValidAgent)
# PlayerUIに新しいUIを指定したスロットとAllの入力モードで追加する
PlayerUI.AddWidget(NewUI, player_ui_slot{InputMode := ui_input_mode.All})
# MaybeMyUIPerPlayerを新しいUIを含むオプションに設定する
if(set MaybeMyUIPerPlayer[Player] = option{NewUI}) {}
if(MyUI := MaybeMyUIPerPlayer[Player]?):
のMaybeMyUIPerPlayer[Player]
は、MaybeMyUIPerPlayer
という辞書(マップ)から特定のキー(この場合はPlayer
)に対応する値を取得するための記述です。
これによって、特定のプレイヤーに関連するUIを取得できます。
もしMaybeMyUIPerPlayer
自体が単なる変数であれば、MyUI := MaybeMyUIPerPlayer?
のように書くことができます。
今回のコードではMaybeMyUIPerPlayer
が辞書(マップ)として宣言されています。
辞書はキーと値のペアを保持するデータ構造であり、MaybeMyUIPerPlayer[Player]
という表記を使用することで、Player
というキーに対応する値を取得することができます。
この場合、Player
はValidAgent
から導かれるプレイヤーの識別子(ID)であり、そのプレイヤーに関連するUIを取得するために使用されています。
MaybeMyUIPerPlayer[Player]
は、辞書内のキーがPlayer
に一致する値を取得するという意味です。
この記法を使うことで、特定のプレイヤーに関連付けられたUIが存在するかどうかを確認し、その有無に応じて条件分岐を行うことができます。

PlayerUI.RemoveWidget(MyUI)の詳細
クリックすると開きます。
PlayerUI.RemoveWidget(MyUI)
は、プレイヤーのUIから特定のウィジェット(UIの一部)を削除するための処理です。
具体的には、以下の手順で行われます。
PlayerUI
は、特定のプレイヤーに関連付けられたUIを表します。MyUI
は、削除したいウィジェットを指定します。- つまり、
PlayerUI
から削除したいUIの一部を示しています。
- つまり、
PlayerUI.RemoveWidget(MyUI)
は、PlayerUI
からMyUI
に指定されたウィジェットを削除する命令です。
ウィジェットの削除により、プレイヤーのUIからその特定の要素が除去されます。これにより、UIの表示や機能が変更される可能性があります。
例えば、ゲームのUIを考えると、プレイヤーのスコア表示があるウィジェットを削除する場合、MyUI
にはスコア表示に関連するUI要素が指定されます。
そして、PlayerUI.RemoveWidget(MyUI)
が実行されると、スコア表示が削除され、プレイヤーのUIにはスコア表示が表示されなくなります。
重要な点は、MyUI
が削除されるだけで、実際のUI要素そのものが削除されるわけではないことです。そのため、後で必要になったとしても、削除された要素を再び追加することが可能です。
プログラミング的な見方では、上記の処理は条件文 if(MyUI := MaybeMyUIPerPlayer[Player]?):
内にある else
ブロックの一部として実行され、必要な場合にのみウィジェットが削除されます。
RemoveWidget関数の詳細
クリックすると開きます。
RemoveWidget
関数は、プレイヤーのUIからウィジェット(UIの一部)を削除するための機能です。
以下に詳細を説明します。
関数名: RemoveWidget
構文:
RemoveWidget(Widget: widget)
パラメーター:
Widget
(ウィジェット):削除したいUI要素(ウィジェット)を指定します。
機能:
RemoveWidget
関数は、指定されたウィジェットをプレイヤーのUIから削除します。- ウィジェットを削除することで、プレイヤーのUIの表示や機能が変更されます。
例えば、ゲームのUIでスコア表示のウィジェットを削除する場合、「RemoveWidget」関数にスコア表示に関連するウィジェットを指定します。
この関数が実行されると、スコア表示がUIから削除され、プレイヤーはスコアを表示するUI要素を見ることができなくなります。
プログラムの中での利用方法:
RemoveWidget
関数は通常、UIフレームワーク(例えば、Unreal Engineのようなゲーム開発エンジン)で使用されます。- 開発者は、プレイヤーのUIオブジェクト(例えば、
PlayerUI
)を操作して、不要なウィジェットを削除するためにこの関数を呼び出します。 RemoveWidget
関数の引数には、削除したいウィジェットオブジェクト(例えば、MyUI
)を指定します。
要点:
RemoveWidget
関数は、指定されたウィジェットをプレイヤーのUIから削除します。- ウィジェットが削除された後でも、必要になった場合は再度追加することができます。
if(set MaybeMyUIPerPlayer[Player] = false) {}の詳細
クリックすると開きます。
OpenUI(Agent : ?agent):void=
# エージェントが有効かどうかをチェックし、関連するプレイヤーとプレイヤーのUIを取得する
if(ValidAgent := Agent?, Player := player[ValidAgent], PlayerUI := GetPlayerUI[Player]):
# プレイヤーに対応するMaybeMyUIPerPlayerが存在するかどうかをチェックする
if(MyUI := MaybeMyUIPerPlayer[Player]?):
# PlayerUIから既存のウィジェットを削除する
PlayerUI.RemoveWidget(MyUI)
# MaybeMyUIPerPlayerをfalseに設定する(プレイヤーにUIが存在しない状態)
if(set MaybeMyUIPerPlayer[Player] = false) {}
else:
# エージェントに対して新しいUIを作成する
NewUI := CreateMyUI(ValidAgent)
# PlayerUIに新しいUIを指定したスロットとAllの入力モードで追加する
PlayerUI.AddWidget(NewUI, player_ui_slot{InputMode := ui_input_mode.All})
# MaybeMyUIPerPlayerを新しいUIを含むオプションに設定する
if(set MaybeMyUIPerPlayer[Player] = option{NewUI}) {}
「# MaybeMyUIPerPlayerをfalseに設定する(プレイヤーにUIが存在しない状態)
この部分の目的は、プレイヤーに関連するUIが存在しない状態を表現するために、MaybeMyUIPerPlayer
という変数をfalse
に設定することです。
具体的にどのように動作するかを説明します:
MaybeMyUIPerPlayer
は、プレイヤーごとにUIを格納するための辞書(ディクショナリ)やマップのようなものです。- キーとなる要素は
Player
であり、値としてはUIを表すオブジェクト(ウィジェット)が格納されるか、またはfalse
が格納されます。
- キーとなる要素は
MaybeMyUIPerPlayer[Player]
が現在MyUI
(UIオブジェクト)を持たずに存在しなかった場合、その値はfalse
になっています。- 上記のコードでは、既存のUIが存在する場合(
MaybeMyUIPerPlayer[Player]
がMyUI
を返す場合)、そのUIを削除した後に、MaybeMyUIPerPlayer[Player]
をfalse
に設定しています。 if(set MaybeMyUIPerPlayer[Player] = false) {}
の部分では、MaybeMyUIPerPlayer
におけるPlayer
キーの値をfalse
に設定しようとしています。- ただし、この設定の結果は特に利用されません(
{}
は空のブロックを表し、何も実行されません)。
- ただし、この設定の結果は特に利用されません(
- これにより、
MaybeMyUIPerPlayer[Player]
にfalse
が格納されることで、プレイヤーに関連するUIが存在しないことを示しています。
要するに、このコードは、既存のUIが存在する場合には削除し、その後MaybeMyUIPerPlayer
をfalse
に設定して、プレイヤーに関連するUIが存在しない状態を表現していると言えます。

else~NewUI := CreateMyUI(ValidAgent)の詳細
クリックすると開きます。
OpenUI(Agent : ?agent):void=
# エージェントが有効かどうかをチェックし、関連するプレイヤーとプレイヤーのUIを取得する
if(ValidAgent := Agent?, Player := player[ValidAgent], PlayerUI := GetPlayerUI[Player]):
# プレイヤーに対応するMaybeMyUIPerPlayerが存在するかどうかをチェックする
if(MyUI := MaybeMyUIPerPlayer[Player]?):
# PlayerUIから既存のウィジェットを削除する
PlayerUI.RemoveWidget(MyUI)
# MaybeMyUIPerPlayerをfalseに設定する(プレイヤーにUIが存在しない状態)
if(set MaybeMyUIPerPlayer[Player] = false) {}
else:
# エージェントに対して新しいUIを作成する
NewUI := CreateMyUI(ValidAgent)
# PlayerUIに新しいUIを指定したスロットとAllの入力モードで追加する
PlayerUI.AddWidget(NewUI, player_ui_slot{InputMode := ui_input_mode.All})
# MaybeMyUIPerPlayerを新しいUIを含むオプションに設定する
if(set MaybeMyUIPerPlayer[Player] = option{NewUI}) {}
この部分の目的は、エージェントに対して新しいUIを作成し、それを変数NewUI
に代入することです。
具体的には以下のとおり。
CreateMyUI(ValidAgent)
は、エージェントに対して新しいUIを作成するための関数もしくはメソッドです。- この関数は、引数として
ValidAgent
を受け取り、ValidAgent
を基に新しいUIを作成します。
- この関数は、引数として
NewUI := CreateMyUI(ValidAgent)
という行では、CreateMyUI(ValidAgent)
の実行結果(つまり、新しいUIオブジェクト)をNewUI
という変数に代入しています。- これにより、変数
NewUI
には新しく作成されたUIオブジェクトが格納されます。
- これにより、変数
要するに、このコードは、ValidAgent
を基にして新しいUIを作成し、その結果を変数NewUI
に代入しています。この新しいUIは後続の処理で使用され、PlayerUI
に追加されます。
PlayerUI.AddWidget(NewUI~er[Player] = option{NewUI}) {}の詳細│CreateMyUIの定義(含)
クリックすると開きます。
このコードブロックは、エージェントの有効性をチェックし、関連するプレイヤーとそのプレイヤーのUIを取得します。
OpenUI(Agent : ?agent):void=
# エージェントが有効かどうかをチェックし、関連するプレイヤーとプレイヤーのUIを取得する
if(ValidAgent := Agent?, Player := player[ValidAgent], PlayerUI := GetPlayerUI[Player]):
# プレイヤーに対応するMaybeMyUIPerPlayerが存在するかどうかをチェックする
if(MyUI := MaybeMyUIPerPlayer[Player]?):
# PlayerUIから既存のウィジェットを削除する
PlayerUI.RemoveWidget(MyUI)
# MaybeMyUIPerPlayerをfalseに設定する(プレイヤーにUIが存在しない状態)
if(set MaybeMyUIPerPlayer[Player] = false) {}
else:
# エージェントに対して新しいUIを作成する
NewUI := CreateMyUI(ValidAgent)
# PlayerUIに新しいUIを指定したスロットとAllの入力モードで追加する
PlayerUI.AddWidget(NewUI, player_ui_slot{InputMode := ui_input_mode.All})
# MaybeMyUIPerPlayerを新しいUIを含むオプションに設定する
if(set MaybeMyUIPerPlayer[Player] = option{NewUI}) {}
- 最初の条件文 (
if
) の中身は、変数ValidAgent
にエージェントが設定されているかどうかをチェックし、そのエージェントに関連するプレイヤー (Player
) とプレイヤーのUI (PlayerUI
) を取得します。 - 次の条件文 (
if
) の中身は、プレイヤーに対応するMaybeMyUIPerPlayer
が既に存在するかどうかをチェックします。MaybeMyUIPerPlayer
はプレイヤーごとにUIの有無を追跡するためのオプションです。
- もし既にUIが存在する場合 (
MaybeMyUIPerPlayer[Player]
)、そのUIを削除します (PlayerUI.RemoveWidget(MyUI)
)。- そして、
MaybeMyUIPerPlayer
をfalse
に設定して、プレイヤーにはUIが存在しない状態にします。
- そして、
- もしUIが存在しない場合、新しいUIを作成し (
CreateMyUI(ValidAgent)
)、PlayerUI
にその新しいUIを指定したスロット (player_ui_slot
) とAll
の入力モード (InputMode := ui_input_mode.All
) で追加します (PlayerUI.AddWidget(NewUI, player_ui_slot{InputMode := ui_input_mode.All})
)。- そして、
MaybeMyUIPerPlayer
を新しいUIを含むオプションに設定します。
- そして、
関連するコードの順番でお答えします。
【1】PlayerUI.AddWidget(NewUI, player_ui_slot{InputMode := ui_input_mode.All})
:
PlayerUI
は、UIを管理するためのオブジェクトやクラスを指します。AddWidget
は、PlayerUI
に新しいウィジェット(NewUI
)を追加するメソッドや関数です。player_ui_slot{InputMode := ui_input_mode.All}
は、ウィジェットの表示方法に関する詳細設定を指定するための構造体です。- ここでは、
InputMode
をui_input_mode.All
に設定しています。
- ここでは、
【2】if(set MaybeMyUIPerPlayer[Player] = option{NewUI}) {}
:
MaybeMyUIPerPlayer
は、プレイヤーごとにUIの有無を追跡するためのオプションです。option{NewUI}
は、新しいUI (NewUI
) を含むオプションを作成します。set MaybeMyUIPerPlayer[Player] = option{NewUI}
は、プレイヤーに関連するオプションMaybeMyUIPerPlayer
に新しいUIを含むオプションを設定します。
要約すると、このコードは、プレイヤーに関連付けられたUIが存在しない場合、PlayerUI
に新しいUIウィジェットを追加します。入力モードは All
に設定され、MaybeMyUIPerPlayer
オプションも更新されます。
プレイヤーが既にUIを持っている場合、コードは既存のUIウィジェットを PlayerUI
から削除し、MaybeMyUIPerPlayer
オプションをUIが存在しない状態に更新します。
(別記事にジャンプします。)
AddWidgetの詳細
クリックすると開きます。
AddWidget関数は、プレイヤーのユーザーインターフェース(PlayerUI)にウィジェット(Widget)を追加するための関数です。この関数を使用することで、ゲームやアプリケーション内でカスタムのUI要素を作成し、プレイヤーに表示することができます。
AddWidget関数の詳細を説明します:
- 関数名:
- AddWidget
- 戻り値の型:
- void (何も返さない)
- パラメータ:
- Widget:
- 追加するウィジェットのインスタンスです。
- ウィジェットはユーザーインターフェースの要素であり、ボタン、テキストボックス、イメージなどのコントロールが含まれます。
- Slot:
- ウィジェットの設定オプションを指定するスロットです。
- スロットはウィジェットの配置やインタラクションの方法を制御します。
AddWidget関数の使い方:
- AddWidget関数を呼び出す前に、PlayerUIという名前の変数でユーザーインターフェース(PlayerUI)を取得しておく必要があります。
- 追加したいウィジェットのインスタンスを作成します。
- 例えば、ボタンやイメージのウィジェットを作成します。
- Slotに関連する設定オプションを作成し、ウィジェットの配置や入力方法を指定します。
- 例えば、ウィジェットを特定の場所に配置するか、どの入力モードで反応するかを指定します。
- AddWidget関数を呼び出し、WidgetとSlotを指定します。
- これにより、ウィジェットがPlayerUIに追加され、プレイヤーの画面上に表示されます。
AddWidget関数は、ゲームやアプリケーションの開発者がユーザーインターフェースを柔軟に設定し、カスタマイズするための便利な機能です。
例えば、ゲーム内のキャラクターのステータスを表示するためのボタンや、クエストの進行状況を示すプログレスバーを追加することができます。
つまり、AddWidget関数は、PlayerUIにウィジェットを追加するための関数です。

player_ui_slotの詳細
クリックすると開きます。
player_ui_slot構造体は、ウィジェットの作成設定オプションを保持するためのデータ構造です。
player_ui_slot構造体の詳細を説明します:
- 構造体名:
- player_ui_slot
- メンバー:
- player_ui_slot構造体には、データメンバーがありますが、関数はありません。
- データメンバー:
- ZOrder(整数型):
- ウィジェットのレンダリング順序を制御します。
- 値が大きいものが手前に描画されます。
- つまり、他のウィジェットや要素よりも前面に表示されるウィジェットを作成する場合、ZOrder値を大きく設定します。
- InputMode(ui_input_mode型):
- ウィジェットの入力イベントの消費を制御します。
- ウィジェットがユーザーの入力を受け取るかどうかや、どのように応答するかを制御します。
player_ui_slot構造体は、ウィジェットの作成時に使用され、ウィジェットの表示順序や入力イベントの振る舞いなどを設定するためのオプションを提供します。
例えば、ゲーム内のUI要素としてスコア表示のウィジェットを作成する場合、以下のようにplayer_ui_slot構造体を使用して設定できます:
- ZOrderを使用して、他の要素よりも前面に表示するようにウィジェットの表示順序を指定します。
- たとえば、他の要素がZOrder値4以下の場合、スコア表示のウィジェットにZOrder値を5以上設定すると、スコア表示が他の要素の上に描画されます。
- InputModeを使用して、ユーザーの入力イベントの振る舞いを制御します。
- スコア表示のウィジェットがユーザーの入力を受け取る必要がある場合、InputModeを適切な設定に変更します。
player_ui_slot構造体は、ウィジェットのカスタマイズやインタラクションの設定に役立ちます。
開発者はこれを使用して、ゲームやアプリケーションのユーザーインターフェースを柔軟に制御することができます。
【イメージ】
player_ui_slot構造体は、ウィジェットの作成時に使用され、表示順序や入力イベントの振る舞いを制御します。例として、ゲーム内にスコア表示のウィジェットを作成する場面を考えてみましょう。
// player_ui_slot構造体の定義
struct player_ui_slot
{
int ZOrder; // ウィジェットの表示順序
ui_input_mode InputMode; // ウィジェットの入力モード
};
// player_ui_slot構造体の使い方の例
void CreateScoreWidget()
{
player_ui_slot ScoreSlot; // player_ui_slot構造体のインスタンスを作成
ScoreSlot.ZOrder = 5; // スコアウィジェットを他の要素の上に表示するためにZOrder値を設定
ScoreSlot.InputMode = ui_input_mode::Enabled; // スコアウィジェットがユーザーの入力を受け取るための設定
// スコアウィジェットの作成とplayer_ui_slotの設定を実際のコードで実行する
CreateWidget(ScoreWidgetClass, ScoreSlot);
}
この具体例では、以下のようなプロセスでスコア表示のウィジェットを作成しています:
player_ui_slot ScoreSlot;
のようにplayer_ui_slot構造体のインスタンスを作成します。ScoreSlot.ZOrder = 5;
と書くことで、スコアウィジェットを他の要素の上に表示するためにZOrderの値を5に設定します。- ZOrder値が大きいほど、要素は前面に描画されます。
ScoreSlot.InputMode = ui_input_mode::Enabled;
と書くことで、スコアウィジェットがユーザーの入力を受け取ることができるようにInputModeをEnabled(有効)に設定します。CreateWidget(ScoreWidgetClass, ScoreSlot);
という関数(ここでは仮想的な関数として使っています)を呼び出して、スコアウィジェットの作成とplayer_ui_slotの設定を実行します。
この例では、スコアウィジェットを作成する際に、表示順序(ZOrder値)と入力モード(InputMode)をplayer_ui_slot構造体で指定しています。
これにより、ゲーム内でスコアウィジェットが他の要素の上に表示され、ユーザーの入力を受け取ることができるようになります。
このように、player_ui_slot構造体は、ウィジェットの作成時にさまざまな設定を行うための手段として使われます。
設定パラメータにはZOrder(表示順序)やInputMode(入力モード)などがあり、これらの値を変更することでウィジェットの見た目や動作を自由にカスタマイズすることができます。

ui_input_mode列挙型の詳細
クリックすると開きます。
ui_input_modeは、ウィジェットの入力消費モードを表す列挙型です。
ui_input_mode列挙型には、次の列挙子が含まれています:
- None:
- ウィジェットは入力を消費しません。
- つまり、ウィジェット上の入力は他の要素にも渡されます。
- 例えば、ウィジェット上でクリックした場合、そのクリックイベントはウィジェット外の要素にも伝わります。
- All:
- ウィジェットはすべての入力を消費します。
- つまり、ウィジェット上での入力はウィジェット内で完全に処理され、他の要素には伝播しません。
- 例えば、ウィジェット上でクリックした場合、そのクリックイベントは他の要素に伝わりません。
このui_input_mode列挙型は、ウィジェットが入力イベントをどのように処理するかを指定するために使用されます。
例えば、Noneの場合は、ウィジェット上での入力がゲームプレイに影響を与える他の要素にも伝えることができるため、ウィジェットが透明な領域にある場合などに便利です。
一方、Allの場合は、ウィジェット内での入力が独立して処理されるため、そのウィジェット上でのみ反応させたい場合に使用します。
【噛み砕くと】
ui_input_modeは、ウィジェット(画面上の部品やボタンのようなもの)が入力(例えば、クリックやタッチ)をどのように扱うかを指定するものです。
このui_input_modeには、「None」と「All」という2つの設定があります。
- None(なし):
- ウィジェットがNoneの場合、ウィジェット上での入力は他の要素にも伝わります。
- たとえば、ウィジェット上でクリックすると、そのクリックがウィジェット以外の場所にも影響を与えます。
- ウィジェットが透明な場所にあるときなどに使われます。
- All(すべて):
- ウィジェットがAllの場合、ウィジェット上での入力はウィジェット内だけで処理され、他の要素には伝わりません。
- たとえば、ウィジェット上でクリックすると、そのクリックは他の要素には影響を与えません。
- ウィジェット上で独自の動作をしたいときに使われます。
つまり、ui_input_modeは、ウィジェットが入力をどのように扱うかを選ぶための設定です。
ウィジェットを使ってゲームやアプリを作るときに、どのようにユーザーと対話するかを制御するために使われます。

【イメージ】
- None(なし)の場合の別の例:
- スマートフォンのホーム画面でアプリアイコンを長押ししてアンインストールする場合、アイコンがNoneの設定になっていると、アイコン以外の場所をタップしてもアプリはアンインストールされず、他の操作が行われます。
- 地図アプリでピンチジェスチャーを使ってズームイン/ズームアウトする際、地図がNoneの設定になっていると、地図領域以外をピンチしてもズームイン/ズームアウトは実行されず、他のアクションが反応します。
- All(すべて)の場合の別の例:
- ウェブブラウザでリンクをクリックして新しいタブで開く場合、リンクがAllの設定になっていると、リンク以外の場所をクリックしても新しいタブでの開く操作が優先され、他の操作は影響を受けません。
- メディアプレーヤーでメディアファイルを再生する際、再生ボタンがAllの設定になっていると、再生ボタンのみをクリックして再生するだけで、他の要素には影響を与えず、メディアの再生が優先されます。
入力モード設定は、特定の操作(クリック、タップ、ジェスチャーなど)がどの範囲で有効であるかを示しています。

具体的には、None(なし)の場合は指定した要素のみで操作が有効になり、その要素の外側をクリックまたはタップしても操作が無視されます。
一方、All(すべて)の場合は操作が全体の範囲で有効であり、指定した要素以外をクリックまたはタップしても影響を与えません。
入力モード設定は、ユーザーが特定の操作を行う際に意図しない効果を避けるために使用されます。要素の境界を定義することで、操作の対象となる領域を制限することができます。
PlayerUI.AddWidget(NewUI, player_ui_slot{InputMode := ui_input_mode.All})を記述する理由
クリックすると開きます。
このコードの PlayerUI.AddWidget(NewUI, player_ui_slot{InputMode := ui_input_mode.All})
は、新しいUI(NewUI)をプレイヤーのUIに追加する際に、入力モードを"All"に設定するためのものです。
UI(ユーザーインターフェース)を持つゲームやアプリでは、プレイヤーがUI要素を操作する必要があります。
しかし、UI要素が他の要素や操作と競合することを避けるために、UI要素の範囲に対して入力モードを設定する必要があります。
入力モードの設定には、主に2つのオプションがあります。それは"All"と"None"です。
- "All"の場合は、UI要素が表示されている領域全体で操作が有効になります。
- つまり、UI要素をタップまたはクリックしなくても、UI要素の範囲内のどこでも操作が反応します。
- "None"の場合は、UI要素の範囲外では操作が無効になります。
- つまり、UI要素以外の領域をタップまたはクリックしても、UI要素に対する操作は無視されます。
コードの PlayerUI.AddWidget(NewUI, player_ui_slot{InputMode := ui_input_mode.All})
の部分では、新しいUI要素(NewUI)を既存のプレイヤーUI(PlayerUI)に追加しています。
そして、player_ui_slot{InputMode := ui_input_mode.All}
によって入力モードを"All"に設定しています。これにより、新しいUI要素はプレイヤーのUI全体で操作が有効になります。
入力モードを設定することで、ユーザーがUI要素を直感的に操作できるようになります。
具体的には、タップした場所に関係なく、UI要素内のどの部分をタップしても同じ操作が実行されるため、ユーザーエクスペリエンスが向上します。

if(set MaybeMyUIPerPlayer[Player] = option{NewUI}) {}の詳細
クリックすると開きます。
OpenUI(Agent : ?agent):void=
# エージェントが有効かどうかをチェックし、関連するプレイヤーとプレイヤーのUIを取得する
if(ValidAgent := Agent?, Player := player[ValidAgent], PlayerUI := GetPlayerUI[Player]):
# プレイヤーに対応するMaybeMyUIPerPlayerが存在するかどうかをチェックする
if(MyUI := MaybeMyUIPerPlayer[Player]?):
# PlayerUIから既存のウィジェットを削除する
PlayerUI.RemoveWidget(MyUI)
# MaybeMyUIPerPlayerをfalseに設定する(プレイヤーにUIが存在しない状態)
if(set MaybeMyUIPerPlayer[Player] = false) {}
else:
# エージェントに対して新しいUIを作成する
NewUI := CreateMyUI(ValidAgent)
# PlayerUIに新しいUIを指定したスロットとAllの入力モードで追加する
PlayerUI.AddWidget(NewUI, player_ui_slot{InputMode := ui_input_mode.All})
# MaybeMyUIPerPlayerを新しいUIを含むオプションに設定する
if(set MaybeMyUIPerPlayer[Player] = option{NewUI}) {}
if(set MaybeMyUIPerPlayer[Player] = option{NewUI}) {}
は、MaybeMyUIPerPlayer[Player]
を新しいUI (NewUI
) を含むオプションに設定するためのコードです。
このコードの目的は、プレイヤーごとに関連するUI要素 (MaybeMyUIPerPlayer
) を管理することです。MaybeMyUIPerPlayer
は、プレイヤーごとにUI要素が存在するかどうかを示す変数で、option
型というオプションの値を持ちます。
コードの一部である set MaybeMyUIPerPlayer[Player] = option{NewUI}
は、MaybeMyUIPerPlayer
の値を新しいUI (NewUI
) を含むオプションに設定しています。これにより、プレイヤーにUI要素が存在することを示します。
以下は、解説の詳細です。
MaybeMyUIPerPlayer[Player] = option{NewUI}
:- この部分では、
MaybeMyUIPerPlayer[Player]
の値をoption{NewUI}
に設定しています。 option{NewUI}
は、NewUI
という値を保持するオプションです。- つまり、プレイヤーごとに関連するUI要素が存在する場合は、そのUI要素を
MaybeMyUIPerPlayer[Player]
に設定します。
- この部分では、
set
:set
は変数の値を設定するためのキーワードです。- ここでは、
MaybeMyUIPerPlayer[Player]
の値を設定しています。
if(set MaybeMyUIPerPlayer[Player] = option{NewUI}) {}
:if
文は条件分岐を行うための制御構文ですが、ここでは条件式がset MaybeMyUIPerPlayer[Player] = option{NewUI}
となっています。- この分岐では、条件式が真(true)の場合の処理を実行する必要がありますが、何も処理する必要がないため、中括弧
{}
内は空です。
このコードの目的は、プレイヤーごとに関連するUI要素を管理し、所定の条件に基づいてその値を設定することです。
具体的には、既存のUI要素が存在する場合には削除し、新しいUI要素を追加する際に MaybeMyUIPerPlayer
の値を設定しています。

optionを使用している理由
クリックすると開きます。
option
を使用して MaybeMyUIPerPlayer
の値を設定している理由は、UI要素の存在有無を柔軟に管理するためです。
option
は、変数に値があるかどうかを表現するための型です。具体的には以下のような性質を持ちます:
- 値が存在しないことを表現できる:
option
型の変数は、値が存在しないことを表現できます。- 例えば、
None
やNull
などの特別な値を使わずに、単に値の存在/不在を表現できます。 - これにより、プレイヤーに関連するUI要素が存在しない場合、
MaybeMyUIPerPlayer[Player]
の値は単にNone
ではなく、option
型のオブジェクトであるため、より明確に状態を表現できます。
- 安全な値のアクセスが可能:
option
型の変数には、値が存在する場合と存在しない場合の2つの状態があります。- 値が存在する場合、値を安全に取得することができます。
- 一方、値が存在しない場合、値にアクセスしようとするとエラーを回避することができます。
- このため、プレイヤーに関連するUI要素が存在しない場合でも安全に処理することができます。
- 状態を明示的に表現できる:
option
型を使用することで、値の存在/不在を明示的に表現できます。- UI要素が存在する場合はその値が設定され、存在しない場合は
None
ではなくoption
型のオブジェクトを使用することで、プログラマーや他の人がコードを読んだ際に明確な状態を把握しやすくなります。
つまり、option{NewUI}
を使用することで、プレイヤーごとに関連するUI要素の存在有無を明確に管理できます。
存在する場合はUI要素そのものを保持し、存在しない場合は option
型のオブジェクトが設定されます。
これにより、安全な操作と状態の明示を実現することができます。

まとめ
今回はVerse解説の続き(2)について解説しました。
本日もお疲れさまでした🍵
がんばった!!!
僕のTwitterアカウントです。-
-
【UEFN】UIボタンの作り方(3ページ目)│Verse解説の続き
続きを見る
-
-
【UEFN】UIボタンの作り方(4ページ目)│Verse解説の続き
続きを見る
-
-
【UEFN】UIボタンの作り方(5ページ目)│Verse解説の続き
続きを見る