はじめに

この記事では C# のプログラム上から C# のコードをスクリプトとして使う方法を紹介します。
過去の私のように学生でゲーム作ってます!な方に役立つといいなと思っています。
また、環境は Windows で VisualStudio を前提としていますのでご了承ください。

どんなときにつかうのか

たとえば、RPG ゲームの村人の行動の制御をするとしましょう。
単純な行動と会話のみであれば、最低限の継承や設定でなんとかなると思いますが、移動パターンの制御、話しかけたときの返答の制御、主人公の持ち物で会話が変わる…
などと凝ったことをしようとすると、数値や文字だけで制御するのは難しいです。
そんなときに、スクリプトが使われるわけですね。

スクリプトとして読み込むようにすれば、動きを変えるたびに毎回ゲーム全体をビルドする必要もありませんし、制御の内容を一緒にゲームを作る友人に任せるということもできます。
ゲームのスクリプトとしてよく Lua などが使われてきたのですが、ゲーム制作でいっぱいいっぱいで新しく覚えるのは大変ですし、ましてやスクリプトを友人に任せるなんてできないです。
しかし、C# には Roslyn があります!
Roslyn は C# で書くことができ、割と簡単に動いてくれるので、新しく覚えることは少なく済むでしょう。

つかう準備

Roslyn は .Net4.6 以上でないと動いてくれないようなので、プロジェクトを .Net4.6 以上にしてあげてください。
あとは NuGet で Microsoft.CodeAnalysis.CSharp.Scripting をインストールすれば準備完了です。

つかってみる

基本的には、

  1. スクリプトを書いたファイルを読み込む
  2. スクリプトの環境を準備する
  3. スクリプトを実行する
  4. 実行結果を取得する

といった感じになります。
以下のプログラムは Roslyn の紹介に必要な最小限 +α 程度のものとなっています。
実行するとコンソールに Child! と表示してくれるはずです。

こちらが読み込んで実行する側のプログラムです。
重要なのは、WithReferences(Assembly.GetEntryAssembly()) で参照を追加している部分、
result.ReturnValue で実行結果を取得している部分です。

using System;
using System.IO;
using System.Reflection;

using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;

namespace MyRoslyn
{
    class Program
    {
        static void Main(string[] args)
        {
            var text = File.ReadAllText("script");

            var script = CSharpScript.Create(text).
                WithOptions(
                    ScriptOptions.Default.
                    WithReferences(Assembly.GetEntryAssembly()));

            var result = script.RunAsync().Result;
            var value = result.ReturnValue;
            Console.WriteLine(value.Method());
        }
    }

    public abstract class Parent
    {
        public abstract string Method();
    }
}

こちらが読み込まれる側のスクリプトです。 Parent クラスを継承元に利用できている点が重要な点ですね。
唐突に return などと書けるのがなかなか面白いです。

using MyRoslyn;

public class Child : Parent
{
    public override string Method()
    {
        return "Child!";
    }
}

return new Child();

今回のプログラムでは実行結果は簡素なものですが、このプログラムを応用すれば RPG の村人の制御などのようなものはすぐでしょう。

最後に

本当はスクリプト用のディレクティブやオプション、リゾルバを説明しようかとも思ったのですが、最小限かつある程度使えるもの を目指した紹介にしてみました。
やろうと思えばスクリプトからなんでもできて楽しいので、ぜひ触ってみてほしいです。