なるように、なる

徒然なつぶやき、備忘録です。

Unityの勉強

本業でUnityプロジェクトにジョインし、半年が過ぎました。
Unityも色々あって大変ではありますが、参考までに自分がやってきたことを整理しました。

私のバックグラウンド

  • C#未経験、C++は経験あり
  • Unity未経験、ただしUnrealEngine, oF, TouchDesignerなどの3DCG経験あり

UE経験あるからどうにかなると思っていたけど、どうにもなりませんでした。

やったことリスト

基本チュートリアル

この2つだけで大分Unityの雰囲気というかノリが分かりました。
なにはともあれやった方が良いです。

C

なんとなく読めたのですが、やはり知らない文法もチラチラあり、そういうときは言語仕様にザっと目を通すのが良いと思っています。
すぐには覚えられないんですけど、次に見かけたときにちゃんと立ち止まれるように。

設計

本業プロジェクトが既存のVRシステムのリファクタだったので、アーキテクチャの参考を探し、自分として一番馴染んだのがこの記事でした。
もともと前のプロジェクトがClean Architectureで開発していたので。
やり過ぎは良くないけど、なにもやらないのも良くない。

映像製作チュートリアル

ここからは本業ではあまり使わないけれど、趣味のVJやMV製作に必要なインプット。 この辺を勉強したアウトプットがこちら。

www.youtube.com

www.youtube.com

www.youtube.com

あと、リリース前のMVがもう1本。。

VJチュートリアル

5月あたりにライブをやりそうなので、今はVJシステムを構築したくてamagiさんの資料を参考にさせて頂いてます。
そしてコツコツとVFXグラフを勉強。もちろんKeijiro神のリポジトリを見漁っています。大感謝。

なかなか覚えも悪いし、アウトプットが出なくなってツライ気持ちもあるのですが、慌てずにじっくり勉強していきます。

PLATEAU AWARD2023にエントリーしました(予選落ち)

PLATEAU AWARDにエントリーしましたが、残念ながら予選落ちでした。

都市情報から音楽を生成するアイディアは評価されたものの、都市ごとの差異が分かり難いという点が課題として指摘されました。
差異が見え難い部分はある程度狙い通りではあったのですが、コンテストではそれではいけなかったなという反省です。

自分としては満足な作品を作ることが出来たと思っているので、エントリーして良かったです。

PLATEAU SDK for Unity で都市情報を取得する

PLATEAUは3Dモデル以外にも様々な都市情報を含んでいます。
それらの情報をPLATEAU SDK for UnityのAPIを通して取得することができます。

公式のサンプルに取得方法は書かれているので、だいたいその通りですが、メモを残しておきます。

環境

  • OS: windows11
  • Unity: 2022.3.5f1
  • PLATEAU SDK for Unity: 1.1.6
  • 都市データ:渋谷駅周辺

公式サンプル

都市情報にアクセスするためのサンプルコードがパッケージの以下に含まれています。
これを確認するのが最も確実です。

/Packages/com.synesthesias.plateau-unity-sdk/Samples/AttributesSample/Scripts/ClickToShowAttributes.cs

このサンプルの概要は以下のとおり。

  • マウスでクリックした建物オブジェクトの情報をCanvasに表示する
  • PLATEAUCityGmlProxy.LoadAsync()でGMLファイルをロードする(CityModelが返却される)
  • CityModelからロードした情報から対象の建物の情報(CityObject)を取得する
  • CityObjectが保持する属性情報(Dictionay)から必要な情報を取得する

CityModelとかCityObjectってなんやねんってなるのですが、この階層関係を整理してマニュアルを読むのが一番理解が早いです。

都市情報の階層構造

ざっくりですが、以下のような感じ。

  • PLATEAUInstancedCityModel: インポートした都市のルートGameObject
    例:13100_tokyo23-ku_2022_citygml_1_1_op
  • CityModel: GMLファイルをパースして得られる街のモデル。 0個以上の CityObject を保持する。
    例:53393586_bldg_6697_1_op.gml
  • CityObject: CityGMLにおける全てのオブジェクトのベースクラス。 例:bldg_eebb977c-0711-4af6-8472-e58da99f3fbf

個々の都市情報にアクセスするにはCityObjectを取得する必要があります。
CityObjectを取得するには、サンプルのように特定の建物のGameObjectを基に取得していく方法と、トップのGameObject(PLATEAUInstancedCityModel)からたどる方法があると思います。
私は全ての建物の情報が欲しかったので、後者をやりました。

全ての建物の情報を取得する方法

実装方法は2種類ありましたので、それぞれコードを記載します。

PLATEAUCityGmlProxy.LoadAsync() を使う方法

var rootDirName = "13100_tokyo23-ku_2022_citygml_1_1_op";
var transforms = instancedCityModel.GmlTransforms;

foreach (var transform in transforms) {
    if (transform.name.Contains("bldg")) {
        var cityModel = await PLATEAUCityGmlProxy.LoadAsync(transform.gameObject, rootDirName);
        var cityObjects = cityModel.GetCityObjectsByType(CityObjectType.COT_Building);
        foreach (var cityObj in cityObjects) {
            Debug.Log(cityObj.AttributesMap["bldg:measuredheight"].AsDouble);
        }
    }
}

nstancedCityModel.LoadGmlAsync を使う方法

var transforms = instancedCityModel.GmlTransforms;

foreach (var transform in transforms) {
    if (transform.name.Contains("bldg")) {
        var cityModel = await instancedCityModel.LoadGmlAsync(transform);
        var cityObjects = cityModel.GetCityObjectsByType(CityObjectType.COT_Building);
        foreach (var cityObj in cityObjects) {
            Debug.Log(cityObj.AttributesMap["bldg:measuredheight"].AsDouble);
        }
    }
}

ハマったところ

最初、PLATEAUの都市情報をUnityのStart()の中で呼んでいたのですが、以下の関数が永遠に返ってきませんでした。
処理が長いだけかと思っていたのですが、Update()の中ではすぐ返ってきたので、たぶん初期化順でデッドロックしていたのかと思います。

  • PLATEAUCityGmlProxy.LoadAsync()
  • instancedCityModel.LoadGmlAsync()

おまけ:建物の大きさだけが知りたい

建物の大きさだけが知りたい場合、都市情報にアクセスしなくても、メッシュのサイズから同等の情報が得られました。

var transforms = instancedCityModel.GmlTransforms;

foreach (Transform lod in transform) {
    if (lod.name == "LOD0") {
        continue;
    }
    foreach (Transform cityObjTransform in lod) {
        if (cityObjTransform.gameObject.GetComponent<MeshFilter>()) {
        Debug.Log(cityObjTransform.gameObject.GetComponent<MeshFilter>().mesh.bounds.size);
        }
    }
}

Unity初心者なので、間違っていたらおしえてください。

おしまい

UnityでPlateauのCityModelの原点の緯度・経度を取得する方法

Plateauでimportした街に対して、緯度・経度を指定してオブジェクトをスポーンしたかったので、そのためにUnity内の原点の緯度・経度が知りたかったです。

調べても見つからなかったので記事にしました。
Unity初心者なので、間違っていたら教えてください。

マニュアル

Namespace PLATEAU | PLATEAU SDK for Unity

方法

importしたCityGMLをInspectorで見ると、「GeoReferenceData」にそれっぽい数値がありました。

国土地理院の変換ページで緯度・経度にしてみると、期待通り自分がImportした街(渋谷)の中心の緯度・経度でした。

CityGMLのトップのオブジェクトのクラスは「PLATEAUInstancedCityModel」です。

マニュアルを調べると、「PLATEAUInstancedCityModel.GeoReference.ReferencePoint」で該当の数値が取得できることが分かりました。

Class PLATEAUInstancedCityModel | PLATEAU SDK for Unity

Class GeoReference | PLATEAU SDK for Unity

スクリプトは以下のとおり。

using PLATEAU.CityInfo;

public class Hoge : MonoBehaviour {
    public PLATEAUInstancedCityModel CityModel;

    void Start() {
        Debug.Log(CityModel.GeoReference.ReferencePoint);
    }
}

以上です。

カラースペース

今まで何回見ても頭に上手く入ってこなかったり、忘れてしまっていたのですけど、なんだかすごく頭に入ってくる記事に偶然出くわしたので、自分メモ。

qiita.com

後で比嘉さんの記事も勉強しなおす!

zenn.dev

zenn.dev

ZigCamでVJした話@さざれ場003

さざれ場 #003 に、Yengoさんと一緒に出演しました。

www.youtube.com

今回はZigCamを使って、生カメラ映像と3Dの映像を混ぜてみました。
ZigCamは、いつか何かで使いたいなと思いながら月日が流れていたのですが、今回主にカメラ位置を取得したいと思い、使う決心をしました。 (後述の課題があったため、割と決心が必要でした。)

リハと本番で1回ずつ絶体絶命のピンチを迎えるなどしましたので、記録しておきます。
↓がZigCamと3Dカメラが連動している感じの動画です。

ZigCamについて

ZigCamは、カメラ画像、デプスデータ、人物のマスク、カメラの姿勢などをiPhoneで取得できるアプリです。
データはNDIで送信されるので、色んなソフトで簡単に受信できます。
すごく最高ですね!

さらに最高なことに、開発者の森岡先生がTouchDesingerでデータを受信&パースするToxも公開してくれています。

github.com

note.com

ちょっと試す分には素晴らしいのですが、本番パフォーマンスで使う際には若干懸念がありました。

  • ネットワーク接続が必要
  • 姿勢の誤差が蓄積する

検証の段階ではどちらもなんとかなるかなと判断していたのですが、どちらももろに当日のピンチに直結しました。

ネットワーク接続 -> リハでのピンチ

ZigCamはNDIでデータを送受信します。
そのためネットワーク接続が必要になります。

自宅のWiFiで開発している分には調子いいんですが、以前にTangle(渋谷のMusic Bar)でお店のWiFiを使って接続したら、けっこうな頻度で接続が切れました。

接続が切れるのは辛いなと思っていたのですが、WiFiじゃなくてスマホの回線をシェアすればよいのでは?と思い、試してみました。
いくつかの方法を調べている中で一番手堅そうだったのが、USBでiPhoneとPCを直結する形式。やっぱり無線より有線のほうが安心。

自宅では全然トラブルもなく、リハの最初もバッチリ受信できたので安心していたら、突然データを受信しなくなってピンチを迎えました。

リハの時間は15分。ヤバイ。

切断前後での状況変化は、、、防音扉!!

そう。
リハが始まって防音扉を閉めたので、半地下の会場の回線状況が悪くなったんですね。

藁スガでお店のWiFiに繋がせてもらったら無事に復旧しました。

今回はお店のWiFiが好調だったので、結局本番中も問題なかったのですが、あぶなかった。。

姿勢の誤差 -> 本番でのピンチ

ZigCamは、(おそらく)アプリ起動時の姿勢を原点とした姿勢情報(T[xyz], R[xyz]やカメラプロジェクションマトリックス)を送信してくれます。

今回はiPhoneの初期位置・FOVをTouchDesignerの3Dカメラの初期位置・FOVと合わせたうえで、リアルタイムで受信する原点からの変化量をカメラ位置に加えることで、3Dカメラの動きを制御しました。

ジャイロの宿命なのですが、iPhoneを静止させていても、Rotationの誤差が蓄積します。
今回のライブは15分だったので、15分間測ってみたところ、X軸・Y軸それぞれ4度程度ずれていました。

今回の演出では4度ならそんなに致命的じゃないと判断して、誤差は許容する方針(無策)で進めました。

浅はかでした。

ピンチはライブ本番の後半で訪れました。

楽しくなってきてiPhoneをブンブン振り回していたら、変な加速度が加わったせいか、自己位置が10メートルも飛んでしまいました。
あわてて手入力でオフセット値を調整してみたのですが、すぐに諦めてアプリを再起動しました。

幸い音楽の転換のはざま辺りだったので、ダメージは少なめでしたが、、あぶなかった。。。

真面目にやるなら誤差に対するフィルタを入れるとか、値が飛んだ時の処置を作る必要が。。。

謝辞

共演してくれたYengoさん、ありがとうございます。
普段とは違うフィールドにも関わらず出演を快諾してくれて大感謝です!

出演者のみなさま、ありがとうございます。 良きイベントになったと思うし、これからの製作の刺激を頂きました!!

さざれ場の運営のみなさま、ありがとうございます。
貴重な機会をいただき、自分としても新しいチャレンジができました!!

見に来てくださったみなさま、感想をくださったみなさま、ありがとうございます。 「悪夢だった」、「気が狂ったのかな」、「エヴァみあった」、などなど、嬉しかったです!

NEXT is YOUR TURN!!!