ユーザ用ツール

サイト用ツール


embed_var_save

差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン前のリビジョン
次のリビジョン
前のリビジョン
embed_var_save [2024/07/12 11:01] – [1.関数から引数を受け取るための実装] machiaworxembed_var_save [2024/07/27 04:32] (現在) machiaworx
行 5: 行 5:
 少なくとも管理者は以下の理由により必要がありました。 少なくとも管理者は以下の理由により必要がありました。
  
-* 敵スクリプトを書いてる時に特定タイミングで次に行動を指定したい +  * 敵スクリプトを書いてる時に1回命令を送って、行動を変えたい 
-* プレイヤーの行動に合わせて敵やボスの行動を変更したい+  * プレイヤーの行動に合わせて敵やボスの行動を変更したい 
 +  * ツールを作っていて、特定命令を1回実行したらツールの色が変わるようにしたい等
  
 上記内容について、実装がうまく行ってるのでその内容を記載します。 上記内容について、実装がうまく行ってるのでその内容を記載します。
行 46: 行 47:
   - ValueクラスがVMへの参照しか持っておらず、実変数・文字列は全部VM上に持っている   - ValueクラスがVMへの参照しか持っておらず、実変数・文字列は全部VM上に持っている
   - Context(VMがスクリプトを読んで計算する1回の処理)上での変数定義は保存しているが、基本的にはContext上でのローカル変数は開放されてしまう   - Context(VMがスクリプトを読んで計算する1回の処理)上での変数定義は保存しているが、基本的にはContext上でのローカル変数は開放されてしまう
 +
 +※Contextについては以下解釈が近い模様。\\ https://e-words.jp/w/%E3%82%B3%E3%83%B3%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88.html
  
 現在ツールを開発していますが、上記問題に遭遇したため、色々資料を集めながらなんとか対応しました。 現在ツールを開発していますが、上記問題に遭遇したため、色々資料を集めながらなんとか対応しました。
行 65: 行 68:
   }   }
  
-上記は第1引数を取得する組み込み関数の実装です、単純にValueをContextから取得します。 +=== 関数の引数から値を参照する === 
-これによってContext上の変数を参照する、という状発生するわです+ 
 +上記は第1引数を取得する組み込み関数の実装です。 
 + 
 +まず、単純にValueをContextから取得します。これによってContext上の変数を参照できるわけでね。\\  
 +Context上では一意とな文字列をもって値を取得することができるためあらかじめ組み込み変数で使う文字列を指定しておいて、処理中に参照するこが可能になっております。(今回は記述を省略してます) 
 + 
 +=== グローバル領域に変数を保存 === 
 + 
 +次に、vm上の「グローバル変数を保存しておく領域」となるGetGlobalContext()に変数を保管します。 
 + 
 +これはContext外やstatic変数で保存しようとする場合、あくまでVM上の一時的な参照領域にアクセスする事になってしまうため、処理中ならまだしも結果を受け取りた場合処理終了後になることが多く、その場合VM上ですべて開放されているため、アクセスができない事になってしまいます。 
 + 
 +結果、組み込み関数上でstatic変数に値を格納しよとしても、後でアクセスしようとしたときには変数がすべて初期化されていることになります。\\  
 +ただこのおかげでMiniScriptがプログラム本体に影響なく処理を行えるシステムになっているということではあります。 
 + 
 +これらのグローバル変数について正確なウォッチはしてませんが、恐らく「次のスクリプト起動タイミング」までは有効かと思います。 
 +よって、次の実行までに別の場所に保存する必要があります。 
 + 
 +※正確に言うと変数のIndexが作られたら以降のプログラム実行後もそのままではあるんですが、グローバル変数である関係上いつ更新されるか分からないので早い段階で別の場所に保存しておく必要はあると思います。 
 + 
 +==== 2.保存した変数をキープしておく ==== 
 + 
 +  Value x = interp.vm->GetGlobalContext()->GetVar("_sequence1"); 
 +  savedInterpreter.vm->GetGlobalContext()->variables.SetValue("_sequence1", x); 
 + 
 +コードがややこしすぎて説明も難しいんですが書いていきます。 
 + 
 +上記は、「スクリプトを実行した後で保存したグローバル変数を、別インタプリタのグローバル変数として保存する」処理を書いてます。 
 + 
 +先ほどの話の通りで、基本的にはMiniScriptの変数はInterpreterクラス上で保存されているため、もう1回起動したり開放する場合、一時的に保存した変数等もずっとアクセスできることが保証されていません。\\  
 +上記を回避する策として、もう1個Interpreterクラスを作り、このVM上のグローバル変数として保管する実装を行います。 
 +上記の例では、「SavedInterpreter」がもう1個作成したInterpreterクラスのインスタンスになります。 
 + 
 +ちなみに未使用のInterpreterのほうは実行しない想定です。そうしないとキープできないですからね。 
 +とは言うものの一度Contextを起動しないとうまく初期化ができないので、ソースコードが空の状態で起動して、上記の処理を行うことになります。 
 + 
 +==== 3.未使用Interpreter上から変数を参照する ==== 
 + 
 +これでいつでも変数を参照できるようにはなりましたが、先程の話の通り利用中のInterpreter上だといつ更新されるかかりません。 
 +よって、参照するときはコピーした未使用のInterpreterクラスからの参照を行います。 
 + 
 +  Value search; 
 +  search = savedInterpreter.vm->GetGlobalContext()->GetVar("_sequence0"); 
 + 
 +上記は、変数を作成し、未使用InterpreterクラスからIndexerで変数にアクセスし取得する処理です。\\  
 +ややこしいですがここまででようやく変数をContext外で保存、ないしはアクセスすることができるようになりました。 
 + 
 +ちなみに、特定のインデクサでアクセスできる事自体は「誰も管理していません」。\\  
 +すなわち何も登録していない場合、アクセスした時点で内部で例外的なアクセス扱いになります。(つまりエラー)\\  
 +よって、このインデクサで変数を登録しているよ!という管理が必要になります。 
 + 
 +自分の実装では、別途変数を設けてこのインデクサにアクセスしていることを変数を見て確認した上でアクセスできるようにしました。 
 + 
 +==== 最後に ====
  
-次に+サンプルプロジェクトも用意したほうがいいかなと思い始めてます。説明がややこしいので。
embed_var_save.1720749669.txt.gz · 最終更新: 2024/07/12 11:01 by machiaworx