20200219のUnityに関する記事は5件です。

Azure × MR開発準備(HoloLens2、MRTKv2.3.0、Unity2018.4.2f1)

こちらはKumamoto HoloLens ミートアップ vol.5のAzure × HoloLens2の開発準備を整える記事になります。当日、開発を楽しむために、下記の事前準備を行ってください。実機なしでもできます。

開発環境

・Windows 10
・Visual Studio 2019 Community
・Windows 10 SDK (10.0.18362.0)
・Unity Hub
・Unity 2018.4.2f1
・Azure アカウント

準備

Visual Studio 2019 ダウンロードからCommunityをインストールしてください。

Windows 10 SDKからWindows 10 SDK (10.0.18362.0)をインストールしてください。

Microsoft Mixed Reality Toolkit v2.3.0からunitypackageをダウンロードしてください。
・Microsoft.MixedReality.Toolkit.Unity.Examples.2.3.0.unitypackage
・Microsoft.MixedReality.Toolkit.Unity.Extensions.2.3.0.unitypackage
・Microsoft.MixedReality.Toolkit.Unity.Foundation.2.3.0.unitypackage
・Microsoft.MixedReality.Toolkit.Unity.Tools.2.3.0.unitypackage

Unity をダウンロードからUnity Hubをインストールしてください。

Unity ダウンロード アーカイブからUnity 2018.4.2 をUnity Hubからインストールしてください。

Azure の無料アカウントを今すぐ作成しましょうからAzureアカウントを作成してください。Azure Portalにサインインできる状態にしておくこと。

確認事項

Unity Hubを開いて、Unity 2018.4.2f1でプロジェクトを新規作成します。

image.png

名前はMRTK230にしました。
image.png

開いたらこんな感じです。
image.png

ダウンロードしたMRTKをインポートします。
image.png

image.png

Importをクリックします。
image.png

同様に、Tools、Extensions、Examplesをインポートしてください。
image.png

MRTK Project Configuratorが表示されたらApplyをクリックしてください。
image.png

HandInteractionExamplesを開きます。
image.png

TMP Importerが表示されたら、Import TMP Essentialsをクリック。インポート後に、Import TMP Examples & Extras もクリックしてください。
image.png

スタートボタンを押して、動作確認してください。q,w,e,a,s,dキーで移動、ShiftキーでHandの表示、Rayを物体に合わせてクリックでつかめます。

動作確認ができたら、BuildSettingsを開きます。
image.png

App Open Scenesをクリックし、HandInteractionExamplesシーンが選択されていることを確認、PlatformはUniversal Windows Platformを選択し、Switch Platformをクリックしてください。
image.png

Player Settingsを開き、Inspectorビューにある設定を確認します。
image.png

image.png

image.png

image.png

BuildSettingsにもどり、Buildをクリックします。

Holo2フォルダを作成し、選択してください。
image.png

ビルドが完了したら、作成したHolo2フォルダの中のMRTK230.slnをVisual Studio 2019で開いてください。
image.png

image.png

Release、ARMに設定し、Ctrl+Shift+Bを押して、ビルドしてください。
image.png

ビルドが完了したら、HoloLens2にデプロイする準備が完了です。

わからないことがあれば @sotongshi までDMください。
3/7のKumamoto HoloLens ミートアップ vol.5はみんなで一日開発しましょう!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity×VR】個人的ベストプラクティス & ワークアラウンド集【2019年度版】

思い出したとき or 気が向いたときに更新

◥◤ 環境構築@ハードウェア

  • 開発用PCおよびVR機器等は,2セット用意すると良い.故障時のスペアとして,また,検証実験を平行して行う際に良い.そして何よりも,在宅作業用と学校作業用をそれぞれ用意することで,持ち運びの労力が大幅に省けるというメリットがある.

  • 大量のデータを扱う上に,技術情報を調べながらの開発だと,ブラウザが開くタブが100を超えることも多々あるため,メモリを盛っておく.休止モードはメモリの中身をストレージに書き込むため,ストレージの空き容量も十分確保しておく.バックアップ用のストレージも忘れずに.

  • 周辺機器もきちんと揃えておこう.まず外付けのPCクーラーは必須である.VR用PCだからと油断しているとOSごと焦げる.また,PCの画面は最低でも2枚ほしい.大量のログやエラーをさばくうえで,画面の狭さは致命傷となり得る.キーボードとマウスは無線のものが良い.設置位置が自由であれば,長時間の作業でも,肩・背中・目などへの疲労を軽減できる.

  • 機器が上手く動かない場合,ソフトウェアの設定ミス等だけでなく,ハードウェアの初期不良,経年劣化も疑うと良い.コネクターを純正品から別の既製品に変えたら正常に動作した,ということもあった.コネクターを買い足す場合には,端子の両端の規格を確認しておこう.普段見ないような組み合わせになっていることもある.

◥◤ 環境構築@ソフトウェア

VR機器との連携

  • 今回の構成は,UnityでVR環境を構築し,SteamVRを経由してOpenXR規格で,VR機器と連携,とした.実装開始時点で,容易にマルチデバイス対応可能な方法はこれくらいしかなかったが,現時点ではそうでもない.構成は適宜検討されよ.

エディタのカスタマイズ

  • Unityエディタは画面構成をカスタマイズできる.著者はディスプレイが1枚なら図 19上のように,ディスプレイが2枚なら図 19下のようにしている.ポイントはヒエラルキーウィンドウとインスペクターウィンドウを隣接させていること,そしてコンソールウィンドウができるだけよく見えるようにしているところである.特に,コンソールウィンドウは様々なログやエラーが表示される,「ヒントウィンドウ」でもある.常にその全体が視界に入るようにしておけば,問題解決のスピードも上がる.スペースに余裕があるのなら,図 19下のように,セカンドディスプレイいっぱいに表示すると良い.

そのほか

  • GPU周りは意外によく不調になる.とりあえず公式のツールを使うなどして,ドライバー等のアップデートをしておく.なお,Unityエディタのアップデートは.少し慎重になった方が良い.まれに仕様への破壊的変更が行われるため,作業中のプロジェクトをフォルダごと複製したものを,新しいバージョンで開いて,一通りの作業が問題なくできるか検証すべきかもしれない.特に,Previewの機能は注意されたし.筆者の環境ではGPUを用いたベイクが2019.3から機能不全になっている.

◥◤ レベルデザイン

レベルデザインとは

Prefab

  • NestedとVariant
  • どうネストする?

ギズモの表示
ピボット

エディタ拡張の利用

  • ProGrids
  • 自作拡張,ショートカット

小話

  • トイレで寿命が縮んだ話

命名規則とヒエラルキーウィンドウによる検索絞り込み

◥◤ ライティングそしてベイク

各種ベイクの設定方法と注意点

設定
static
影投影,クリッピング
アリアライト,えみっしぶ

◥◤ スクリプティング

ライフサイクル

物理挙動・衝突/接触判定

  • ライフサイクルを踏まえる
  • レイヤーを分ける

SteamVR Plugin周りの扱い

小話

  • Staticの怪

VRにもテストを

  • Prefabで元に戻せる.あるいはシーンを分けて

◥◤ VR体験実施時の配慮など

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Unity]オーディオクリップ設定による発生問題

広告 インディーズチームでAzraelという音ゲーを出しています。現在はiOSバージョンしかありません。 Androidはできる次第リンク先を入れます。 有料ですが、音ゲーにご興味のある方是非遊んでみてください!。 TwitterAzrael公式 iOS: 問題1アプリ起動が遅い 原因 PreloadAudioDataがオンになってるかを確認。 オンになってると、アプリ起動時シーンに入るタイミングで、オンになってるすべてのオーディオのロードに入るため、起動が遅くなる現象が起きます。 問題2アプリ容量が大きい 原因 LoadTypeがCompressedInMemoryになってるかを確認。 アプリパッケージ作った時容量が大量に増えるのが現象です。 問題3音再生時にフレームが落ちる 原因 PreloadAudioDataがオフになってるかを確認。 オフになってると、音再生時にcpu負荷がかかりますので、フレームが落ちます。なので、フレーム保持したいアプリとかは事前にローディングタイミングでLoadAudioData()で読み込み処理を追加する必要があります。 汎用まとめ 大体のロードタイプ LoadType=DecompressOnLoad 大きい過ぎて展開できないファイルのみ LoadType=CompressedInMemory 時間が長いファイルなど(例:BGM) LoadType=Streaming CompressionFormat Android : Vorbis iOS : Vorbisでも問題ないと思いますが、参考からMP3が最適の様です インポート時自動設定拡張 using UnityEngine; using UnityEditor; public class UnityAssetImporter : AssetPostprocessor { /// <summary> /// 音源データインポートした後呼ばれる /// </summary> private void OnPostprocessAudio(AudioClip clip) { var audioimporter = (AudioImporter)assetImporter; audioimporter.Setting("iOS", AudioCompressionFormat.MP3, clip.length); audioimporter.Setting("Android", AudioCompressionFormat.Vorbis, clip.length); audioimporter.preloadAudioData = false; } } public static class ImpoterUtility { public static void Setting(this AudioImporter importer, string platform, AudioCompressionFormat acformat, float length) { var setting = importer.GetOverrideSampleSettings(platform); setting.compressionFormat = acformat; //適当に時間でロードタイプ決める if (length >= 5f) setting.loadType = AudioClipLoadType.Streaming; else setting.loadType = AudioClipLoadType.DecompressOnLoad; importer.SetOverrideSampleSettings(platform, setting); } } 注意:手動でaudioclipインスペクター設定更新した時、拡張ファイル一回走りますので注意
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Unity]オーディオクリップ設定と注意

広告 インディーズチームでAzraelという音ゲーを出しています。現在はiOSバージョンのみです。 Androidはできる次第リンク先を入れます。 有料ですが、音ゲーにご興味のある方是非遊んでみてください!。 TwitterAzrael公式 iOS: 問題1アプリ起動が遅い 原因 PreloadAudioDataがオンになってるかを確認。 オンになってると、アプリ起動時シーンに入るタイミングで、オンになってるすべてのオーディオのロードに入るため、起動が遅くなる現象が起きます。 問題2アプリ容量が大きい 原因 LoadTypeがCompressedInMemoryになってるかを確認。 アプリパッケージ作った時容量が大量に増えるのが現象です。 問題3音再生時にフレームが落ちる 原因 PreloadAudioDataがオフになってるかを確認。 オフになってると、音再生時にcpu負荷がかかりますので、フレームが落ちます。なので、フレーム保持したいアプリとかは事前にローディングタイミングでLoadAudioData()で読み込み処理を追加する必要があります。 汎用まとめ 大体のロードタイプ LoadType=DecompressOnLoad 大きい過ぎて展開できないファイルのみ LoadType=CompressedInMemory 時間が長いファイルなど(例:BGM) LoadType=Streaming CompressionFormat Android : Vorbis iOS : Vorbisでも問題ないと思いますが、参考からMP3が最適の様です インポート時自動設定拡張 using UnityEngine; using UnityEditor; public class UnityAssetImporter : AssetPostprocessor { /// <summary> /// 音源データインポートした後呼ばれる /// </summary> private void OnPostprocessAudio(AudioClip clip) { var audioimporter = (AudioImporter)assetImporter; audioimporter.Setting("iOS", AudioCompressionFormat.MP3, clip.length); audioimporter.Setting("Android", AudioCompressionFormat.Vorbis, clip.length); audioimporter.preloadAudioData = false; } } public static class ImpoterUtility { public static void Setting(this AudioImporter importer, string platform, AudioCompressionFormat acformat, float length) { var setting = importer.GetOverrideSampleSettings(platform); setting.compressionFormat = acformat; //適当に時間でロードタイプ決める if (length >= 5f) setting.loadType = AudioClipLoadType.Streaming; else setting.loadType = AudioClipLoadType.DecompressOnLoad; importer.SetOverrideSampleSettings(platform, setting); } } 注意:手動でaudioclipインスペクター設定更新した時、拡張ファイル一回走りますので注意
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Unity][Fee]セーブデータを暗号化する

はじめに

自作ライブラリ開発日記です。
https://github.com/bluebackblue/fee_core

unitypackage
https://github.com/bluebackblue/fee_core/releases

データ

public class Data
{
    int money;
}

セーブ

コード

public static System.Collections.IEnumerator Save(Data a_data)
{
    string t_pass = "asdf1234";
    string t_salt = Fee.MD5.MD5.CalcMD5(t_pass);
    string t_filename = "savedata";
    byte t_version = 0x01;

    //1、ObjectToJsonString
    string t_jsonstring = Fee.JsonItem.Convert.ObjectToJsonString<Data>(a_data);
    if(t_jsonstring == null){
        yield break;
    }

    //2、StringToUtf8Binary.Convert
    byte[] t_plane_binary = Fee.StringConvert.StringToUtf8Binary.Convert(t_jsonstring);
    if(t_plane_binary == null){
        yield break;
    }

    //3.RequestEncryptPass
    byte[] t_binary_encrypt = null;
    {
        Fee.Crypt.Item t_crypt_item = Fee.Crypt.Crypt.GetInstance().RequestEncryptPass(t_plane_binary,0,t_plane_binary.Length,t_pass,t_salt);
        while(t_crypt_item.IsBusy() == true){
            yield return null;
        }
        t_binary_encrypt = t_crypt_item.GetResultBinary();
        if(t_binary_encrypt == null){
            yield break;
        }
    }

    //4、System.Array.Copy
    byte[] t_binary_encrypt_and_version = new byte[t_binary_encrypt.Length + 1];
    {
        System.Array.Copy(t_binary_encrypt,0,t_binary_encrypt_and_version,1,t_binary_encrypt.Length);
        t_binary_encrypt_and_version[0] = t_version;
    }

    //5、RequestSaveBinaryFile
    {
        Fee.File.Item t_file_item = Fee.File.File.GetInstance().RequestSaveBinaryFile(Fee.File.File.SaveRequestType.SaveLocalBinaryFile,new Fee.File.Path(t_filename),t_binary_encrypt_and_version);
        while(t_file_item.IsBusy() == true){
            yield return null;
        }
        if(t_file_item.GetResultType() != Fee.File.Item.ResultType.SaveEnd){
            yield break;
        }
    }

    //成功。
    yield break;
}

1、ObjectToJsonString

インスタンスをJSON文字列化

{"money":123l}

2、StringToUtf8Binary.Convert

JSON文字列をバイト配列化

[ 0]    0x7b    System.Byte
[ 1]    0x22    System.Byte
[ 2]    0x6d    System.Byte
[ 3]    0x6f    System.Byte
[ 4]    0x6e    System.Byte
[ 5]    0x65    System.Byte
[ 6]    0x79    System.Byte
[ 7]    0x22    System.Byte
[ 8]    0x3a    System.Byte
[ 9]    0x31    System.Byte
[10]    0x32    System.Byte
[11]    0x33    System.Byte
[12]    0x6c    System.Byte
[13]    0x7d    System.Byte

3.RequestEncryptPass

バイト配列を暗号化

[ 0]    0xa2    System.Byte
[ 1]    0xdd    System.Byte
[ 2]    0xcb    System.Byte
[ 3]    0xd9    System.Byte
[ 4]    0xd2    System.Byte
[ 5]    0xec    System.Byte
[ 6]    0x7c    System.Byte
[ 7]    0xcc    System.Byte
[ 8]    0x9e    System.Byte
[ 9]    0xd6    System.Byte
[10]    0xd7    System.Byte
[11]    0xf5    System.Byte
[12]    0xd3    System.Byte
[13]    0x36    System.Byte
[14]    0x3b    System.Byte
[15]    0x39    System.Byte

4、System.Array.Copy

配列の0番目にバーションを設定
配列の1番目以降は暗号化したバイト配列

[ 0]    0x01    System.Byte
[ 1]    0xa2    System.Byte
[ 2]    0xdd    System.Byte
[ 3]    0xcb    System.Byte
[ 4]    0xd9    System.Byte
[ 5]    0xd2    System.Byte
[ 6]    0xec    System.Byte
[ 7]    0x7c    System.Byte
[ 8]    0xcc    System.Byte
[ 9]    0x9e    System.Byte
[10]    0xd6    System.Byte
[11]    0xd7    System.Byte
[12]    0xf5    System.Byte
[13]    0xd3    System.Byte
[14]    0x36    System.Byte
[15]    0x3b    System.Byte
[16]    0x39    System.Byte

5、RequestSaveBinaryFile

Application.persistentDataPathにファイルをセーブ

ロード

コード

public static System.Collections.IEnumerator Load(Data a_data)
{
    string t_pass = "asdf1234";
    string t_salt = Fee.MD5.MD5.CalcMD5(t_pass);
    string t_filename = "savedata";
    byte t_version = 0x01;

    //1、RequestLoad
    byte[] t_binary_encrypt_and_version = null;
    {
        Fee.File.Item t_file_item = Fee.File.File.GetInstance().RequestLoad(Fee.File.File.LoadRequestType.LoadLocalBinaryFile,new Fee.File.Path(t_filename));
        while(t_file_item.IsBusy() == true){
            yield return null;
        }
        t_binary_encrypt_and_version = t_file_item.GetResultAssetBinary();
        if(t_binary_encrypt_and_version == null){
            yield break;
        }
        if(t_binary_encrypt_and_version[0] != t_version){
            yield break;
        }
    }

    //2、RequestDecryptPass
    byte[] t_plane_binary = null;
    {
        Fee.Crypt.Item t_crypt_item = Fee.Crypt.Crypt.GetInstance().RequestDecryptPass(t_binary_encrypt_and_version,1,t_binary_encrypt_and_version.Length - 1,t_pass,t_salt);
        while(t_crypt_item.IsBusy() == true){
            yield return null;
        }
        t_plane_binary = t_crypt_item.GetResultBinary();
        if(t_plane_binary == null){
            yield break;
        }
    }

    //3、Utf8BinaryToString.Convert
    string t_jsonstring = Fee.StringConvert.Utf8BinaryToString.Convert(t_plane_binary,0,t_plane_binary.Length);
    if(t_jsonstring == null){
        yield break;
    }

    //4、JsonStringToObject
    Data t_data = Fee.JsonItem.Convert.JsonStringToObject<Data>(t_jsonstring);
    if(t_data == null){
        yield break;
    }

    //成功。
    a_data.money = t_data.money;
    yield break;
}

1、RequestLoad

Application.persistentDataPathのファイルをロード
ロードしたバイト配列の0番目はバージョンが入っているはず

[ 0]    0x01    System.Byte
[ 1]    0xa2    System.Byte
[ 2]    0xdd    System.Byte
[ 3]    0xcb    System.Byte
[ 4]    0xd9    System.Byte
[ 5]    0xd2    System.Byte
[ 6]    0xec    System.Byte
[ 7]    0x7c    System.Byte
[ 8]    0xcc    System.Byte
[ 9]    0x9e    System.Byte
[10]    0xd6    System.Byte
[11]    0xd7    System.Byte
[12]    0xf5    System.Byte
[13]    0xd3    System.Byte
[14]    0x36    System.Byte
[15]    0x3b    System.Byte
[16]    0x39    System.Byte

2、RequestDecryptPass

ロードしたバイト配列の1番目以降を複合化

[ 0]    0x7b    System.Byte
[ 1]    0x22    System.Byte
[ 2]    0x6d    System.Byte
[ 3]    0x6f    System.Byte
[ 4]    0x6e    System.Byte
[ 5]    0x65    System.Byte
[ 6]    0x79    System.Byte
[ 7]    0x22    System.Byte
[ 8]    0x3a    System.Byte
[ 9]    0x31    System.Byte
[10]    0x32    System.Byte
[11]    0x33    System.Byte
[12]    0x6c    System.Byte
[13]    0x7d    System.Byte

3、Utf8BinaryToString.Convert

複合化したバイト配列をJSON文字列化

{"money":123l}

4、JsonStringToObject

JSON文字列からインスタンスを作成

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む