20200320のUnityに関する記事は6件です。

Unity/IL2CPPでJSONを使う

UnityのIL2CPPで、普通にJSONライブラリを使おうとするとReflection関係でエラーが発生して使えないため、IL2CPPでも使えるライブラリとその使い方を書いておきます。

1. JsonUtility

Unity標準のJSONライブラリです。Dictionaryなど一部の型には対応していませんが、IL2CPP下でも使えます。

using System;
using UnityEngine;

[Serializable]
public class Item {
    public string Name;
    public int Value;
}

string json = JsonUtility.ToJson(item);
Item item = JsonUtility.FromJson<Item>(json);

2. Newtonsoft.Json

普通に使おうとすると他のライブラリ同様、エラーになりますが、以下の手順で動作させることができました。

  1. Newtonsoft.Json の Nuget Package をダウンロード
  2. .nupkg.zip に変えて解凍
  3. lib\netstandard2.0 以下にある dll ファイルを Unity のプロジェクトに追加 (重要、 lib\net45 ではない)
  4. 加えて以下の link.xml もプロジェクトに追加
<linker>
<assembly fullname="System.Core">
<type fullname="System.Linq.Expressions.Interpreter.LightLambda" preserve="all" />
</assembly>
</linker>

あとは通常通り使えるはずです。

using Newtonsoft.Json;

string json = JsonConvert.SerializeObject(item);
Item item = JsonConvert.DeserializeObject<Item>(json);

ちなみに Newtonsoft.Json for Unity が使えるとの情報もありましたが、手元ではエラーで動きませんでした...

参考リンク

https://stackoverflow.com/a/59486989/8320511
https://issuetracker.unity3d.com/issues/il2cpp-notsupportedexceptions-exception-is-thrown-in-build-with-newtonsoft-dot-json-plugin

その他

Utf8Json には、 IL2CPP 用に事前コード生成の機能があるのですが、これも手元ではエラーで動かすことができず... (もしかするとシリアライズするクラスにジェネリクスを使っていたせいかもしれませんが)

こちらで動かなかったライブラリも、バージョンや環境によっては動くこともあると思いますので、いろいろ試してみてください。

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

【Unity(C#)】OculusQuestのハンドトラッキングでボタンを押す

Oculus Integration

この記事内ではOculus Integrationの使用を前提に話を進めていきます。

Oculus Integration内のコード自体は
私レベルでは理解不能なことをいっぱいやっていますが、
パーツを部分的に使用すれば本当に使いやすくなっているのが
今回使ってみて改めてよくわかりました。

ありがとうOculus。
(贅沢言えばハンドジェスチャーのステートとかほしい、、、)

デモ

作成中のお絵描きアプリでRedo,Undo機能の呼び出しにボタンを使いました。

HandPaint1.gif

準備

下記リンクを参考に、デモシーンからボタンをパクってきていろいろ設定します。

【参考リンク】:Oculus Quest ハンドトラッキングを試してみた

コード

一部を抜粋して貼ります。

        [SerializeField] private ButtonController _redoButtonObj, _undoButtonObj, _paintButtonObj;

        private HpPaintFunctionState _paintFunctionState;

        private void Start()
        {
            //Redoボタンが押されたらFunctionステートを変更
            _redoButtonObj.InteractableStateChanged.AddListener(modeChangeToRedo);

            //Undoボタンが押されたらFunctionステートを変更
            _undoButtonObj.InteractableStateChanged.AddListener(modeChangeToUndo);

            //Paintボタンが押されたらFunctionステートを変更
            _paintButtonObj.InteractableStateChanged.AddListener(modeChangeToPaint);
        }


        /// <summary>
        /// Redoモードに変更
        /// </summary>
        /// <param name="obj">リスナー登録時に必要な引数</param>
        private void modeChangeToRedo(InteractableStateArgs obj)
        {
            if (obj.NewInteractableState == InteractableState.ActionState)
            {
                _paintFunctionState = HpPaintFunctionState.Redo;
            }
        }

        /// <summary>
        /// Undoモードに変更
        /// </summary>
        /// <param name="obj">リスナー登録時に必要な引数</param>
        private void modeChangeToUndo(InteractableStateArgs obj)
        {
            if (obj.NewInteractableState == InteractableState.ActionState)
            {
                _paintFunctionState = HpPaintFunctionState.Undo;
            }
        }

        /// <summary>
        /// Paintモードに変更
        /// </summary>
        /// <param name="obj">リスナー登録時に必要な引数</param>
        private void modeChangeToPaint(InteractableStateArgs obj)
        {
            if (obj.NewInteractableState == InteractableState.ActionState)
            {
                _paintFunctionState = HpPaintFunctionState.Paint;
            }
        }

InteractableState.ActionStateという状態になっていれば
各機能(Redo,Undo,Paint)へ切り替わる
という関数を
それぞれのボタンのステートが切り替わった際に実行されるイベントとして登録しています。

まとめ

ButtonControllerInteractableStateChanged
 イベントを登録することでステート変化時に任意の処理が実行可能。

・登録するイベントにはInteractableStateArgsを引数で渡して
 どのステートからどのステートに移行したかに応じた処理が書ける。

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

【爆速メモ】全身3Dデータをclusterのアバターにしたいとき

z01.png


動画だとこんな感じです【clusterにダイブしてみた】
https://youtu.be/_GJlFthi7gw


例によって、作り終えてからの爆速メモなので、
随時、画像追加などで更新していきます。

1.objファイルをBlenderで読み込み、向きを補正して、サイズを拡大する
その後、エクスポートする

2.MeshMixerに読み込み、ポリゴンの削減を行う。
その後、エクスポートする

3.再度Blenderに読み込み、[モディファイアーを追加]して、[デシメート]を行い、ポリゴン数をさらに削減する。
※Blenderは最新版の2.82をインストールしました。
※最終的に32000以下になれば良いのです
z02.png
z03.png
z04.png
z05.png

4.mixamoにアップロードして、リグの設定をして、アニメーションを確認して、T字ポーズでfbx(unity用)でダウンロードする

5.unityは、VRMパッケージがインストールされていること

6.unityでmixamoのfbxデータのアニメーションタイプをHumanoidにしてApplyする。
Configure Avatarでボーンにエラーがないことを確認してDoneする。

7.fbxデータをsceneに出して、positionはオールゼロにする

8.マテリアルを新規作成して、3Dスキャンのデータで作成されたpng画像をマテリアルに入れる

9.scene上のfbxデータに、マテリアルをアタッチする

10.UniVRMでいったんエクスポートする

11.Scene上のfbxデータは削除して、UniVRMでエクスポートされたvrmデータをScene上に出す

12.positionはオールゼロで、再度UniVRMでエクスポートする

13.最後にエクスポートされたvrmデータをclusterのアバターとしてアップロードする

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

UnityでMonaparty(WebGLとMpurse編)

たいそうなタイトルですね、、、

まずはこちらを

・公式doc
https://docs.unity3d.com/ja/current/Manual/webgl-interactingwithbrowserscripting.html

・UnityのWebGLで外部JavaScriptライブラリを使う
h ttps://qiita.com/void_vtuber/items/2aad097eac69771826fd

・モナ版MetaMask Mpurseプログラミング超入門
https://monappy.jp/memo_logs/view/Monacoin_Charts/4654

(qiitaのリンクを張るとリンク元にもこちらの記事が反映されてしまうのは恐れ多い)

結論

・C#からJavaScriptを呼ぼうとする時にjslibファイルを作るが、そこに await/async を書くとビルドエラーになる(たぶん)
(同じような質問もあった??)→https://forum.unity.com/threads/unity-jslib-async-problem.809478/

・なのでJavaScriptからC#にメッセージを送ることに

Massageを送る.html
<head>
  <script>
      async function GetAddress()
          {
            const address = await window.mpurse.getAddress();
            gameInstance.SendMessage("MyGameObject", "MyFunction", address);   
          }
  </script>
</head>

これでやりとりが出来ました。

jslibファイルに await/async 書けるといいけども、、、

( ´∀`)<owari

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

ビルド時にgitのCommit Hashを定数として自動生成する

はじめに

バージョニングはアプリをデプロイする上で大事な要素です。
大抵の開発プラットフォームにはバージョン番号が設定できます。それを設定画面やトップ画面等で表示しているアプリもよく見かけます。
ですが「このアプリはいつ時点のコミットでビルドしたものなのか?」を確認したい場合、数字ではひと目でわかりません。
というわけで、ビルド前に自動で現在のコミットのハッシュ値を定数のクラスとして生成するEditor拡張を作成しました。

準備

Editorフォルダに格納する

CommitHashGenerator.cs

この.csEditorフォルダに格納します。
このとき、自動生成される.csのパスを変更したい場合は以下の箇所を書き換えます。

CommitHashGenerator_Line_28
// replace if necessary
private const string FilePath = "Assets/Scripts/Generated";

生成する

Commit.cs
public static class Commit
{
    public const string Hash = "390181b";
}

このような.csが自動生成されます。

手動生成

スクリーンショット 2020-03-20 1.40.16.png
Create -> CommitHashで手動で生成することができます。
importした直後はこれで.csを生成してください。

自動生成

IPreprocessBuildWithReport.OnPreprocessBuild
ビルドの開始前に呼ばれる上のコールバックのタイミングで.csを自動生成します。

.gitignore.gitkeep

Commit.csは別のコミットでビルドするたびに再生成されるため、.gitignoreに登録することをおすすめします。
しかしそのままだと空フォルダにUnity.metaを生成するので、.gitkeepを使ってフォルダの構成を維持しておくと便利です。

CI対応

JenkinsCircleCIなど、様々なCI/CDツールがあります。
やり方はプロジェクトによって異なると思うので、以下のpublic staticなAPIを公開してあります。

CommitHashGenerator_publicApi
/// <summary>
/// 引数のstringをHashに設定したCommit.csを生成します.
/// </summary>
public static void GenerateScript(string hash)

/// <summary>
/// 現在のcommitのhash値を取得します.
/// </summary>
public static Task<string> CheckCommitHashAsync()

BuildPipeline.BuildPlayerの実行前に上記のAPIを実行すれば生成されます。

使用例

スクリーンショット 2020-03-20 2.16.23.png
デフォルトだと上記のパスに生成されます。
画面に表示してみました。

SampleCommitHash
using UnityEngine;
using UnityEngine.UI;

public class SampleCommitHash : MonoBehaviour
{
    [SerializeField]
    private Text _text;

    private void Start()
    {
        _text.text = Commit.Hash;
    }
}

まとめ

これ作ってなかった自分、アホですわ!
って言いたくなるくらい便利です。
アプリのバイナリのバージョン確認やログ収集など、どの時点かのビルドかがわかるようになるとここまで便利になるとは……。

「リリースしたいんだけど、このバイナリいつビルドしたやつだろう……ヨシ!」1

みたいなことがなくせます。やったね!

前回の記事でMessagePack-CSharpのもろもろを解析した結果思いつきました。
OSSをちゃんと読むの大事ですね。肝心のSerialize/Deserializeしてるあたりはぜんぜんわかんなかったです。わからん。
手元に開発環境がmacしかないので、winとかlinuxとかの人は動かしてみて、だめだったらなんか適当に直しといてください。

おしまい。

CommitHashGenerator.cs

参考

【Unity】ビルド時にGitコミットハッシュをバージョン情報に含めた件
Git で現在のコミットのハッシュを取得する方法
(小ネタ)改行文字を削除する
スクリプトからテンプレを自動作成【Unity】【エディタ拡張】
Unityプロジェクトへファイルを追加する際に上書き更新する
【Unity】エディタ拡張で使用できるコールバックを40個まとめて紹介
Unityのエディタ拡張で設定を保存
メニューを追加するための属性「MenuItem」は意外と多機能【Unity】【エディタ拡張】【属性】


  1. もちろんしたことないですけどねそんなこと!!!?!?!!!?!!!?!?!?!?!?!???!!!! 

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

[Unity] UniversalRenderPipelineのRenderScaleをC#から変更する

はじめに

UniversalRenderPipelineのRenderScaleを実行時にC#から変更したいのでコードを書きました。
URPを使っている人向けの情報なので、URPのセットアップは説明は省略します。
ソースコードはここです。

↓結果画面
renderscale.gif

目的

実行時にC#からRenderScaleを変更して見え方を確認したできるようにします。

Editor操作で変更

インスペクタ上でRenderScaleを変更する場合、使っているUniversalRenderPipelineAssetのインスペクタを開きます。
Quality > RenderScaleのスライダーを動かすとRenderScaleが変更されます。

スクリーンショット 2020-03-19 23.31.04.png

C#から変更

GraphicsSettings.currentRenderPipelineでUniversalRenderPipelineAssetを取得すれば、あとはrenderScaleにアクセスできます。
0に近づけると解像度が低くなります。Default値は1です。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.UI;

public class RenderScaleWidget : MonoBehaviour
{
    [SerializeField]
    private Slider renderScaleSlider;

    private UniversalRenderPipelineAsset pipelineAsset;

    private void Start()
    {
        pipelineAsset = GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset;
        if (pipelineAsset != null)
        {
            renderScaleSlider.onValueChanged.AddListener(OnValueChange);
            OnValueChange(pipelineAsset.renderScale);
        }
    }

    private void OnValueChange(float value)
    {
        if (pipelineAsset != null)
        {
            pipelineAsset.renderScale = value;
        }
    }
}

さいごに

URPのRenderScaleを変更できるようになりました。
UniversalRenderPipelineAssetの他のパラメーターも変更できます。

URPの使い方をもっと知りたい方はこちらをどうぞ。
技術書典8 新刊
Unity実践UniversalRenderPipeline
技術書典応援祭
BOOTH

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