UnityでPythonを使うことができるPython Scripting packageというものがあります。公式の説明はこちらです。

公式の説明だけではなかなかできませんでしたが、Python for Unity 3D 2020!!というYoutube動画を参考にして何とかできました。

ただ、この動画はPython2.7.16の環境構築でしたので、Python3で動かすにはまた少し苦労しました。そこで、ここに忘備録を残しておきます。

Pythonの環境構築

Python3.8.3 を、C:\Python38\にインストール(公式ではPython3.10.6としてあるが、すでに入れていたPython3.8.3でもできた)。

環境変数のPath にC:\Python38\ を追加(すでにしてあった)。

コマンドプロンプトから、Pytho3.8.3が実行できることを確認。

[code]
C:\Users\itoma>python –version
Python 3.8.3
[/code]

Unityでプロジェクト作成

2021.3.6f1 で、3Dのアプリケーションでプロジェクト「231001_PythonForUnity」を作成。

Pytohn Scripting というパッケージを入れればよいのだが、いつものPackage Manager からは入れることができない。

そこで次のようにする。

Unityで作ったプロジェクト「231001_PythonForUnity」のディレクトリから以下のファイルをVSCodeなどで開いて、ハイライトしている一行「”com.unity.scripting.python”: “7.0.1”, 」を加える。

\231001_PythonForUnity\Packages\manifest.json

これでUnityに戻ると、自動でPython Scripting がインストールされるのでこれでOK。

Window > Package Managerで、Packages: Unity Registry のリストに「Python Scripting」が入っていることが確認できる。

 

Python Script Editor

Python Scripting が入ると、以下の3つの使い方ができる。

1.Python Script Editor を使う

2.Unity のC#のコード中にPythonコードを書くPythonRunner .RunString

3.Pythonファイルを読み込んで実行する、PythonRunner.RunFile

以下、Pyton Script Editor の使い方を紹介する。

 

Window > General > Python Script Editor で、Python Script Editor を開く。

 

Python Script Editor は、下のような2段組みのUI。下のboxにPythonコードを書いて「Execute」を押すと、実行結果が上のboxに表示される。

例えば、hello Unity。

 

変数を使った計算もできる。

 

UnityEngine というパッケージをimport すると、UnityでのObjectの情報をとったり、Objectの操作をすることができる。下のコードを実行すると、Unity上にあるすべてのGameObjectの名前をコンソールに表示する。

import UnityEngine as ue
objects = ue.Object.FindObjectsOfType(ue.GameObject)
for obj in objects:
    ue.Debug.Log(f"Pythonから出力 >> {obj.name}")

 

下は実行例。コンソールにライトとカメラの名前が表示されている。

 

ちなみに、Loadのボタンを使うと、pyファイルをエディターにロードすることもできる。

冒頭で述べたように、Python script editor を使う方法以外に、Unity のC#のコード中にPythonコードを書くPythonRunner .RunString という方法と、Pythonファイルを読み込んで実行する、PythonRunner.RunFileという方法もある。詳しくは、公式HP参照。

ただ、これら3つの方法は、PythonとUnityを並列に走らせることはではなく、Pythonの処理が終わるのをUnityが待つような形になるようだ。

実は、Unityで作ったロボットをPythonで逐次動かせないかと考えて調べていたのだが、それはできなさそうだ。

例えば、Unityでcubeを作って、下のコードをアタッチするとする。外部から、moveUp()が呼ばれれば、cubeが上に上がり、moveDown()が呼ばれれば、cubeが下がる仕組みだ。

# Controller.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Controller : MonoBehaviour
{
    float dy = 0.5f;
    public void moveUp()
    {
        transform.position += new Vector3(0, dy, 0);
    }
    public void moveDown()
    {
        transform.position += new Vector3(0, -dy, 0);
    }
}

 

そして、Python Script Editor で以下のコードを実行する。moveUp()の後に、1秒したからmoveDown()を2回コールするという内容だ。cube が上に上がってから一秒後に、下に2つ分下がるという動きを期待している。

import UnityEngine as ue
import time
objects = ue.Object.FindObjectsOfType(ue.GameObject)
for obj in objects:
    if obj.name == "cube":
        controller = obj.GetComponent("Controller")
        controller.moveUp()
        time.sleep(1)
        controller.moveDown()
        controller.moveDown()

 

しかし、これを実行すると、cubeは下に1つ分動いただけだった。つまり、逐次実行されるのではなく、一気にまとめて実行されているということになる?

まだ十分に理解していないが、ロボットを動かすのには向いていなさそうという印象だった。