ゲーム組み込み用スクリプト言語を作ってみた
DESCRIPTION
C#のExpressionTreeを使って作成したスクリプト言語の簡単な紹介TRANSCRIPT
ゲーム組み込み用スクリプト言語を作ってみた2013 年 6 月 1 日
目次 目的 言語仕様策定 作る 作った
目的 細かい調整するにはスクリプト言語がいい 小規模なロジックをたくさん書くのに便利 既存言語調べるのめんどくさい 作るの楽しそう
言語仕様策定
基本事項 言語の開発は C# で 動作環境も C# で 1 フレームで数百回走らせられる速度
コンパイル型にする
方針 単純な命令は書きやすく
括弧なしでのメソッド呼び出し オーバーロードを簡単に
名前付き引数的機能 手続き型っぽく
実装の簡単化 1 種類のオブジェクトにつき 1 本のスクリプ
ト
実際のスクリプト
実演
スクリプトでパーティクル制御
作る
処理の流れ ソースの文字列の読み込み プリプロセッサ 文字列をトークン分割 ( スキャナ )
トークン : スペースで区切られた単語や改行文字
トークン列を構文に整理 ( パーサ ) 構文を実行可能形式に変換 ( プロセッサ ) 実行
ソースの読み込み 普通のファイル読み込み 暗号化して固めたデータからの読み込みも別
途サポートした
プリプロセッサ 定数定義の #define と単純な #include をサ
ポート 入力ソースを適当に置換して実装
スキャナ 入力文字列をスペースでトークンに分割
手抜き トークンを型付けする
数値リテラルは float 値に 演算子やタブ、改行などは対応する列挙体に その他は文字列に
トークンの配列を返す
パーサ コメント部分を除去 トークン列を改行を目印に行に分割
行にインデントの深さも与える 行内のカッコを再帰的にまとめる カッコで括られた部分を一塊のオブジェクト
に
プロセッサ基本方針 .NET の Expression Tree というライブラリ
を使用 式の木構造をオブジェクトで組んでコンパイ
ルすると、そのまま実行可能な無名関数を返す !
本体側のメソッド呼び出しにはリフレクションを活用
プロセッサ準備 本体側のメソッドやプロパティを呼び出す準
備 1 つの型につき 1 つの「識別子 - メソッド情
報」辞書 全ての型で 1 つ、グローバル関数の辞書も用
意
プロセッサ 1
トップレベルの文を 1 つずつパース トップレベルの文 = 必ず実行される文
文がどの構文かをチェック 最初の 1 、 2 単語を見て判断可能 制御文、代入文、宣言文でなければメソッド呼び
出し 実行中に使う数値型は基本的に全て float
作った
速度テストfloat i = 0;
float j = 0;
while (i < 1000){
j = 0;
while (j < 1000){
j++;
}
i++;
}
というコードを最適化なしで実行 C# ネイティブ : 10k ticks(2-3ms) スクリプト : 16k ticks(4ms)
速度テスト 2
中身が空で 1 引数の C# 側関数を 40 万回呼び出し
C# ネイティブ :12ms スクリプト :57ms 動的な呼び出しなのでやや遅い