20210916のUnityに関する記事は4件です。

オブジェクトに乗っても落下しないようにする

1.はじめに スーパーマリオ・ロックマン等のアクションゲームにありがちな動く床。はじめての制作だとプレイヤー物に乗っても動く床に沿って動かなかったり、下のGif動画のように落ちることがある。 解決策はとても簡単なものだが、ネタとしてはアリだと思いアウトプットします。 ここだと床の上昇のみでの紹介になるが、この方法はそれ以外の動きにも対応が可能です。 なおここでは接触判定等の紹介はしません。 2.スクリプト スクリプトは単純明快で動く床の子オブジェクトになればいいです。注意点は動く床から離れた場合、親子関係を解除しないと動く床の挙動に影響され続けてしまいます。 using UnityEngine; public class QiitaObject : MonoBehaviour { //物体と接触したら物体の子オブジェクトとなる private void OnCollisionEnter(Collision collision) { transform.parent = collision.gameObject.transform; } //物体から離れたら物体の子オブジェクトを解除する。 private void OnCollisionExit(Collision collision) { transform.parent = null; } } 3.最後に 親子関係の扱いはVR制作だと物を掴む等で使っていましたが、それ以外の用途では使うことがなかったので、とても勉強になった。 これ以外にももっと良い方法があるかもしれませんが、その時は加筆をしたいと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ROS2とUnityを連携させる (1)環境構築

記事一覧 ROS2とUnityを連携させる (1)環境構築 ROS2とUnityを連携させる (2)UnityでSubscribe ROS2とUnityを連携させる (3)UnityでPublish ROS2とUnityを連携させる (4)Unityでカメラ画像をSubscribe はじめに UnityとROSの連携をサポートするUnity Robotics Hubが、これまで提供していたROS1に加えて、新たにROS2に対応するようになりました。 そこで、今回はROS2とUnityを連携させて、Unity内のロボットとROS2内のロボットが同期して動くシミュレーターを作ることを目標にします。具体的には、UnityとROS2間で、移動指令(/cmd_vel)やカメラ画像をやり取りする方法を扱います。記事中では、簡易化のためにgazeboを使いますが、もちろん実機を使って動かすこともできます。以下は、Oculus Quest(Unity)でカメラ映像を見ながら、Turtlebot3(ROS2)を操作している様子です。 最初に、この記事ではROS2とUnityの通信を行うための環境構築を行います。 環境 ubuntu 20.04.2 LTS ROS 2 Foxy Fitzroy Unity 2020.3.17f1 2020.2以降のバージョンが必要です 通信の構造 ROS2とUnityの通信は以下のような構造で行われます1。ROS2側にはROS-TCP-Endpoint、Unity側にはROS-TCP-Connectorをそれぞれ導入します。 ROS-TCP-Endpoint (ROS2側) Unityから送られてくるメッセージを受信するためのエンドポイントを作成するパッケージです。 ROS-TCP-Connector (Unity側) Unity側で使います。主に以下の3つの機能があります。 ① ROSConnection ROS2のノード上で動いているエンドポイントに対してメッセージを送信します。 ② Message Generation ROS2上の情報のやり取りに使われるメッセージを、C#のクラスに変換します。ROSのメッセージにシリアライズ、デシリアライズする処理も自動で生成されます。 ③ ROSGeometry 座標系やオイラーとクォータニオンの変換などの幾何学的変換を行います。ちなみに、ROSとUnityでは座標系が違います。また、CGソフトとしての側面をもつUnityでは角度の表現にクォータニオンが多く用いられます。 ROS2側の環境構築 ROS2の環境構築はすでに済んでいることを想定しています。まだインストールしていない場合は、このページなどを参考に作業してください。 まず、新しいワークスペースを作成して、srcディレクトリの中にROS-TCP-Endpointパッケージをクローンします (ワークスペースの作成についてはこちらを参照)。その後、パッケージをビルドします。 $ mkdir -p ~/ros2_unity_test_ws/src $ cd ~/ros2_unity_test_ws/src/ $ git clone -b ROS2 https://github.com/Unity-Technologies/ROS-TCP-Endpoint/ $ cd ~/ros2_unity_test_ws/ $ colcon build $ echo "source ~/ros2_unity_test_ws/install/setup.bash" >> ~/.bashrc $ source ~/.bashrc 以下のROS-TCP-Endpointを起動するコマンドを実行してエラーが出なければ、ROS2側の準備は完了です。の部分は適宜置き換えて実行してください。UnityでROS2との通信を行うときは、常にROS2側でROS-TCP-Endpointを起動しておきます。 $ ros2 run ros_tcp_endpoint default_server_endpoint --ros-args -p ROS_IP:=<your IP address> [INFO] [1630459690.215017900] [TCPServer]: Starting server on <your IP address>:10000 Unity側の環境構築 まずは、新しいプロジェクトを作成して開きます。 WindowタブからPackage Managerを開きます。Add package from git URLを選択して、https://github.com/Unity-Technologies/ROS-TCP-Connector.git?path=/com.unity.robotics.ros-tcp-connectorを入力します。これで、ROS-TCP-Connectorがプロジェクトに追加されました。 次に、Roboticsタブから、ROS Settingsを選択します。すると、以下のようなウィンドウが表示されるので、必要な項目を設定します。 Connect on Startupをチェックする ProtocolをROS2にする ROS IP Addressの欄に、ROS2がインストールされている端末のIPアドレスを入力する Show HUDをチェックする ROS2とUnityの環境構築は以上で完了です。次回は、ROS2からパブリッシュされたメッセージを、Unityでサブスクライブする処理を実装します。 次の記事→ROS2とUnityを連携させる (2)UnityでSubscribe https://github.com/Unity-Technologies/Unity-Robotics-Hub/blob/main/tutorials/ros_unity_integration/README.md ↩
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unityでマルチチャンネル音声入力を試す

はじめに UnityはMicrophoneクラスを使えば簡単にマイクから音声データが取得出来ます。 ただ、Microphoneクラスは1デバイスしか識別しないため、同時に複数のマイク入力をやりたい場合は複数のオーディオIFを接続する必要があります。 5台つながったのでマイク祭の始まり!ZOOM製品が多いのはたまたまです。 pic.twitter.com/1rezY8o9Bl— アオダマ (@aodama) June 12, 2021 こんな状況になります… テストの度にこれではとても面倒なので、これを何とかしようと音声のマルチチャンネル入力を試すことにしました。 なお検証環境はUnity 2020.3.18f1です。 結果 マルチチャンネル入力対応のオーディオIFとASIOドライバを使うことで、1台のオーディオIFで複数マイク入力出来るようになりました。 マイクが3本しかなかったので地味ですが、各マイクに音が入るとミキサーが反応しています。 ASIOドライバ経由だとLiveTrak L-8の入力がマルチチャンネルで行えるので、これで複数オーディオIF繋げなくても複数マイク入力のテストがUnityで出来る! pic.twitter.com/5Gt9FklPx4— アオダマ (@aodama) August 20, 2021 ASIOドライバならマルチチャンネル入力できるの? オーディオIFによっては12in/4outのような複数入力対応している製品がありますが、UnityのMicrophoneクラスからはあくまで1デバイス(1入力)としか認識されません。 しかしASIOドライバを経由すれば複数入力出来るようなので、UnityからASIOドライバ経由でオーディオIFにアクセスできればマルチチャンネル入力が使えそうです。 今回検証に使うオーディオIFは12in/4out対応のZOOM LiveTrak L-8です。 https://zoomcorp.com/ja/jp/digital-mixer-multi-track-recorders/multi-track-recorders/LIVETRAK-L-8/ まずDTMソフトのFL StudioからL-8の入力を確認すると、ASIOドライバ使用時はスペック通り12in出来ることがわかりました。 ちなみにキャノンケーブルで接続するマイクはIn1~6になります。 ASIOSDKを使って動作確認 ここからASIO SDKをダウンロードします。 https://www.steinberg.net/developers/ とりあえず動かすところまで持っていくのはここを参考にするといいでしょう。 https://zenn.dev/kodai100/articles/ca449cf826e5ce 上記サイトとASIO SDK付属のhostsample.cppを参考にしてASIOドライバが使えるようになったら、データ入出力時に呼ばれる ASIOTime* bufferSwitchTimeInfo(ASIOTime* timeInfo, long index, ASIOBool processNow) で音声データが取得出来ているか確認できます。 確認のやり方は色々ありますが、私は3秒録音(メモリに保存)し、録音終了後に保存した音声を再生して確認しました。 なお真面目に対応するとASIOSampleTypeに合わせてデータを整形しないとですが、今回はL-8限定でASIOSTInt32LSBだけ処理しました。あくまで確認なので。 問題はこれをUnityからどうやって使うかになります。実装の候補としては ASIOSDKをDLL化してC#側でDllImportする ASIOSDKをC++/CLIを使ってアセンブリとして使う C#でASIOSDK相当を再実装(やることは主にレジストリの読み込みとCOMを扱うだけなので) あたりですが、ぶっちゃけどれも面倒だ… 救世主NAudio ASIOドライバをUnity(マネージド環境)で動かせるライブラリがないかなーと探していたらありました! NAudio https://github.com/naudio/NAudio それもASIOで録音出来る! https://github.com/naudio/NAudio/blob/master/Docs/AsioRecording.md はい、もうさっきのASIO SDKは不要です。もう一気にUnityでやってしまいましょう。 ただ、過去トラブルが出ているようですが、今回試した限りでは特にトラブルはありませんでした。 http://furipro.blog.fc2.com/blog-entry-8.html NAudioのインストール NAudioのver.1.8.4はビルド済みのzipがあるので、それをダウンロードします。 https://github.com/naudio/NAudio/releases/tag/v1.8.4 新規でUnityプロジェクトを作り、NAudio-Release.zip内のNAudio.dllをUnityのAssets配下のどこかにコピーします。 慣例に従うならAssets\Plugins\x86_64内です。 これでNAudioを使う準備は出来ました。 ASIOドライバの初期化 UnityでC#スクリプトを作成し、最低限これだけ書けば動きます。 private AsioOut _asioOut; private void Start() { _asioOut = new AsioOut("ZOOM L-8 ASIO Driver"); // 使用するオーディオIF _asioOut.InitRecordAndPlayback(null, 12, 48000); // 12ch録音する _asioOut.InputChannelOffset = 0; // 録音する先頭ch _asioOut.AudioAvailable += OnAsioOutAudioAvailable; // データ取得時のイベント登録 _asioOut.Play(); // 録音開始 } void OnAsioOutAudioAvailable(object sender, AsioAudioAvailableEventArgs e) { e.GetAsInterleavedSamples(_inputSamples); // 事前に確保しておいたfloat[]。サイズはASIOバッファサイズ * ch数 // 音声データをUnityのメインスレッドに渡す(ConcurrentQueueを使うと簡単) } 録音が始まり音声データが入ってくると登録したイベントが呼ばれます。 InputChannelOffsetはどのチャンネルから読み込むか指定できます。L-8の入力は なので、マイクの音声データだけ取るなら _asioOut.InitRecordAndPlayback(null, 6, 48000); _asioOut.InputChannelOffset = 2; と設定出来ます。 注意すること 音声データ取得時のイベントはUnityのメインスレッドとは別スレッドで呼ばれるイベントなので、Unityの機能を使う場合はUnityのメインスレッドに音声データを渡す必要があります。 また音声データは ・インターリーブになっている ・0~1に正規化されている(ASIOSampleTypeに合わせた変換はやらなくていい!ありがたい!) の点に注意です。インターリーブはこんな処理で直列な音声データに戻せます。 var samplesPerBuffer = 512; var ch = _inputSamples.Length / samplesPerBuffer; var buf = new float[samplesPerBuffer]; for (var i = 0; i < ch; ++i) { for (var j = 0; j < samplesPerBuffer; ++j) { buf[j] = data[i + ch * j]; } // チャンネル毎の処理を行う } 後は好きに加工して処理するなりAudioSourceに書き込むなり自由です。 最後に これでオーディオIFとマイクの山で苦労している方のお役に立てば幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unity C# Invoke()について、

Unity Invokeでググると、MonoBehaviour.Invoke() がHITし過ぎる。 しかし本当に知りたいのは .NETのMethodBase.Invoke() だったのだ。 何という事でしょう、、、サンプルにあるInvoke()は指定時間後に実行されると思ったら、パラメータは違うし挙動も違うし、 大混乱という人が少なからずいるんじゃないかと思いまして、 私?私はググったから大丈夫でしたよ? なんてね。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む