目次

より実践的なソース組み込み

Unityのプロジェクトを新規作成

2Dにする理由はないですし、3Dで問題ないです。

Miniscriptのソースコード用意

それではプロジェクト内にMiniscriptのC#ファイルを読み込ませてください。

フォルダの中に格納するほうが他のソースと判別しやすくて管理が楽です。

オブジェクト準備

以下の画面の様に「Cube1個、Text1個」を用意してください。

実装

以下のソースをCubeにアタッチしてみてください。

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Miniscript;
using TMPro;
 
public class ScriptMover : MonoBehaviour
{
    public TMP_Text tmp_stage_frame;
    private string loadText;
    public TextAsset textAsset;
    public Interpreter interpreter;
 
    //ここにグローバル変数を格納するクラス名を指定してください。
    public string globalVarName="ship";
    private int frame=0;
 
    void Start(){
        loadText = textAsset.text;
        interpreter = new Interpreter();
 
        interpreter.hostData = this;
 
        //標準出力先の指定
        interpreter.standardOutput = (string s,bool t) => Debug.Log(s);
        interpreter.implicitOutput = (string s,bool t) => Debug.Log($"implicit {s}");
        interpreter.errorOutput = (string s,bool t) => {
            //エラーログ出力。(Unity側のエラーとして動く)
            Debug.LogError(s);
        };
 
        //組込関数定義のための変数
        Intrinsic f;
 
        //文字列をテキスト枠に反映させる
        f = Intrinsic.Create("change");
        f.AddParam("str", "");
        f.code = (context, partialResult) => {
            var rs = context.interpreter.hostData as ScriptMover;
            rs.tmp_stage_frame.text = context.GetVar("str").ToString();
            return Intrinsic.Result.Null;
        };
 
        //ソースコードの起動準備を行う。
        RunScript(loadText);
    }
 
    public void RunScript(string sourceCode) {
        //前提になるソースコードを最初から埋め込んでおく。
        string extraSource = "ship.reset = function(); self.x=0; self.y=0; self.rot=0;end function\n";
 
        //上記前提ソースコード+テキストのソースコードを読み込ませる。
        interpreter.Reset(extraSource+sourceCode);
 
        //コンパイル処理
        interpreter.Compile();
 
        //グローバル変数の初期化。
        ValMap data = new ValMap();
        data["cnt"]=new ValNumber(0);
        data["x"] = new ValNumber(this.transform.localRotation.x);
        data["y"] = new ValNumber(this.transform.localRotation.y);
        data["rot"] = new ValNumber(this.transform.localRotation.z);
 
        //グローバル変数の定義。今回は1個のマップにまとめてる
        interpreter.SetGlobalValue(globalVarName, data);
    }
 
    void Update(){
        //コンパイルしたソースコードを実行する
        try{
            if( !interpreter.Running())
                interpreter.Restart();
            interpreter.RunUntilDone(1.0f);
        }catch (MiniscriptException err) {
#if UNITY_EDITOR
            Debug.Log("Script error: " + err.Description());
#endif
        }
 
        //処理したスクリプトのグローバル変数から各種動きを反映する
        UpdateFromScript();
    }
 
    public void UpdateFromScript() {
        ValMap data = null;
        try {
            //変数名が最初に定義したものかを確認、一致してれば以降読み込めてるものとして処理する。
            data = interpreter.GetGlobalValue(globalVarName) as ValMap;
        } catch (UndefinedIdentifierException) {
            Debug.LogWarning(globalVarName + " not found in global context.");
        }
        if (data == null) return;
 
        //CubeのRotationを変更する
        Value xval = data["x"];
        Value yval = data["y"]; 
        Value rotVal = data["rot"];
        if (rotVal != null) t.localRotation = Quaternion.Euler(xval.FloatValue(), yval.FloatValue(), (float)rotVal.FloatValue());
 
        //全体フレーム数を加算する
        Value cntval=data["cnt"];
        frame=cntval.IntValue();
    }
}

終わったらCubeからテキスト部分を参照しておいてください。

Miniscript言語で書いたソースコード用意

以下の内容のテキストファイルを用意してください。

serif=["This is Miniscript's test.","This is sample."]
ship.x=ship.x+1
ship.rot +=2
ship.cnt+=1
change(serif[(ship.cnt/600)%2])

終わったらCubeから作ったソースコードを参照しておいてください。

動かしてみましょう

見事にCubeが回転したり文字が更新したりされるはずです。