あけましておめで… あれ、もう4月の後半…(・_・;)
今回はあっさりめな記事、
のつもりが自分でどんどん広げてしまって記事を書くのも時間がかかりましたw
時間も掛けましたが結局下記に書いている注意点の部分は解決できていません…
Mayaから書き出した特定のテキスト形式のデータをUnityのEditor上で読み込んで使う際に
Maya & Pythonを用いてJSON形式で書き出して、Unity側でJsonUtility.FromJson関数など使って読み込むことは以前からやっていました。
しかし、ちょっと仕事で、ランタイムでもそういうデータを使う事になりそうになり、
「ということは、ScriptableObjectの方がいいかなぁ~
じゃあJSONを書き出してAssetImporterで内容読み取って生成する事になるかな?」
と思ったのですが、ScriptableObject(.asset)も中身はテキストにもでき、YAML形式で書き出されているので、
調べたらPyYAMLというPythonでYAMLを扱えるライブラリがあるじゃないですか!
これで勝つる!と思いきや…
最初PyYAMLを使って読み書きしていたのですが、PyYAMLでググってもらうとよく出てくる通りに読み書きするファイルの内容の順序を保持してくれないのです…
それに加えてUnityが書き出すYAMLの記述と微妙に書き方が変わってしまい、
大量に変更点が出てしまいました…
(ただUnity上での読み込みは問題なくできて、
そのファイルをUnity側で再保存するとYAMLの書き方を戻してくれます)
そこでどうにかならないか再度検索していたら、ruamel.yamlというライブラリを見つけました!
ruamel.yamlはPyYAMLのフォークして作られたものだそうです。
一応GitHubの方にもruamel.yamlを追加してありますが、
ruamel.yamlライブラリをインストールするには
pip install ruamel.yaml
実行してもらうか、
こちらのサイト(PyPI)から ruamel.yaml-0.15.92.tar.gz をDLして下さい。
※使用にされた際に不具合が出ても責任は取れませんので自己責任でお試し下さい。
==================================================================
PyYAML & ruamel.yaml の使い方は下記を参考にさせてもらいました。
●【Python】YAMLファイルの読み込み書き込み
https://code-graffiti.com/yaml-file-in-python/
●Python で YAML ファイルを扱う | まくまくPythonノート
https://maku77.github.io/python/io/yaml.html
●【PyYAML VS ruamel.yaml】PythonからYAMLファイルを触ってみた | DevelopersIO
https://dev.classmethod.jp/server-side/python/getting-started-with-pyyaml-and-ruamel-yaml/
==================================================================
※最初に注意点
アップしているデータのAssets/Scenesにある ReadingTest.unity で試してもらうと分かりますが、
元のSceneファイルで下記のよう記述されている部分が
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
今回の記事で使っているScene内のライトのカラーをランダムな値に変更するという処理を実行すると、
変更したライトのカラー値以外に下記の部分に変更点が出てしまいます…
m_Mesh: {fileID: 10202, guid: 0000000000000000e-00000000000015, type: 0}
見ての通りの間に入っている e とその後ろに続く 0 によって、
guidの文字列が指数表記の浮動小数点数として認識されているようです。(・_・;)
タイプをprintするとこの部分は ruamel.yaml.scalarfloat.ScalarFloat
となっており、
別のguid (例えば guid: 0000000000000000f000000000000000 )はきちんと str として認識されています。
まだyamlの使い方が理解できてないですが、
おそらく add_constructor (load) と
add_representer (dump) を使って、
回避できたりするのかな~という所までは分かったのですが、まだ解決できていません。
もし解決方法をご存知の方がいらっしゃいましたら教えて頂けると助かります。
では、まず下記が今回ruamel.yamlを使って編集するScriptableObjectのベースとなるアセットの内容を定義&生成するスクリプト TestScriptableObject.cs です。
Unity上で Tools > Create TestScriptableObject Sample を実行すると、サンプルのアセットが生成されます。
そして、こちらがMayaから実行する事を想定したスクリプト CreateScriptableObjectFromMaya.py です。
今回はテストで上記で作ったサンプルのアセットを相対パスから読み込んで、
Mayaのシーン名と選択しているオブジェクトの名前・移動・回転・スケールの値を取得して、
新しいScriptableObjectとして書き出すという内容です。
実行文は
import CreateScriptableObjectFromMaya
CreateScriptableObjectFromMaya.main()
です。
完全にサンプル用のスクリプトなので、こんなデータは普通にFBXなどで書き出すだけで十分ですが、
応用すれば色々書き出せますね。
上記のkkUnityYamlUtility.pyの中の readYamlClassIdList 関数の中で
UnityのコンポーネントのClassIDを参照しているのですが、
最初は関数ではなく、公式サイト内の「YAML クラス ID リファレンス」に書いてあるものを
辞書としてスクリプト内に全部列挙していました。
しかし、この内容が全然更新されていないらしく、下記サイトに書かれているのを参考にさせてもらい、
System.Reflectionを用いてUnityからテキストファイルとして
YAML_ClassID_List.txt というファイルを出力するスクリプト LlistupClassID.cs です。
そして readYamlClassIdList 関数内でテキストファイルを読み取って、辞書として返すようにしています。
ここから先はおまけ的な内容ですが、ScriptableObjectでやったようにUnityのデータを読み書きできるなら
SceneやMaterialの情報もMayaから書き換えれるちゃうの?と思って試してみました。
こちらはMaya側からYAMLを読み書きするために用意した関数をまとめたスクリプト kkUnityYamlUtility.py です。
kkUnityAamlUtilityを使って、UnityのMaterialやSceneのデータのプロパティをprintするサンプルスクリプトが
・ShowMaterialPropertyList.py
・ShowScenePropertyList.py
そして、MaterialやSceneのデータを直接変更してみたサンプルスクリプトが
・ChangeMaterialValueFromMaya.py
・ChangeSceneSettingFromMaya.py
となります。
長くなりすぎたので、ChangeMaterialValueFromMaya.py だけここに表示しておきます。
実行文は
import ChangeMaterialValueFromMaya
ChangeMaterialValueFromMaya.main()
です。
他のスクリプトはGitHubの方で直接ご覧下さい。
このスクリプトでの注意点はファイル内にも書いていますが、
Material の m_SavedProperties の中の m_TexEnvs や m_Floats は辞書ではなくリストなので、
読み書きする場合は少し注意?が必要です。
コメントをお書きください