unity上でpythonを使う魅力と使いかたについてまとめてみた

#なぜUnityでpythonを使いたいのか
あくまで私個人の意見である。

##unityを使ってたから
個人的にunityが好きだから。VR、AIが注目されている今、unityとpythonは需要が増えると考えている。
その二つを組み合わせられるのは非常に魅力的だ。

##python変数の中身をGUIから変更できるようになる
unityのSerializeFieldを使えば、unityの[Inspectorウィンドウ](https://docs.unity3d.com/ja/current/Manual/UsingTheInspector.html)から変数の中身を設定できるようになる。

![InspectorExampleObjWithScripts.png](https://qiita-image-store.s3.amazonaws.com/0/104887/b712168e-2564-fd49-17a2-450b0b78e786.png)

pythonにおいて、例えば機械学習のパラメータを変更しないといけないときに、わざわざファイルを開かなくてもInspectorウィンドウから中身をいじれるようになるため、非常に便利だ。

##pythonの演算結果をunity画面でわかりやすく表示することができる
また、unityはゲームや直感的なアプリケーション作成にも優れている。
「機械学習などの演算をpythonにやらせ、その結果によって、異なるアクションを起こすunityゲーム」などをつくることも可能。

#ironpythonはpython2なのか、python3なのか
公式サイトから[githubのページ](https://github.com/IronLanguages)に飛んでみる

![無題.png](https://qiita-image-store.s3.amazonaws.com/0/104887/6721c15e-1f81-02f2-e8b8-120415ea0bd0.png)


python2、python3両方あるが、ironpython3は「DO NOT USE」とある。[ironpython3](https://github.com/IronLanguages/ironpython3)を見てみる。


![無題.png](https://qiita-image-store.s3.amazonaws.com/0/104887/c41e6917-a846-373d-96d5-ddaafb884031.png)

どうやらまだ、十分に使える状態ではないようだ。
今後に期待したい。


#インストール方法
[kitao's blog](http://tkitao.hatenablog.com/entry/2015/05/18/225902)さん参考
↑
問題なくできた。csスクリプトをGameObjectに追加するのを忘れずに

#プログラム例
##オブジェクト生成
[コガネブログ](http://baba-s.hatenablog.com/entry/2017/10/25/100000)さん参考

pythonコード内を以下のように変更

```py:test.txt

#!/usr/bin/env python

import clr
clr.AddReferenceByPartialName('UnityEngine')
import UnityEngine
from UnityEngine import *

def call_test():
	go = GameObject()
	go.name = 'pokemon'
	rigidbody = go.AddComponent( Rigidbody )
	rigidbody.isKinematic = True

call_test()

```

![無題.png](https://qiita-image-store.s3.amazonaws.com/0/104887/b8d2d9aa-721d-17dd-b536-c24641205176.png)

pokemonオブジェクトが生成され、Rigidbodyが追加されているのを確認

##.netクラスライブラリを使用する
[いろいろ備忘録日記](https://devlights.hatenablog.com/entry/20070119/p1)さん参考

```py:test.txt

#!/usr/bin/env python

import clr
clr.AddReferenceByPartialName('UnityEngine')
import UnityEngine
from UnityEngine import *

import System as _s

def print_message():
    #OSVersion is Microsoft Windows NT **.*.* ****.*を出力
	Debug.Log("OSVersion is " + str(_s.Environment.OSVersion))

print_message()

```


ちなみにDebug.Log内の関数において
```
	Debug.Log("OSVersion is " + _s.Environment.OSVersion)
```
とすると以下のエラーが出る

```
TypeErrorException: unsupported operand type(s) for +: 'str' and 'OperatingSystem'
```
pythonの記法に則ってUnityEngineを呼び出す必要がある

##値の受け渡し（外部オブジェクトの連携）
SetVariableを使えばpython側でC#内のクラスや変数などが扱える

[(hatena (diary ’Nobuhisa))](http://d.hatena.ne.jp/Nobuhisa/20090422/1240333834)さんを参考にして以下のファイルを作成


pythonの呼び出し

```cs:Callpython.cs
public class CallPython : MonoBehaviour {
	// Use this for initialization
	void Start () {
        TestPython test = new TestPython();
        TestComponent componentPython = GameObject.Find("TestObject").GetComponent<TestComponent>();
        private int num = 2; //同スコープ内ならprivate型でも呼び出せる

        var script = Resources.Load<TextAsset>("test").text;
        var scriptEngine = IronPython.Hosting.Python.CreateEngine();
        var scriptScope = scriptEngine.CreateScope();

        scriptScope.SetVariable("TestPython",test);                //testクラスをTestPythonとしてpythonで扱えるようにする
        scriptScope.SetVariable("TestComponent",componentPython);  //GameObjectを扱うことも可能
        scriptScope.SetVariable("num", num);

        var scriptSource = scriptEngine.CreateScriptSourceFromString(script);

        scriptSource.Execute(scriptScope);
    }
}
```



```cs:TestPython.cs
public class TestPython : MonoBehaviour {
    private string title = "Hello Uniity";
    public string Title
    {
        get
        {
            return title;
        }
        set
        {
            title = value;
        }
    }

    public void ShowTitle()
    {
        Debug.Log(title);
    }

}
```

```cs:TestComponet.cs
public class TestComponent : MonoBehaviour {
    [SerializeField]
    public string title;

    public void ShowTitle()
    {
        Debug.Log(title);
    }
}

```




python側プログラム

```python:test.txt
import clr
clr.AddReferenceByPartialName('UnityEngine')
import UnityEngine
from UnityEngine import *

def call_unity():
	Debug.Log(TestComponent.title)      #インスペクターに登録されてあるパラメータの確認
	Debug.Log(TestPython.Title)         #TestPython内の変数の中身を確認
	TestPython.Title = "Hello Python"   #TestPython内の変数の中身を書き換える
	TestPython.ShowTitle()              #関数呼び出し
	Debug.Log("num is " + str(num))     #

call_unity()
```

unity側で以下のように実装する
1. TestObjectの生成
2. TestObjectにTestComponent.csを追加
3. 追加したTestComponent.csのTitleをインスペクターから書き換え

![無題.png](https://qiita-image-store.s3.amazonaws.com/0/104887/04622ea4-b8d1-f6f4-ab07-7ad1c630ab5a.png)

実行結果
![無題.png](https://qiita-image-store.s3.amazonaws.com/0/104887/0478b488-fa0d-5436-ab91-5d2aef4a3301.png)



※ちなみにpython側でC#側のクラスを扱おうとすると「そのような変数はありませんよ」とエラーが出る。

```
#!/usr/bin/env python

import clr
clr.AddReferenceByPartialName('UnityEngine')
import UnityEngine
from UnityEngine import *

def call_unity():
	testObject = GameObject.Find("TestObject")
	testScript = testObject.GetComponent<TestPython>()

	Debug.Log("[Python] Title is " + testScript.Title());


call_unity()
```

```
UnboundNameException: global name 'TestPython' is not defined
IronPython.Runtime.Operations.PythonOps.GetVariable (IronPython.Runtime.CodeContext context, System.String name, Boolean isGlobal, Boolean lightThrow)
IronPython.Compiler.LookupGlobalInstruction.Run (Microsoft.Scripting.Interpreter.InterpretedFrame frame)
Microsoft.Scripting.Interpreter.Interpreter.Run (Microsoft.Scripting.Interpreter.InterpretedFrame frame)
```

##pythonの外部ライブラリを使用する
そこでpython側でlibsvmを扱ってみる

[ぬわーーーーーーー！！！](https://yoheikoga.github.io/2016/07/20/use-libsvm-by-python/)さんを参考
[詠み人知らずの備忘録](http://authorunknown408.blog.fc2.com/blog-entry-33.html)

うまくいかない。ironpythonではlibsvmは対応していないらしい。

##ironpythonからpythonを実行して
subprocessはpopenしか対応していないよう。

#その他
ironpythonでは、C#で作成したdllファイルを読み込めるそう([参考](https://tnakamura.hatenablog.com/entry/20090915/ironpython_inheritance_csharp_class))。

#参考
[公式](https://ironpython-test.readthedocs.io/en/latest/library/subprocess.html)
[テラシュールブログ](http://tsubakit1.hateblo.jp/entry/2015/01/03/203843)さん