20200604のUnityに関する記事は11件です。

[Unity]Motion Blurで勘違いしてたこと・続 ~Post Processing Stack ゴメンナサイ。でもダメ~

前回の記事 で、

Post Processing Stack の Motion Blur は、カメラの角度や座標の変化によって画面はブレますが、カメラが不動・あるいはあまり動かないときに、 視野内でオブジェクトがどんなに激しく動こうとモノがブレない

と書きましたが。間違いでした。

ブレました

ブレる.gif
▲ブン・・・ブン・・・

image.png
Post-Processing Profile の Motion Blur の 「Frame Blending」 という値を、0より大きい値にすることで実現できました!

でも、ちょっと違うんです。コレじゃなかったんです。

何が気に入らないの?

まず、 カメラを動かしてブレさせたとき の絵をご覧ください。
blur_1.JPG
輪郭がボヤけるような感じになっていて、リアルなブレ方になっているのがわかります。

一方、 「Frame Blending」を使ってオブジェクトを動かしてブレさせたとき の絵がこちらです。
※中央のブロックに注目してください。
blur_2.JPG
フレーム感を補間してるに過ぎないので、ブレてはいるんですが 輪郭がはっきりした残像 が遅れて消えてるに過ぎず、イマイチきれいなブレ方ではありません。

理想

モーションブラー_2.jpg

やはりこちらを持ち出しますが、やはり輪郭がぼやけるようなブレ方・・・というより 色が動きの線上に伸びるようなブレ方 にしたいなと思っていて、それにはやはり前述のカメラを動かしたときのようなブレ方が望ましいのです。

引き続き調べます。

ちなみにゼノブレイドリメイク版はサブクエストしすぎてまだモナドもらってません。

試してみようと思ってるやつ

会社で 良さげなGitHub を共有していただいたので、これを試してみようと思います。
デモを見たところ、望んでる絵になってそう・・・!

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

DOTweenでカーブさせる

DOTween便利

 1週間ほど前にDOTween使い始めました。便利ですねこれ。
 ただ、ちょっと探した感じ、オブジェクトを円周上でカーブさせる方法が見つかりませんでした。パスをうまいことやるとそれっぽいことができるようですが、勉強がてら拡張メソッドを書いてみました。

できたやつ

DOCurveAroundAndRotateの実行の様子。Cylinderを中心にCubeが回転している。
docurve.gif

public static class DoTweenExt
{
    //centerを中心、axisを軸として、degree(度)回転する
    public static TweenerCore<float, float, FloatOptions> DOCurveAround(this Transform transform, Vector3 axis, Vector3 center, float degree, float duration)
    {
        var from = Vector3.negativeInfinity;
        return DOTween.To(() => 0, (x) =>
            {
                if (float.IsNegativeInfinity(from.x)) from = transform.position;
                transform.position = Quaternion.AngleAxis(x, axis) * (from - center) + center;
            },
            degree,
            duration
        );
    }

    //オブジェクトそのものも回転させる
    public static TweenerCore<float, float, FloatOptions> DOCurveAroundAndRotate(this Transform transform, Vector3 axis, Vector3 center, float degree, float duration)
    {
        var from  = Vector3.negativeInfinity;
        var fromRot = Vector3.zero;
        return DOTween.To(() => 0, (x) =>
            {
                if (float.IsNegativeInfinity(from.x))
                {
                    from = transform.position;
                    fromRot = transform.localEulerAngles;
                }
                var q = Quaternion.AngleAxis(x, axis);
                transform.position = q * (from - center) + center;
                transform.localEulerAngles = fromRot + q.eulerAngles;
            },
            degree,
            duration
        );
    }

    //使い方
    //(x,y,z)=(2,0,0)を中心に3秒かけて90度回転させる。
    //transform.DOCurveAround(Vector3.up, new Vector3(2, 0, 0), 90, 3);
}

解説

 みんな大好き、Toメソッドを使います。Toの使い方ですが、

DOTween.To(() => Vector3.zero, (x) => transform.position = x, new Vector3(3, 0, 0), 1);

 (0,0,0)から(3,0,0)に1秒かけて移動します。

DOTween.To(() => 0, (x) => transform.position = new Vector3(x,0,0), 3, 1);

 上と意味は同じですが、変化する値があくまでもプリミティブなfloatになってます。このfloatを角度にして、角度からposition、localEulerAnglesを割り出します。

 それがCurveAroundAndRotateの

var q = Quaternion.AngleAxis(x, axis);
transform.position = q * (from - center) + center;
transform.localEulerAngles = fromRot + q.eulerAngles;

 この部分です。まずはQuaternionを出します。そのQuaternionと回転させたいVector3を掛ければ、(0,0,0)を中心に回転します。fromは開始位置ですが、あくまでもこの関数が走り始める時点での位置です。変数初期化時にtransform.positionを入れてしまうと、Sequenceで動かすときにおかしくなってしまいます。
 角度も同様で、関数が走り出す時点でのeulerAnglesをfromRotにとっておきます。で、fromRotとさっきのQuaternionのeulerAnglesとを足したものを放り込みます。

所感

 Quaternionってすげー

 ※ CurveAroundAndRotateでオブジェクトの向きがうまく変わらないバグがありましたので、修正しました。(2020/6/5)

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

Unity + VRoid + androidスマホでお手軽にVR観賞を試してみる

はじめに

ただいま趣味でゲームを作成中なのですが、ゲームエンジンをどうするか、という選択肢で急遽Unityが浮上してきました。
Unityは前々から使ってみたくて色々と本を買ってたのですが、全然手付かずだったので、この機会にやるか!と。

で、ふと「そういえば、前に試しに何となく作ったVRoidのモデルがあったな。。」というの思い出しまして、
「折角だからVR化しちゃうか!」となったのが今回の経緯です。
まあ本来の目的から完全に脱線してますよね。悪い癖です。。
でも「自分で作った3DモデルをVRで動かしてみたい!」って思いません?(思いますよね?だから仕方ないのです!)

そんなこんなで色々なサイトの情報を見てみたところ、かなり簡単に作れそうな感じ。。
(ジャイロ機能ってこんな簡単に実装出来るのね。。)
ちなみに参考にさせて頂いたサイトは以下です。(本当にありがとうございます)

https://3owebcreate.com/web/design/vroid_studio_animetion
https://qiita.com/ELIXIR/items/084839ae0824985fcfaf

ちなみにVRっていうとOculusとかが有名ですが、自分にはなかなか手が出せない。。(お値段的に)
なので今回は簡単に試せるスマホのGoogle Cardboard用に作成してみたいと思います。
(勉強しながらって感じになるので、まぁ参考程度のモノと思っていただければ。。)
(画像を沢山張ってるので作業が多そうに見えますが、1時間もあれば終わる気がする。。)

使うもの

  1. VRoidのvrmファイル
  2. unity
  3. スマホ(あとCardboardも)

使うものはこれだけ(多分)ですが、SDK等のインストールが必要そうな感じです。
では、早速作っていきたいと思います。

1. VRoidモデルの準備

今回は既にVRoidのvrmファイルが作成してある状態です。
が、モーションは全く作ってません(過去の自分はモデルを作って満足したらしい)

余談ですが、VRoidモデル自体はかなり簡単に作成出来た気がします(まぁ単に作り込んでないだけなのですが)
ただ、衣装の作り込みは割と面倒だったかも。。(衣装だけこだわった)
blenderで細かく作り込もうとして、予想以上に難しくて断念した記憶があります。。

下記がvroid studioから出力したvrmファイルです。(testちゃん)

image.png

2. Unityプロジェクト作成

まずは「Unity Hub」を起動し、プロジェクトを新規作成します。
ちなみに自分は「2019.3.15f1」のバージョンを使用してます。
プロジェクト名を「TEST_VR」にして、テンプレートに「3D」を選択、と。

image.png

「作成」を押すとUnityが立ち上がります。

3. UniVRMパッケージをインポート

Unity 向けの VRM ファイルの読み書きを行う C# による標準実装、それがUniVRMとのこと。
UniVRMを使うことでVRM形式のファイルが簡単に編集できるという感じでしょうか。。
使わせて頂くしかないですね!

https://github.com/vrm-c/UniVRM/releases
上記リポジトリに公開されているので、最新のパッケージをダウンロードしてきます。
自分が作業した時点では「UniVRM-0.55.0_ce1c.unitypackage」になるようです。

image.png

ダウンロードが完了したら、このファイルをダブルクリックします。(Unityは起動した状態で)
すると以下のウィンドウが立ち上がります。

image.png

インポートをクリックします。

インポートが完了し、プロジェクトアセット内にVRMというフォルダが出来ました!
(これで簡単にvrmが読み込めるはず。。)
image.png

4. 3Dモデルのインポート/配置

きましたね。今回の山場と言っても過言ではない(いや、過言ですね)

インポート自体はUnityのAssetsにドラッグ&ドロップするだけのようです。(なんて簡単なんだ。。)

これを。。
image.png

こうすると。。
image.png

お、確かにtestちゃんのプレハブが作成されてますね。
image.png

で、このプレハブをヒエラルキーのシーン内にドラッグ&ドロップすると。。

image.png

おー!きました!ゲーム内になんかポツンと誰か表示されましたね!ひゃっほー!

5. オブジェクトの調整とVR化

きましたね、メインイベントが。
Google CardboardでのVR化はSDKが公開されていて、ビルド時に適用するだけで簡単に作れるらしいのですが、それじゃ面白くないので「今回は手動でVR化」します。
ちなみに手動で設定した方が映像の描画が早いらしく、処理遅延をなくせるというメリットがある模様。
カスタマイズも好みで色々出来るので、手動の方がお得っぽいですね。

まず、モデルが後ろを向いてるのが気になりますね。。
モデルを選択してTransformの回転Yを180に設定してみます。
image.png

お、こっちを向きましたね。
ヒエラルキーで「空のオブジェクトを作成」を押し、オブジェクト名を「Camera」にします。
image.png

次にヒエラルキーでMainCameraを選択して、cameraの中にドラッグ&ドロップします。
image.png

ふむ、中にMainCameraが入りました。
次にMainCameraを「Main Camera L」にリネームするようです。
image.png

OKですね。次に「Main Camera L」を複製します。
「Main Camera L」を選択→右クリック→複製です。
image.png

複製した「Main Camera L (1)」を「Main Camera R」にリネームします。
image.png

次にMainCameraRを選択し、インスペクターからTagを「Untagged」にします。
このタグというのはその名の通り、参照ラベルみたいですね。
複数のゲームオブジェクトをまとめて扱いたいときに同じタグを設定する、グループ化みたいなイメージ?
ふむ、勉強になりますな。ちなみに「Untagged」はタグなしです。mainCameraから分離するってことかな?

image.png

次にMainCameraRのインスペクターから「Audio Listener」を消します。
右クリック→コンポーネントを削除ですね。
「Audio Listener」というのは音声を再生するデバイスとして機能するようです。
MainCameraにくっついているのがデフォルトみたいですが、シーン内で機能するのは一つだけのようなので、こいつは要らないってことですね!
(まあ今回、音声なんてありませんが。。)

image.png

現在、2つのカメラは完全に重なっている状態だと思うので、調整していきます。
まずは「Main Camera L」です。ビューポート矩形を以下にします。
X=0 Y=0 w=0.5 h=1
image.png

次に「Main Camera R」です。ビューポート矩形を以下にします。
X=O.5 Y=0 w=0.5 h=1
image.png

なんとなくVR感が出てきましたね。
ビューポート矩形というのは、カメラの映像を画面上のどこに表示するかの設定みたいですね。(設定値は0~1)
いまは2つのカメラの映像を並べて表示してるイメージだと思われます。

次にカメラのTransformを調整していきます。

まずは「Main Camera L」のTransformを以下に設定します。
位置:X=-O.1(-0.1) Y=1 Z=-2.5
回転:X=O Y=0.1(+0.1) Z=0
image.png

次に「Main Camera R」です。
位置:X=O.1(+0.1) Y=1 Z=-2.5
回転:X=O Y=-0.1(-0.1) Z=0
image.png

これでカメラの位置調整は完了です。
(モデルがあまりに小さいからカメラを近づけたけど、その分調整した方が良いのだろうか。。一回見てからだなぁ)

6. ジャイロ設定

という訳でジャイロ機能を付けます。
プロジェクト→作成→C#スクリプトを選びます。
image.png

ファイル名を「gyro」にします。
image.png

作成した「gyro」をダブルクリックすると、エディターが起動してきます。
image.png

ここから中身を追加していきます。
Startメソッドに以下を追加します。

Input.gyro.enabled = true;

ジャイロセンサによる入力を有効にするという意味っぽいですね(見た感じ)

続いてUpdateメソッドに以下を追加します。

transform.rotation = Quaternion.AngleAxis(90.0f, Vector3.right) * Input.gyro.attitude * Quaternion.AngleAxis(180.0f, Vector3.forward);

ジャイロセンサから取得した値を、直接カメラの角度に適用しているみたいですが、、
なにこのQuaternionってやつ、めっちゃ難しいぞ。。(数学詳しくないと理解できない。。)
とりあえず、、Quaternion.AngleAxisは「AngleAxisはaxis(軸)の周りをangle度回転するQuaternionを生成します。」って意味のようです。第1引数で角度(オイラー角)、第2引数で軸を指定しているとのこと。なお軸は以下。

Vector3.right(x軸を指定したい場合)
Vector3.up(y軸を指定したい場合)
Vector3.forward(z軸を指定したい場合)

頭が痛くなってきたので、考えのはここまでかな。。
ようはジャイロセンサーの入力値をカメラの上下左右角度に加算しているってことなのだろう。。

とういうわけで、結果的にgyroの中身は以下になります。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class gyro : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Input.gyro.enabled = true;
    }

    // Update is called once per frame
    void Update()
    {
        transform.rotation = Quaternion.AngleAxis(90.0f, Vector3.right) * Input.gyro.attitude * Quaternion.AngleAxis(180.0f, Vector3.forward);
    }
}

これでスクリプトは完成なので、cameraオブジェクトのコンポーネントとして追加します。
(gyroファイルをヒエラルキーのcameraオブジェクトにドラッグ&ドロップすればOKです)
以下みたいになってれば〇。
image.png

7. モーション設定

さて、作業も終盤です。
ここまでの作業でVR鑑賞の機能としては完成なのですが、重大な問題があります。
それは「モデルが色々動いてくれなきゃ鑑賞にならないやん」です。

ただ前述のとおり、モーションは全く作成しておりません!
(正直、この検証のためにわざわざ作る気力はありません。。)

という訳で今回は、ユニティちゃんのモーションを使わせて頂こうと思います。
まずはウィンドウメニューから「アセットストア」を開きます。

image.png

検索BOXに「unity-chan」と入れます。

image.png

検索結果に出てくる「unity-chan! Mosel」をクリック

image.png

本当はダウンロード→インポートの順番なのですが、自分は既にダウンロード済みなので、インポートします。
image.png

ポップアップが出てくるので、インポート!
image.png

(勢いで全部インストールしちゃったけど、正直モーションだけで良かった。。)

これでユニティちゃんモデルがインポートされました。
image.png

ユニティちゃんフォルダの Unity-chan! > Unity-chan! Model > Art > Animations のフォルダをアセット直下に持ってきます。
image.png
image.png

これでユニティちゃんの役目は終わったのでフォルダごと消します(ありがとうユニティちゃん。)
image.png

次にヒエラルキーでtestちゃんを選択します。
image.png

インスペクターからAnimatorを探し、「コントローラー」のインプットボックスをクリックします。
コントローラの選択が出てくるので、「UnityChanActionCheck」を選択します。
image.png

次にウィンドウからアニメーターを開きます。
image.png

いっぱいモーションがありますね。
自動で全部のモーションが流れるようにしたいので、オレンジのモーションで右クリックして「遷移を作成」を選択、遷移したいモーションに繋ぎます。(もっと良いやり方がありそうだけど。。)
image.png

これで自動で色々なモーションをしてくれるようになりました!

8. ビルド

遂にビルドする時がやってきました。。
ただ、ビルドをする前に次のモノを準備する必要があるようです。

・AndroidSDK
・JDK(1.8まで)

上記の2つは以下のサイトで「AndroidStudio」をインストールすると一緒に入手出来るようです。

https://developer.android.com/studio/index.html

今回インストールしたバージョンは3.6みたいです。
ちなみにインストールしたら一回起動して下さい。初回起動時にSDKがインストールされるらしいです。
終わったらもう「AndroidStudio」は使わないので閉じちゃいましょう。

そしたらUnityに戻って、編集→環境設定を開きます。

image.png

外部ツールの下の方に、JDKとSDKのパスを指定する欄があるので、それぞれのパスを指定します。
(JDKを探すのに凄く手間取りました。。)
ちなみに自分はDドライブにインストールしてるのでDですが、普通はCになると思います。
image.png

これで準備は終わりなので、ファイル→ビルド設定を開きます。

image.png

プラットフォームにandroidを選択して「Switch Platform」をクリックします。
Android build suportが未インストールの場合は、入れちゃって下さい。

image.png

デフォルトの状態ではシーンが何も含まれていないので、「シーンを追加」を押して、作成したシーンをビルドに含めます。
そしてビルドを押しちゃいます!
image.png

任意のフォルダを選択して、保存を押します!
image.png

しばらく待つと、.apkファイルが出力されます。これでビルドは完了です。
image.png

7. アプリインストール、実行

あとはapkファイルをスマホに移してインストールすれば完了です。
方法は何でも良いと思いますが、今回はGoogleDrive経由で持っていきます。
(PCからGoogleDriveにアップして、スマホからダウンロードするだけです。)

機種によるかもしれませんが、スマホでダウンロードが完了すると、インストールするか尋ねてきます。
(ちなみに「開発元不明のアプリ」のインストールを許可しておく必要があります。インストールが終わったら設定を戻しておきましょう)

起動するとこんな感じになってると思います。
ちょっと感動ですね。

image.png

おわり

というわけで今回はスマホVRを試してみました。
内容自体はそんなに難しくないですし、初歩的なモノではありますが、
やっぱり自分で作ったキャラが3Dで自由に動いてくれると、めっちゃ嬉しいですね!
あー、Oculus買っちゃおうかなー、、

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

Unity 上のロボットをマイコンシミュレータと同期してデバッグする!

概要

「TOPPERS/箱庭デモ ETロボコンシミュレータ」で,ETロボコン競技者向けのシミュレータを開発してきました.

ですが,現状のシミュレータ,乗り越えるべきチャレンジングな課題が2つあります.

  1. PCスペックが低いとシミュレーションが成り立たない.
  2. マイコンシミュレータ(athrill)のデバッグと同期してUnity側が停止してくれない.

この問題,箱庭WGで仕組み検討している時間同期機構を拡充することで一挙に解決できないかと模索していましたが,意外に簡単に解決できましたので,情報共有します.

なお,箱庭WGで検討中の時間同期の仕組みについては,6/12(金)に開催さ入れるTOPPERSカンファレンス2020の箱庭WGセッションでオンライン説明しますので,興味のある方はぜひご参加ください!

この問題をどう見るか(what)

箱庭WGで開発してきた ETロボコン向けシミュレータ,Unityとマイコンシミュレータ時間同期機構,実は前提とする条件があります.

  • 前提条件

    • マイコンシミュレータ(athrill)のシミュレーション時間速度はUnityのシミュレーション時間に比べて十分早いこと.
  • 時間同期方法

    • この条件を前提として,athrillは,Unity側のシミュレーション時間を見て,自分のシミュレーション時間がUnityよりも進んでいることを検出した場合,athrillのシミュレーション時間の進む速度を遅くすることで,Unity側と時間同期をはかります.

こうやっておけば,athrill側で勝手に時間同期が行われるのですが,PCスペックが低い場合やathrill上で動作するアプリケーションの処理負荷が高い場合は,前提条件が崩れてしまい,時間同期できなくなってしまいます.

自分は,マイコンシミュレータ開発者だったので,athrill側の同期機構ばかりに注力していたのが問題の根源でした.前提をとっぱらって,Unity側にも時間同期の仕組みを入れれば,いろんな問題が一挙に解決するだろうと思い至ったわけです.

どうやって解決に導くべきか(how)

やりたいこと(what)は以下です.

  1. PCスペックが低いとシミュレーションが成り立たない問題を解決したい.
  2. マイコンシミュレータ(athrill)のデバッグと同期してUnity側が停止しさせる.

その解決方法は,先述の通り,Unity側にも時間同期機構を入れることで一挙に上記内容の対応ができるようになるはずです.

1 については,athrillのシミュレーション時間をUnity側が見て,自分のシミュレーション時間が進んでいる場合は,そのシミュレーション時間を止めちゃうことで解決できそうです.

2 についても,1の対応が出来てしまえば,athrill側がデバッグ状態に入れば,athrillのシミュレーション時間の進み幅は一気に遅くなる(人が操作する速度)になりますので,こちらも解決できそうです.

というわけで,Unity側のシミュレーション時間を制御する方法を調べてみることにしました.

Unityのシミュレーション時間

Unityのシミュレーション時間に関しては,Unity公式サイトや先駆者の方の記事が参考になるかともいますので,リンク集のみを以下にまとめます.

対応方法

そういうわけで,Unity側の物理シミュレーション時間は,以下をおさえておけば自分(プログラマ)が制御できることが分かったわけです.

  1. Physics.autoSimulation を false にする
  2. 物理シミュレーション時間は,Physics.Simulate(Time.fixedDeltaTime)で進める

上記を抑えた上での,Unity側のプログラムの変更ポイントは以下でした.

① Unityのシミュレーション時間とathrillのシミュレーション時間との差分時間の許容最大時間を定義する

    public long maxDiffTime = 10000; /* usec */

②差分時間が,許容時間内である場合のみ,物理シミュレーション時間を進める

            if (this.diff_time > -this.maxDiffTime)
            {
                this.unity_simtime += this.delta_time;
          :
          (ロボット制御処理)
          :
                Physics.Simulate(Time.fixedDeltaTime);
            }

上記対応した Unityパッケージを以下で公開しました.

https://github.com/tmori/athrill-sample/blob/master/ev3rt/ev3rt-beta7-release/unity/ev3rt-demo1.1.unitypackage

デモ

とりあえず,TOPPERS箱庭版ETロボコンシミュレータをデバッグする風景をデモしてみます.

操作内容としては,以下になります.

  1. デバッグ状態で,Unityとathrillを停止状態にする.
  2. athrillのシミュレーション時間を 10000クロック進めて止める
  3. しばらく進めて,強制デバッグモードに遷移させる(qコマンド押下)
  4. cpu コマンド,CPUレジスタ状態を確認する.
  5. シミュレーションを継続する.

robocon_debug2.gif

これで,やりたかったこと(what)は一通りできたと思えたので,今日はこれまで.

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

UnityのRandom.rotationが偏る時

Random.rotationでサイコロ振ったのに目が偏る(´・ω・`)

Random.rotationではなくRandom.rotationUniformを使ってみてください。

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

Unityで2Dアクションゲームを制作したときの知見

はじめに

まずは公式リファレンスを見よう

一番言いたいことを最初に書きました。

UnderRocketというゲーム制作を通して得た知見を(自分用のメモとして)残しておきます。
Unityを学び始めて1年未満くらいの人向けの内容です。

特に以下のようなものを実装したい人向けです
・2Dのアクションゲーム
・WebGLビルドをし、公開する
・ハイスコアを保存、共有したい

(UnderRocketは以下のサイトで遊べるので、ぜひプレイしてみてください^^)
UnderRocket | unityroom

汚いですがコードはこちら
UnderRocket GitHub

TilemapとCinemachine

ステージ外を移さないカメラ移動

Cinemachineを利用します。
インストールの仕方を調べると、AssetStoreからインストールという記事がたくさんありますが、
現在はUnityエディタからインストールできます。

一番注意する点として、カメラの枠より小さい範囲を映そうとすると上手くいきません。
ステージの大きさや、映す範囲には注意してください。

Cinemachineインストール方法
Cinemachineの基本的な使い方

Tilemapを利用する

2Dゲームで素直にsceneにgameObjectを置いてステージを作成しようとすると、だいぶ大変です。
Tilemapを利用すると、簡単に描画・Collider配置ができます。

以下の2サイトを見れば、できると思うので、利用したことがない人はぜひ
コガネブログ
Qiita

Tilemapのtileひとつひとつの間隔が空いてしまう

tilemap.png

原因: SpritesのPixels Per Unitのサイズがタイルに合っていない
tilemap2.png

tilemap3.png

上の画像の場合は、Pixels Per Unitの値を16にする

TilemapとCinemachineを共存させる方法

Cinemachineの映す範囲を、Cinemachine ConfinerのBounding Shape2Dで指定します。
Cinemachine0.png

ここで、代入するものは、Tilemapとは別でステージの範囲に合わせて作成したCompositeCollider2D。

Cinemachine1.png

当然ですが、TilemapのcompositeColliderをカメラの枠にするとうまく動きません。
そのため、ステージの枠用のCompositeCollider2Dを別で用意する必要があるのです。

ただし、Tilemapと別ステージ枠を設定することで、本来狭すぎてCinemachineで映せなかった部分を、実際のステージより大きくすることで映すということができます(ステージ外が映ってしまいますが)。

NCMB

NCMBを利用し、オンラインランキング機能を実装する

今回オンラインランキング機能を実装するにあたり、
NCMB(Nifty Cloud Mobile Backend)というサービスを利用しました。
無料でひと月100万回APIリクエストできるすごいやつです。
NCMB公式サイト

公式のマニュアルや、記事を漁れば環境構築と基本的な実装は難しくないはずです。
クイックスタート(公式)
機能別コード例
コルーチンをいい感じに

前座: NCMBはUnityのWebGLビルドに対応しているのか

開発している途中で、実装は間違っていないはずでUnityエディタ上では動くのに、ブラウザ上では上手く動かないということがありました。
調べると「NCMBはUnityのWebGLに対応していない」とか「WebGL専用のスクリプトを用意してます」みたいなニュアンスの記事を目にします。

結論を言うと専用のスクリプトを使わなくても、WebGL版でもちゃんと動きます。
動かないとすれば、ビルドの設定やその他諸々の問題です。

createDateが参照できない

NCMBのデータストアを利用する際、最初からデータ格納日時である「createDate」とデータ更新日時である「updateDate」が用意されています。
しかし、このcreateDateが参照できなく...ない...ない...
...ありました。

自分で作成したDBでいうところのカラム(PlayerName, Scoreなど)はobj["PlayerName"]などと参照しているので、てっきりobj["createDate"]で参照できると思っていました。
obj.CreateDateでした。
この仕様は一般的なんですかね...私はわかりません。

private NCMBObject obj;

Debug.Log(obj["createDate"].ToString()); //error
Debug.Log(obj.CreateDate.ToString()); //ok

データストアへの登録が終わったかわからない

NCMBObjectに用意されているSaveAsyncを利用してデータストアへのセーブ作業をしているのですが、この関数、エラーは返しても結果は返してくれません。
SaveAsync

例えばスコアランキングを作っていたとして、
①プレイヤーのスコアをデータストアに登録
②データストアからスコアが高い順にn人取得
とやったときに①が完了する前に②をおこなうと、②の結果が変わる可能性があります。

この問題は、プレイヤーの送信予定のデータとデータストアから持ってきたデータを比較することで解決しました。
①データストアからスコアが高い順にn人取得
②n人のスコアと、プレイヤーのデータで比較、処理(クライアント側)。
③プレイヤーのスコアをデータストアに登録

実装

当たり判定を残したまま、壁で跳ね返す

これには様々な方法があると思いますが、今回はRigidbody2Dを利用した方法です。

・Rigidbody2DのBodyTypeをDynamic
・CircleCollider2DのIsTriggerをfalse
・動きの制御はRigidbody2Dで
これさえ守れば、PhysicsMaterialの値次第で様々な跳ね返りができますね。

しかし、「壁でだけ跳ね返ってほしいのに、他のgameObjectとも物理的な衝突処理がされてしまう」という問題になりがちです。

この問題の解決策のひとつとして、「壁衝突用、他衝突フラグ用でふたつのgameObjectを用意する」があります。
・壁衝突用...CircleCollider(IsTrigger = false)、Layerを壁用のLayerと検知(他不要なものは検知しない)
collider1.png

・他衝突フラグ用...見た目に合わせたCollider(IsTrigger = true)、Layerは特に指定なし(Layer単位で無視したいものがあれば)
collider0.png

Layer同士無視するかどうかは、Edit->ProjectSettings->LayerCollisionMatrixから設定できます
collider2.png

毎回データストアを参照しない

UnderRocketの話をすると、各ステージごとにクリアタイム順10名と最近クリア10名の名前とタイム(or日付)を表示します。
プレイヤーがミッションクリアしたときは、ランクインしている可能性があるのでデータストアから最新の情報を読み取ります。
しかし、ミッション失敗したときはどうでしょう?私は最新の情報である必要性は低いと考えました。
そのため、ランキングデータを初回取得時にクライアント側に格納し、ランキング一覧表示や失敗時には、すでにあるデータはクライアント側から、無いデータだけをデータストアからとってくるという処理にしました。

データはDictionaryとして格納
keyはミッション名(SceneManager.GetActiveScene().nameと一致)
valueはstring2つ(playerNameと、timeまたはdate)を持つクラス

プロパティもシリアライズ化したい

「プロパティだけでいいのに、SerializeFieldでInspector上から編集したいから、仕方なくフィールドを用意。プロパティの初期値をフィールドから参照。」

[SerializeField] private int hp;
public int Hp {get; private set;}
private void Awake(){
    this.Hp = this.hp;
}

こういうとき、ないですか?
プロパティの初期値をSerializeFieldで変えられたら...最高ですよね?

そんな魔法がこちら↓
コガネブログ

※公式で意図されたものかわからないのでご用心

フォント

WebGLのビルドでは、Unityのデフォルトのフォント(Arial)を利用していると日本語が表示されません。
日本語に対応したフォントに変更する必要があります。
また、フォントによって大きさが違うので、表示の変化に注意してください。

フォントを一括で変更するには、以下のサイトを参考にしました↓
フォント一括変更

ツイートボタン

WebGL版でツイートする場合、現在開いているウィンドウとは別ウィンドウで開く、という処理が必要になります。
「エディタ上ではできるけど、ブラウザ上からはツイートできない」みたいな人は必見↓

WebGLでツイートボタン

Maximum call stack size exceeded

maximum.png
⇈エラー画像

NCMBを利用して初めてのビルドをし、unityroomに反映させたら出たエラー。
当時、ロードシーンにNCMBSettings等のgameObjectや、BGMなどをロードするgameObjectを置いていました。
そしてロードシーンのStart()でタイトルシーンへ移動するようにしていたのです。

つまり、最初の処理でやることが多すぎ、ということだったんですね。
「NCMBがダメなのか?」と当時試行錯誤しましたが、NCMB関連のgameObjectをタイトルシーンに移動させることで解決しました。

フルスクリーンのときに文字の表示が違う(大きさ)

フルスクリーンにしたときに、Canvas内の見え方が変わるというお話。
今まで見えていたTextがフルスクリーンにすると範囲をはみ出て見えなくなってしまった、なんてこともありました。

Canvasの設定でなんとかできそうですが、今はどちらのサイズでも注意する、とだけしています。
どなたか知りませんか(小声)

停止処理をtimeScaleに頼らない

動作停止の簡単な実装方法としてTime.timeScaleを0にするというものがあります。
これによりUpdateは呼ばれたままで、Time.deltaTimeが0になったり、FixedUpdateが呼ばれなくなったりします。
つまり、プレイヤーの入力は受け取るまま、時間経過によるgameObjectの動きを止められます。

最初この方法を使っていたのですが、NCMBを利用するにあたって、主にコルーチンが動かしたいときに動かせない状態になってしまいました。
自作のものなら実時間で測るコルーチンを利用すれば、できなくはないのですが...。

他の機能も実装しづらくなる可能性があるので、timeScaleを使わずフラグによって処理する形にしました。
Update()の冒頭で、止まっているフラグならRigidbody2D.simulated = falseにするなどです。

Unityの便利機能

ColliderとRigidbodyのPhysicsMaterialの違い

ColliderとPhysicsの両方にPhysicsMaterialを代入できます。

ColliderとPhysicsのPhysicsMaterialには優先順位があります。
Colliderのほうが優先順位が高く、
基本となるPhysicsMaterialはRigidBodyに、特定の部分だけ変える場合はColliderに
という認識でよさそうです。

ちなみに、何も代入しない場合のデフォルトは
friction = 0.4、bounciness = 0

詳しくはこちら↓
UnityEngine.Rigidbody2D-sharedMaterial

UnityEvent

UnityEvent 公式リファレンス

Buttonで出てくるこれ
unityevent.png

Inspector上でボタンが押されたときにする処理を設定できて、便利ですよね。

注意する点
・UnityEventにInspector上から何も代入してないときに、Invoke()で呼ぶと、エラーにならず次の処理に進む。
・呼ぶ関数の引数は1つまで

サンプルコード

using UnityEngine.Events;

/*省略*/

[SerializeField] private UnityEvent haveDamaged; //攻撃を受けた際の処理
[SerializeField] private UnityEvent destroyMe; //自身が破壊されるときの処理
[SerializeField] private UnityEvent contactEnemy; //敵にあたったときの処理

private void OnTriggerEnter2D(Collider2D collision)
{
    if (collision.CompareTag("Enemy"))
    {
        this.contactEnemy.Invoke();
    }
    if (collision.CompareTag("AttackToPlayer"))
    {
        this.hp--;
        this.haveDamaged.Invoke();
        if (this.hp <= 0)
        {
            this.destroyMe.Invoke();
            Destroy(this.gameObject);
        }
    }
}

スクロールビュー

テラシュールブログ

Tilemap同様、使ってみたら意外と便利だったシリーズ。
大事なのは、contentにvertualGroupをいれることです。
contentの中に空のgameObject→その中に入れたいものを複数入れるという流れ
contentに入るContentSizeFitterは「Unconstrained」にしておくことで自由にwidth/heightを変えることができます

公式リファレンス

OnEnable()

gameObjectがactiveになったときに呼ばれます。
Awake()より後、Start()より前です。
OnDisable()もあります。
Update()等目立ちすぎて、影薄くなりがちですが、大変便利です。

呼ばれる順番

クリックされたときに呼ばれたいが、ボタンのように選択してほしくない

これはUnderRocketの右上歯車アイコンを押すと、設定が開く、といったときの話です。
Buttonの画像だけ変えるとそれっぽくなりますが、どうしてもゲームの入力中に間違って選択してしまい、そのままEnter/Spaceで押してしまったりします。

そこで、EventTriggerをアタッチしてPointerClickの処理を追加することで、簡単にマウスクリック時の処理ができます。
知ってるかどうかの問題ですが、本当便利ですね。
なお、クリックされたかの判定は、Imageの画像の範囲に自動で合わせてくれていました。
onClick.png

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

Unity IAPは公式APIドキュメントがないので課金処理は自前ネイティブ実装がいいかも

まとめ

  • https://docs.unity3d.com/Manual/UnityIAP.html
  • マニュアルはある。しかしAPIについての最新の説明は存在しないので自己責任でやるしかない。
  • 自分でネイティブ連携するのが最強

現状

-https://forum.unity.com/threads/where-has-unity-iap-scripting-reference-gone.660454/#post-4543948

Understood on the concern. As we are moving more towards Package Manager, we've had to adjust our documentation work flow, and it's still a work in progress. It is something we are actively working on, apologies on the inconvenience.
JeffDUnity3D, May 15, 2019
(今作業中です(2019/05/15))

つまり1年以上放置されてるわけで Unity 2018.3 以降は最新の情報を得る手段がありません。つまりLTS基準で考えると2018版から現在までドキュメントのないものを雰囲気で実装してるわけでAppleやらGoogleやらの方でPurchasing APIに変更やら機能追加やらが入ったときにちゃんと追従されるかも怪しい気がします。

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

Mixed Reality Toolkit V2.4.0 のリリースノートを整理した

Mixed Reality Toolkit V2.4.0が提供されました。

順調に新機能をリリースしながら拡張が進むMRTKことMixed Reality Toolkitですが、先日v2.4.0がリリースされました。今回のエンハンスも便利な機能が色々と追加されたのでリリースノートを読み解きながら追加機能の紹介をしていきたいと思います。

以上をトピック的に整理。

1.環境/デバイス

1.1.対応デバイス

V2.4.0の対応デバイスは以下の通り。

  • Microsoft HoloLens 2
  • Microsoft HoloLens (1st gen)
  • Windows Mixed Reality Immersive headsets
  • OpenVR
  • (Experimental) Unity 2019.3 XR platform
  • Mobile AR via Unity AR Foundation
    • Android
    • iOS
  • Ultraleap Hand Tracking

以前から変わったところはMobile ARが正式対応になりました。あと、興味深いところではUltraleap Hand Trackingですね。これはLeap Motionを利用して、MRTK上でHand Trackingを実現する仕組みです。

1.2.開発環境

開発環境は以下の通り

  • Microsoft Visual Studio (2017 or 2019) Community Edition or higher
  • Windows 10 SDK 18362 or later (installed by the Visual Studio Installer)
  • Unity 2018.4 LTS, 2019(2019.3以降推奨)
  • NuGet for Unity 2.0.0 or newer(任意)

開発環境としては以下の3つはセットアップしていたので試した形では問題なく動作。

  • Unity 2019.3.1f1
  • Unity 2018.4.22f1

2.V2.4.0からの大きな変更点と移行に関する事

フォルダ名の変更

フォルダ構成が変更になりました。これは過去issueにもなっていたLong Path問題への回避策です。
MRTKはC#系の規約「フォルダ名=名前空間」となるように整理されていたのですが。。。
変換の関係は以下の通り。内部の名前空間などが変わったわけではないですしmetaファイルも変更がないようですので、
基本的な移行は前のフォルダーを削除→V2.4.0をインポートするでいいんですが、

MixedRealityToolkit.Generatedフォルダ(カスタムしたパラメータ設定が入ってるフォルダ)はパス変更不要なのでそのまま削除せずに!!!

Previous Folder New Folder
MixedRealityToolkit MRTK\Core
MixedRealityToolkit.Examples MRTK\Examples
MixedRealityToolkit.Extensions MRTK\Extensions
MixedRealityToolkit.Providers MRTK\Providers
MixedRealityToolkit.SDK MRTK\SDK
MixedRealityToolkit.Services MRTK\Services
MixedRealityToolkit.Tests MRTK\Tests
MixedRealityToolkit.Tools MRTK\Tools

コンポーネントの変更

今回は機能追加などの影響で一部構造が変わったものがあります。現行バージョンの機能はそのまま維持されているので、そのままでも当面は問題ありません。
ただ、今回はマイグレーションツールが提供されているので上記の入れ替えを行ったらついでにやってしまいましょう。
マイグレーション対象となる機能は以下のものです。

  • Microsoft.MixedReality.Toolkit.UI.ButtonConfigHelper
  • Microsoft.MixedReality.Toolkit.UI.ObjectManipulator
  • Microsoft.MixedReality.Toolkit.UI.BoundsControl

BoundsControl系はまだ試験的な機能のため本番では実施する場合は気を付けてください。

3.新機能

まずは全体紹介を中心に。個別に調べたものもあるので別途記事をわけます。

3.1. Ultraleap Hand Tracking Support

Leap Motionを利用してハンドドラッキングを実現する仕組みです。用途としてはハンドトラッキングが利用できないデバイスにハンドドラッキング機能を追加するときに使えます。あと一応Unity Editorでも使えるのでHolographic Remotingよりもちょっと試したいとというときには使えると思います。
使い方としては以下のものをセットアップしてMixed Reality Toolkitのプロパティ設定のInputでLeapMotionDeviceManagerを追加します。

3.2. Migration window

今回から追加されたマイグレーション用の機能です。

image.png

V2.4.0では先ほど紹介した以下の3つのマイグレーション機能が付いています。

  • Microsoft.MixedReality.Toolkit.UI.ButtonConfigHelper
  • Microsoft.MixedReality.Toolkit.UI.ObjectManipulator
  • Microsoft.MixedReality.Toolkit.UI.BoundsControl

一番最後のものはBoundingBoxを置き換えるためのものですがまだ試験的機能なので利用する場合は注意しまししょう。

使い方は該当するコンポーネントを持つ要素を設定してApplyする形です。
せていできる範囲は以下の3つです。GameObjectとSceneは変更したい対象のコンポーネントが含まれるオブジェクトを追加して選択します。

  • GameObject
  • Scene
  • Full Projwct

MRTKの機能のマイグレーションが簡単にできるので便利なのですが、実は自分のオリジナルのマイグレーションも投入できるのですよ。
例えば、一括で設定を見直したいときにこの機能使って対応することも可能です。

IMigrationHandlerインタフェースを実装した必要なメソッドを追加すると対応可能です。
インタフェースはこういう以下の構造を持っています。

IMigrationHandler.cs
/// <summary>
/// Interface defining a migration handler, which is used to migrate assets as they
/// upgrade to new versions of MRTK.
/// </summary>
public interface IMigrationHandler
{
    /// <summary>
    /// Returns true if this migration handler can apply a migration to gameObject
    /// </summary>
    bool CanMigrate(GameObject gameObject);

    /// <summary>
    /// Applies migration to gameObject
    /// </summary>
    void Migrate(GameObject gameObject);
}

CanMigrateはセットされたGameObjectがマイグレーションの対象になるかどうかを設定します。
たとえば、BoundingBoxを置き換えるBoundsControlの場合はBoundingBoxコンポーネントを持っている時にtrueをかえす実装をするわけです。
Migratemメソッドには実際に置き換えるためのコードを書きます。BoundsControlの場合はBoundingBoxから必要な情報を吸出し、BoundsControlにパラメータをコピーしてGameObjectに追加し、元のBoundingBoxを削除します。

使いどころとしては、実際に自身のコンテンツ開発時に一括修正がいる場合に有効だと思います。プロジェクトで共通ライブラリなどを構成して一括展開で修正を行いたい場合にはかなり使えるのではないでしょうか。

3.3. MRTK Toolbox

MRTkはあらかじめUX部品としてボタンやツールチップなど部品化されています。すべてPrefabで用意されているのですが使いたいボタンを探す場合はProjectタブの中から探し出す必要がありました。これを支援するための機能としてMRTK Toolboxが追加されました。
現在は以下の種類に分類されて提供されています。各UI部品の解説記事へのリンクもセットで確認できるようになっているので開発作業がはかどると思います。

カテゴリ 外観|
Buttons image.png
Button Collections image.png
Near Menus image.png
Miscellaneous image.png
Tooltips image.png
Progress indicators image.png
Unity UI(Requires Canvas) image.png

3.4. Tap to Place

image.png

HoloToolkitと呼ばれていたころにはあった機能の1つです。タップするとフリーモードになって物体の表面に沿った形で移動する物体を作ることができる機能です。この機能はSolverシステムとして用意されているのでSolverHandlerとセットで利用する必要があります。

image.png

Solver HandlerのTracked Target Typeの設定沿った形で動作します。例えば、Headに指定すると物体をタップ後、Gaze動作で物体が移動します。また、Contoller Rayを指定することでHand RayやMotion controllerの動きに合わせた移動も可能です。
カスタムなどを使うとまた変わった操作感を提供できると思います。

3.5. Button Config Helperの追加とPressable Buttonsへの実装

MRTKにはPressableButtonという、押すことが可能なボタンが追加されています。これは主にHololens 2での利用のために追加されているものです(当然ほかのデバイスでの利用可能です)。このオブジェクトはよくできている反面設定が非常に複雑になってしまっていました。

image.png

具体的には、ボタンのラベル、アイコン、音声認識用のラベルを設定がButtonの各階層にぶら下がっているというものです。それぞれ変更したい場合はこれらを展開して設定を変更する必要があります。慣れてしまえばある程度対応できるのですが。。。
V2.4.0からはButton Config Helperが追加されました。この機能はPressableButton等にセットすることでこのコンポート内でまとめてパラメータ変更が可能になります。

image.png

パラメータ名 説明
Enabled Main Label メインラベルの表示/非表示
Main Label Text メインラベルに表示するテキスト
Enabled See it/ Say it Label 音声認識コマンド用のラベルの表示/非表示
See it/ Say it Label 音声認識コマンド用のラベルに表示するテキスト
On Click Interactableコンポーネントに設定するOnClickイベント
Icon Style アイコンの種別を設定。設定可能な値はデフォルトでは以下の通り。Noneはアイコン表示を行わない場合に利用します。
  • Quad
  • Sprite
  • Char
  • None
Icon Set Icon Styleで種別に応じたアイコンセットが表示。その中からアイコンを設定します

Icon Setについて

Buttonに設定できるアイコンはDefaultIconSetとして管理されています(Assets/MRTK/SDK/UX/Buttons)。これはかなり便利で自分で作ったコンテンツ用のアイコンなどを用意しておくとアイコンの設定なども簡単になるのでお勧めです。

アイコングループ名 説明|
Quad Icons 俗にいうマテリアルにも定義できるアイコン。デフォルトは以下のものが設定済み。image.png
Sprite Icons スプライトタイプのアイコン。デフォルトは以下のものが設定済み。image.png
Char 指定されたフォントからアイコンと設定できる。デフォルトは未設定。

Charはフォントアセットからアイコンを設定するものです。普通の文字フォントを使えば、アルファベットなどの設定も使えます。
ちなみに、Windows 10に入ってる「holomdl2.ttf」からフォントを取り込んで作るといくつかのMixed Realityっぽいアイコンも利用できます。
使えそうなもの抽出してみると以下のようなものがありました。

image.png

holomdl2.ttfからフォントアセットを生成したい場合は以下の文字コードだけ抜くといいかもしれないです。
フォントアセットはTextMesh Proがあれば吸出しは可能です。
抽出した文字に対応するコードは以下になります。

e700-e702,e706,e70d,e70e,e710-e714,e718,e71a,e71d,e71e,e720,e722,e728,e72a-e72e,e736,e738,e73f,e74a,
e74b,e74d,e74f,e750-e752,e760,e761,e765,e767-e769,e76b,e76c,e770,e772,e774,e777,e779-e77b,e782,e783,
e785,e786,e799,e7a9-e7ab,e7af,e7b0,e7b1,e7b4,e7c8,e7e8,e7e9,e7fc,e80f,e83f,e850-e859,e872-e874,e894,
e895,e8b2,e8b7,e8b9,e8d5,e8ec,e8fb,e909,e91b,e92c,e942,e95b,e992,e993,e994,e995,e9e9,e9ea,ea37,ea40,
ea4a,ea55,ea96,eb51,eb52,eb65,eb9d,eb9e,eb9f,eba0,eba1,eba2,eba3,eba4,eba5,eba6,eba7,eba8,eba9,ebaa,
ebab,ebac,ebad,ebae,ebaf,ebb0,ebb1,ebb2,ebb3,ebb4,ebb5,ebcb,ebcc,ebcf,ebd0,ebd1,ebd2,ebd3,ec03,ec19,
ec3f,ec7a,ec8e,ec8f,ec90,ec91,ec92,ec93,ec94,ec95,ec96,ec97,ec98,ecd8,ecd9,ecda,ece0,ece7,ece8,ece9,
ecea,eceb,ed17,ee93,efa9,f114,f115,f116,f117,f118,f119,f11a,f11b,f11c,f11d,f11e,f11f,f120,f132,f181,
f183,f184,f185,f186

3.6. Hand Menu周りのアップデート

Hand MenuはHoloLens 2用に用意されたメニュー表示の機能で掌を返すことでメニュを表示することができる仕組みです。
この機能の中心となるコンポーネントが「HandConstraintPalmUp」です。今回はこのコンポーネントに機能追加が入っています。

Gaze Activation

HandConstraintPalmUp.csの新しい要素として、「GazeActivation」プロパティが追加されました。このプロパティをチェックすると掌を返しただけではメニューが表示されなくなります。追加でGazeを手のひらに当てることで初めてメニューが表示されるようになるので、うっかり掌を返してもメニューが誤動作することを防ぐことができます。

メニューの動作サンプルの追加

MRTKにはHand Menuのいくつかのサンプルがあります。V2.4.0では新たに2つのHand Menuのアイデアが追加されています。

image.png

これは上記のような複雑なHand Menuで扱う場合のUXを考慮したものになっています。複雑なメニューをHand Menuで扱うと片方の手でメニュー表示をしつつ、もう片方の手でメニュー操作が必要になります。
この操作は試してみるとわかるのですが、かなり操作しにくいものになります。
メニュー操作する手の方に引きずられもう片方の手がぶれるので扱いが難しくなります。そのための解決策として2つのアイデアがサンプルに追加されました。

  • 掌返し→Gazeを当てるとメニューを表示、メニューをつまむとワールドロック
    Show & Hide with Hand World Lock on Grab and Pull
  • 掌返し→Gazeを当てるとメニューを表示、自動でワールドロック
    Auto World lock on Hand Drop

これらは掌返しでHand Menuを表示することと、メニュー操作を切り離すことで操作性を高める試みになっています。複雑なメニューを扱う際は一度導入を検討してみるといいと思います。

3.7. New HoloLens 2-style Toggle Buttons - Checkbox, Switch, Radio

新しいUXデザインとしてチェックボックス、スイッチ、ラジオボタンが追加されました。
以前これらのボタンはPressableButtonとはかなり違うデザインをしていたものです。

image.png

クリックするたびにチェックが変化するのはInteractableで制御されています。
Selection ModeがToggleになっていると選択/非選択でテーマ変更が可能になります。
このテーマに「チェック状態」と「非チェック状態」のUIをセットしておくと切り替わるという仕組みです。
image.png

ラジオボタンも基本的にはこの方法でUIを変更しています。
また、ラジオボタンの場合はグループの中で1つだけ選べるように機能させる必要があるのですが、これは「InteractableToggleCollection」コンポーネントを利用して構築します。
image.png

どのチェックボックスが選択されているかはこのコンポーネントを経由すれば取得できる作りになっています。

3.8. Dialog (Experimental)

image.png

何かとあると便利なダイアログです。今回は試験導入されています。使用方法としては以下の実装で呼出します。

Dialog.Open(DialogPrefabLarge, DialogButtonType.OK, "Confirmation Dialog, Large, Far", "This is an example of a large dialog with only one button, placed at far interaction range", false);

Dialog自体は抽象クラスで、ダイアログをカスタムする場合はこのクラスを継承して作成できます。実態のあるクラスはDialogShellでこれをオブジェクトに追加して必要な実装を行うと利用できます。

(この話も長くなるので別途書きます)

3.9. Dock (Experimental)

DockSample.gif

Dock機能です。これを実現するためにDockPositionコンポーネントが試験的に追加されています。動くところを見るとイメージしやすいと思いますが、このコンポーネントが追加されたオブジェクトの近くにManipulationで物体を近づけるとある範囲で吸着する動作をします。例えば、展示物を置くための台などにこれを設置するときれいに展示することができます。

(この話も長くなるので別途書きます)

3.10. Unity Profiler markers

入力システムとデータ・プロバイダにUnity Profilerマーカーが追加されました。これらは、入力系操作のどこに時間が費やされているかについての詳細な情報を見ることができ、アプリケーションの最適化で活用できます。

3.11. WindowsApiChecker

WindowsApiCheckerクラスについて機能が入っています。このクラスはUWPでサポートしているコンポーネントかチェックするための機能としては以下のメソッドが追加されています。

  • IsMethodAvailable
  • IsPropertyAvailable
  • IsTypeAvailable

UWPのライブラリを利用する前にサポートしているかを確認するなどに利用できます。

3.12. UnityUI, TextMeshPro用のMixedRealityKeyboardが動作する入力テキストフィールド

これも試験的に追加されてた機能です。UGUI向けのテキストフィールドへの入力を補助するためにMixedRealityKeyboardと連携できる仕組みです。フィールドをクリックするとキーボードが起動し入力補助が可能になります。

3.13. Grid Object Collection

Grid Object Collectionにいくつかの修正が入っています。

Grid Object Collection Alignment Options

グリッド内の要素を中央に配置するか、左/右軸に沿って配置するか(行と列のレイアウトを行う場合は上/下軸)を選択できるようになりました。

Grid Object Collection Anchor Changes

オブジェクトの中心軸に沿ってアンカーを配置することで、Unityのレイアウトグループの動作に合わせてグリッドオブジェクトコレクションの動作を変更しました。旧来のグリッドオブジェクトコレクションの動作は、AnchorAlongAxisフィールドで切り替えることができます。

3.14. Adjusted input simulation camera control

Unity Editor上で実行時、入力シミュレーションでのカメラ操作方法の調整。キーボードでカメラ操作する際に、右シフトで高速移動できるようになりました。以前は通常が高速移動で右CTRLで低速移動になっていたものが逆になりました。

Hands-free GGV input simulation

Unity Editor上でオブジェクト操作する場合、通常右シフトを押すと手が出てきて、そこからオブジェクトの操作を行います。V2.4.0ではGazeでオブジェクトと選択したあとに左マウスボタンでドラッグするとオブジェクトの操作が可能になりました。

3.15. Audio Spatializer Selection in MRTK configuration dialog

空間音響のに使うためのライブラリの選択をMRTK configuration dialogで設定可能になりました。Windows向けにチューニングされた音響ライブラリとして「Microsoft.SpatialAudio.Spatializer.Unity」があるのですが、これらを利用するためにはUnityのProjectセッティングを利用します。設定が深い場所にあるためその設定を容易にするためにダイアログで定義できるようになりました。
空間音響については以下のチュートリアルを参考にしてもらうといいかもしれないです。

3.16. Object manipulator graduated to SDK

ObjectManipulatorはSDKに移行し正式に。このコンポーネントは既存のManipulationHandlerクラスを置き換えるものです。
基本的な部分はManipulationHandlerと変わらないのですが操作時に制約(constraint)を与えることで動きに変化をつける
ことができます。

(この話も長くなるので別途書きます)

3.17. Bounds control improvements

とくに大きな変更ではないのですが、一部挙動が変わっている部分があります。
Bounds controlが設定変更時にビジュアルを再作成しなくなりました。また、実行時に任意のプロパティを再設定できるようになりました。また、プロパティ DrawTetherWhenManipulating と HandlesIgnoreCollider がハンドルタイプごとに設定可能になりました。

4.破壊的アップデートについて

今回は視線制御周りで一部変更が入っています。機能を利用している人は注意しましょう。

4.1. Eye Gaze API

IMixedRealityEyeGazeProviderのUseEyeTrackingプロパティがIsEyeTrackingEnabled変更されています。

以前
if (CoreServices.InputSystem.GazeProvider is GazeProvider gazeProvider)
{
    gazeProvider.UseEyeTracking = true;
}
v2.4.0
if (CoreServices.InputSystem.GazeProvider is GazeProvider gazeProvider)
{
    gazeProvider.IsEyeTrackingEnabled = true;
}

4.2. Eye gaze setup

Eye Gaze設定に必要なステップが変更になりました。IsEyeTrackingEnabledは、入力ポインタープロファイルのGaze設定にあるのですが、このボックスにチェックを入れると、デフォルトのHeadのGazeではなく、視線でののGazeが有効になります。

5.既知の問題

すでにわかっている問題は以下の通りです。

5.1. MRTK Configurator dialog does not show 'Enable MSBuild for Unity' in Unity 2019.3

2019.3でUnity用のMSBuildを有効にすると、パッケージを復元する無限ループが発生する問題が存在します。
この影響でダイアログに表示がされないことがあるとのこと。
Microsoft.Windows.DotNetWinRTパッケージをNuGet for Unity経由でインポートしておけば表示されます。

5.2. Duplicate Assembly Version and Multiple Precompiled Assemblies Unity 2018.4

Unity 2018.4でプラットフォームをスタンドアロンからUWPに切り替えてからスタンドアロンに戻すと、コンソールに以下のようなエラーが出ることがあります。

PrecompiledAssemblyException: Multiple precompiled assemblies with the same name Microsoft.Windows.MixedReality.DotNetWinRT.dll included for the current platform. Only one assembly with the same name is allowed per platform. Assembly paths
Assets\MRTK\Examples\Demos\HandTracking\Scenes\Utilities\InspectorFields\AssemblyInfo.cs(6,12): error CS0579: Duplicate 'AssemblyVersion' attribute

これらのエラーは、MSBuildForUnityでの削除処理に問題があるためです。この問題を解決するには、スタンドアロンの状態で、AssetsのルートにあるDependenciesフォルダを削除し、unityを再起動します。

5.3.Applications appearing as a 2D slate on Unity 2019.3

Unity 2019.3を使用している場合、XRサポートを有効にすると、デフォルトのSDK(レガシー)やプラグイン(XR Mangement)が設定されません。その結果、アプリケーションが 2D スレートに制約されます。これを解決するための詳細は、MRTKのBuil And Deployの記事に記載されています。

5.4.Unity 2019.3: ARM build architecture

Unity 2019.3では、Visual StudioでビルドアーキテクチャとしてARMを選択するとエラーが発生する既知の問題があります。推奨される回避策は、ARM64用にビルドすることです。それがオプションでない場合は、[Edit] > [Project Settings] > [Player] > [Other Settings] でGraphics Jobsを無効にしてください。

5.5. Runtime profile swapping

現状、Profileの動的変更には対応していません。Profileは静的な設定となっています。ただ、現状はそこまで困らないと思います。ProfileはマルチデバイスようにProviderを複数デバイスごとに割り当てて定義できるなどかなりの配慮がすでにありますし。
ただ、動的変更をやりたいと思ったときは現状できないことを理解しておきましょう。

5.6. Unity 2018: .NET Backend and AR Foundation

Unity 2018で.NET scripting Backendを使ってUWPをビルドしようとするとAR Foundationのインストールに失敗します。
これを回避するには以下の2つのいずれかの対応が必要。

IL2CPPでビルドする
[Build Settings]内の設定で[Unity C# Projects]のチェックを外す
要はVisual Studio上のUnityのコード(CSharp-Assemblyプロジェクト)をビルドしない状況を作ればいいということです。
まぁ、これはUWPではAR Foundationが不要とはいえ、仕組み上はライブラリをリンクするからモバイル用のライブラリをUWPでは
使えないでしょ?と言われたら、さほど違和感はないんですが。。。

まとめ

ということで、MRTK V2.4.0のリリースノートを読み解いてみました。
既存機能は安定が進んでいるのでより開発が楽になるように簡易化が進み、使いやすい機能がどんどん追加されている印象があります。クロスプラットフォームにむけて強化もすすんでいるので、これからのデファクトのライブラリとして使えるようになってくると思います。
今回後で書きますと書いてる機能は別記事で紹介したいと思います。これらの機能も非常に使いやすく有効なものが多いです。
ぜひ皆さんも色々体験してみください。

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

PlayFabでのプッシュ通知設定が難しすぎた

UnityのバックエンドをPlayFabに任せてみようと試みていたのですが、iOSのプッシュ通知設定が難しすぎたので備忘録です。

pemファイルのアップロードができない

PlayFabのプッシュ通知設定手順については、公式や紹介ブログがあるので詳細は割愛しますが、pemファイルをアップロードする段階で以下のようなエラーが発生してしまいます。

Invalid parameter: Reason: cannot be empty

スクリーンショット 2020-06-04 1.54.16.png

pemの発行には問題無さそうで、まるでエラーの検討がつきません。

解決策

ぐぐってみると以下のフォーラムを発見。
https://community.playfab.com/questions/36895/instruction-on-using-admin-api-to-set-up-ios-push.html

一言で言うと、「管理画面のUIはバグってて使い物にならないから、AdminAPIを使え」とのことでした。

そしてこのAdmin API、pemファイルの中身をいい感じに整形してリクエストパラメータに乗っける、という癖の強い仕様になっています。

リクエストパラメータの設定方法

以下フォーラム記事を翻訳したリクエストパラメータの設定手順です。

  1. テキストエディタを使ってPEMファイルを開きます。2つの文字列のセクションがあり、1つは証明書、もう1つは秘密鍵です。

  2. 証明書のテキストを別の空のテキストファイルにコピーします。また、"-----BEGIN CERTIFICATE-----"と"-----END CERTIFICATE-----"のマーカーも必ずコピーしてください。そして、テキストエディタのreplaceメソッドを使って、すべての改行を「\n」に正確に変換して、1行の文字列にしてください。これはどのPlayFab公式ドキュメントにも記載されていません(えっ)

  3. 秘密鍵部分も同様に繰り返します。鍵のテキストの改行をすべて変換します。

  4. PlayFab APIを呼び出すことができる環境(Postman、.NET Coreのコンソールアプリ、またはUnityのEditorスクリプト)で、SetupPushNotificationを呼び出します。

5 リクエストの "Key "プロパティに証明書の文字列を設定します。

6 Credentialプロパティに秘密鍵の文字列を設定します。

APIのインタフェースは公式を参照。
https://docs.microsoft.com/ja-jp/rest/api/playfab/admin/title-wide-data-management/setuppushnotification?view=playfab-rest

分からなさすぎる

この人はどうやってこの解決策にたどり着けたのか謎です。すごい。。。
おかげで無事にiOSのプッシュ通知設定ができました。

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

コーディング規約チェッカーを運用してみた使用感 (C#(Unity) JavaScript(CocosCreator), PHP(FuelPHP))

はじめに

コーディング規約を自動的にチェックしてくれるコーディング規約チェッカーは、
複数人で開発する際の可読性向上や各人の書き方の癖を平準化できる便利なものです。

コードレビュー等で生産性のない指摘をし合わないよう、
チェックはシステムにやってもらうというのはとても合理的。

一方で、規約に縛られた書き方を窮屈に感じたりすることもあると思います。
そこで、各開発環境における規約チェッカーを使ってみた所感を書き残します。

C# (Visual Studio)

規約チェッカーであるStyleCopは、
・プロジェクトにNuGetパッケージとしてインストール
・Visual Studioの拡張機能としてインストール

という2種類の方法があります。
前者が適用できるならそちらのほうがベターなようです。

・プロジェクトにNuGetパッケージとしてインストール

NuGetでインストールするとプロジェクト内に管理される形となり、
自動でチェックが走るため扱いやすいです。

また、NuGetではStyleCopの後継であるStyleCop.Analyzersが使用できるため、
その点でもオススメできる方法です。

規約のカスタマイズはソリューションにファイルを追加することで可能です。
https://anderson02.com/cs/cs-rules/cs-rules19/

・Visual Studioの拡張機能としてインストール

拡張機能としてインストールした場合はVisualStuioの右クリックメニューから、
「Run StyleCop」を選択することでファイルのチェックを走らせることができます。

規約のルール設定は右クリックメニューの「StyleCop Settings」からGUIで行うことができ、
編集結果はXMLファイル「Settings.StyleCop」として保存されるため、
このファイルをGitで共有するなどすれば、
チームでカスタマイズされたルールを共有できます。

Unityでの利用

Unityのプロジェクトで利用する場合、NuGetによる導入はやや煩雑です。
https://t-tutiya.hatenablog.com/entry/2019/11/07/200330

拡張機能のほうはテキストファイルを検査するだけなので、
Unityプロジェクトであっても、通常のC#プロジェクトと同様の使い方ができます。

Unityの場合は、とりあえず拡張機能のほうを使うのが現状は無難かと思います。

JavaScript (Visual Studio Code)

C#と違ってフレームワーク等により様々な書き方の流儀が存在するJavaScriptにおいては、
チェッカーもいくつかあり、それを適用するIDEも選択肢が多いため、
今回はVisual Studio Code + ESLintという組み合わせを選択しました。

npmでESLintパッケージをプロジェクトにインストールし、
Visual Studio Codeの拡張機能としてのESLintをインストールする、という流れです。
https://qiita.com/yohei_nakamura/items/4cf4876b3e36a46f3750

設定は「.eslintrc.json」というファイルに記述します。
npmのパッケージ設定とルールファイルをGitで共有することでチーム内でルールが共通化できる点については、StyleCopとほぼ同じです。

チェッカー本体とIDEの連携機能を別々にインストールする必要がある、という点がStyleCopとは異なります。
上手く動作しないときの原因切り分けが少々厄介です。

Cocos Creatorでの利用

Cocos Creatorで利用する場合であっても、C#のようにプログラム側にプロジェクトの概念がないため(単なるJavaScriptファイル群)、
Webサービス等でJavaScriptを使用する場合と同じ使い方ができます。

ただし、Cocos Creatorの形式(クラス定義型とか)とルールがマッチしない部分もあるので、
必要に応じてルールをカスタマイズする等の対応は必要になります。

PHP (Visual Studio Code)

PHPの場合もJavaScriptのように、複数のポリシーとIDEの組み合わせが想定されます。
今回はPHPの標準っぽさがあるPSR-2を使ってみました。

導入等は他記事を参照してください。
https://mseeeen.msen.jp/php-codesniffer-with-vscode/

PHPの場合、使用するフレームワークそのものが規約のような縛りがあったりするので、
ルールを調整して運用する必要がありそうです。

FuelPHPでの利用

FuelPHPでも、フレームワークでクラスの書き方(スネークケースで書くなど)等が決まっているので、パスカルケースを使うようなルールになっているとそれだけで正しくかけないといった問題が発生します。

FuelPHP準拠のルールを使用するか、PSR-2のようなルールをベースにフレームワークに合わせてカスタマイズしていくか、

いずれにしろ運用に工夫が必要になります。

おわりに 複数言語の比較

複数言語を比較してみると、言語やチェッカーの特性などが見えてきます。

C#は.NET Frameworkの統一感があるため、規約チェッカーを導入する場合もあれこれ悩む必要が
少なかったです。

Unityで公式に使えるようになると、もっといいですね。

JavaScriptとPHPは言語仕様が緩いことに加え、フレームワーク毎にまったく違う書き方があり、またエディタのデファクトも決定打がないため、様々な選択肢を試行錯誤する必要がありました。

カッコで改行するかどうか、など、細かいところも差異がでてくるため、しっかりと統一したルールを策定し、共有し、運用することが重要だと思います。

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

プログラミング言語毎のコーディング規約チェッカー使用感 (C#(Unity) JavaScript(CocosCreator), PHP(FuelPHP))

はじめに

コーディング規約を自動的にチェックしてくれるコーディング規約チェッカーは、
複数人で開発する際の可読性向上や各人の書き方の癖を平準化できる便利なものです。

コードレビュー等で生産性のない指摘をし合わないよう、
チェックはシステムにやってもらうというのはとても合理的。

一方で、規約に縛られた書き方を窮屈に感じたりすることもあると思います。
そこで、各開発環境における規約チェッカーを使ってみた所感を書き残します。

C# (Visual Studio)

規約チェッカーであるStyleCopは、
・プロジェクトにNuGetパッケージとしてインストール
・Visual Studioの拡張機能としてインストール

という2種類の方法があります。
前者が適用できるならそちらのほうがベターなようです。

・プロジェクトにNuGetパッケージとしてインストール

NuGetでインストールするとプロジェクト内に管理される形となり、
自動でチェックが走るため扱いやすいです。

また、NuGetではStyleCopの後継であるStyleCop.Analyzersが使用できるため、
その点でもオススメできる方法です。

規約のカスタマイズはソリューションにファイルを追加することで可能です。
https://anderson02.com/cs/cs-rules/cs-rules19/

・Visual Studioの拡張機能としてインストール

拡張機能としてインストールした場合はVisualStuioの右クリックメニューから、
「Run StyleCop」を選択することでファイルのチェックを走らせることができます。

規約のルール設定は右クリックメニューの「StyleCop Settings」からGUIで行うことができ、
編集結果はXMLファイル「Settings.StyleCop」として保存されるため、
このファイルをGitで共有するなどすれば、
チームでカスタマイズされたルールを共有できます。

Unityでの利用

Unityのプロジェクトで利用する場合、NuGetによる導入はやや煩雑です。
https://t-tutiya.hatenablog.com/entry/2019/11/07/200330

拡張機能のほうはテキストファイルを検査するだけなので、
Unityプロジェクトであっても、通常のC#プロジェクトと同様の使い方ができます。

Unityの場合は、とりあえず拡張機能のほうを使うのが現状は無難かと思います。

JavaScript (Visual Studio Code)

C#と違ってフレームワーク等により様々な書き方の流儀が存在するJavaScriptにおいては、
チェッカーもいくつかあり、それを適用するIDEも選択肢が多いため、
今回はVisual Studio Code + ESLintという組み合わせを選択しました。

npmでESLintパッケージをプロジェクトにインストールし、
Visual Studio Codeの拡張機能としてのESLintをインストールする、という流れです。
https://qiita.com/yohei_nakamura/items/4cf4876b3e36a46f3750

設定は「.eslintrc.json」というファイルに記述します。
npmのパッケージ設定とルールファイルをGitで共有することでチーム内でルールが共通化できる点については、StyleCopとほぼ同じです。

チェッカー本体とIDEの連携機能を別々にインストールする必要がある、という点がStyleCopとは異なります。
上手く動作しないときの原因切り分けが少々厄介です。

Cocos Creatorでの利用

Cocos Creatorで利用する場合であっても、C#のようにプログラム側にプロジェクトの概念がないため(単なるJavaScriptファイル群)、
Webサービス等でJavaScriptを使用する場合と同じ使い方ができます。

ただし、Cocos Creatorの形式(クラス定義型とか)とルールがマッチしない部分もあるので、
必要に応じてルールをカスタマイズする等の対応は必要になります。

PHP (Visual Studio Code)

PHPの場合もJavaScriptのように、複数のポリシーとIDEの組み合わせが想定されます。
今回はPHPの標準っぽさがあるPSR-2を使ってみました。

導入等は他記事を参照してください。
https://mseeeen.msen.jp/php-codesniffer-with-vscode/

PHPの場合、使用するフレームワークそのものが規約のような縛りがあったりするので、
ルールを調整して運用する必要がありそうです。

FuelPHPでの利用

FuelPHPでも、フレームワークでクラスの書き方(スネークケースで書くなど)等が決まっているので、パスカルケースを使うようなルールになっているとそれだけで正しくかけないといった問題が発生します。

FuelPHP準拠のルールを使用するか、PSR-2のようなルールをベースにフレームワークに合わせてカスタマイズしていくか、

いずれにしろ運用に工夫が必要になります。

おわりに 複数言語の比較

複数言語を比較してみると、言語やチェッカーの特性などが見えてきます。

C#は.NET Frameworkの統一感があるため、規約チェッカーを導入する場合もあれこれ悩む必要が
少なかったです。

Unityで公式に使えるようになると、もっといいですね。

JavaScriptとPHPは言語仕様が緩いことに加え、フレームワーク毎にまったく違う書き方があり、またエディタのデファクトも決定打がないため、様々な選択肢を試行錯誤する必要がありました。

カッコで改行するかどうか、など、細かいところも差異がでてくるため、しっかりと統一したルールを策定し、共有し、運用することが重要だと思います。

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