LoginSignup
56
59

More than 3 years have passed since last update.

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

Posted at

なぜUnityでpythonを使いたいのか

あくまで私個人の意見である。

unityを使ってたから

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

python変数の中身をGUIから変更できるようになる

unityのSerializeFieldを使えば、unityのInspectorウィンドウから変数の中身を設定できるようになる。

InspectorExampleObjWithScripts.png

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

pythonの演算結果をunity画面でわかりやすく表示することができる

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

ironpythonはpython2なのか、python3なのか

公式サイトからgithubのページに飛んでみる

無題.png

python2、python3両方あるが、ironpython3は「DO NOT USE」とある。ironpython3を見てみる。

無題.png

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

インストール方法

kitao's blogさん参考

問題なくできた。csスクリプトをGameObjectに追加するのを忘れずに

プログラム例

オブジェクト生成

コガネブログさん参考

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

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

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

.netクラスライブラリを使用する

いろいろ備忘録日記さん参考

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))さんを参考にして以下のファイルを作成

pythonの呼び出し

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);
    }
}
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);
    }

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

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

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

実行結果
無題.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を扱ってみる

ぬわーーーーーーー!!!さんを参考
詠み人知らずの備忘録

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

ironpythonからpythonを実行して

subprocessはpopenしか対応していないよう。

その他

ironpythonでは、C#で作成したdllファイルを読み込めるそう(参考)。

参考

公式
テラシュールブログさん

56
59
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
56
59