テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

【Unity】Display 1 No cameras rendering を消す方法

f:id:tsubaki_t1:20170201005856j:plain

小ネタです。

Display 1 No cameras rendering

画面のこの表示は、要するにCameraコンポーネントで何も描画してないよという意味です。つまりCameraを用意してやれば消えます。

f:id:tsubaki_t1:20170201010804j:plain

Cameraが不要なケース

基本的にUnityでは画面内のオブジェクトをCameraで映す事により、ゲーム画面に表示しています。
しかし、Cameraを用意するのが面倒だったり、不要といったケースも多々あります。

  •  例えばUIのみしか使用しないシーンの場合。
  • 例えばマルチシーンエディティングでCameraが別シーンに格納されている場合。
  • 例えばCameraが実行時に生成されるタイプの場合。

そういったケースでは、もしかしたら、この表示は余計なお世話かもしれません。

f:id:tsubaki_t1:20170201012519j:plain

Display 1 No cameras renderingを消す方法

f:id:tsubaki_t1:20170201012021g:plain

この項目を消したい場合、以下の操作で消せます。

  • Gameビューを右クリックしwarn if no camera renderingを選択

たぶん使えるのはUnity 5.5からです。
Display 1 No cameras renderingは確か Unity 5.4 からだったと思うので、UIが無いならダミーのカメラを置く必要があるかもしれません。

関連

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

【Unity】エディタ拡張でstaticなフィールドに置いたインスタンスが、コンパイル/再生時に初期化される問題の対策について

長ったらしいタイトルですが、その通り「エディタ拡張で、staticなフィールドに置いたインスタンスコンパイル/再生時に初期化される問題の対策について」です。

初期化されるパラメータ

Unityのエディタ拡張は、ホットリロードの要領でソースコードを書き換えると即座にコンパイル・修正したコードを反映させます。

正確には、「シリアライズ」→「コンパイル」→「シリアライズしたデータ戻し」としているみたいです。

f:id:tsubaki_t1:20170131225147j:plain

これよく見ると、シリアライズしたデータを一時退避し書き出したデータを再設定する事で、コンパイル前に設定したパラメータを保持しています。
逆を言えば、シリアライズ出来なかったパラメータが破棄されます。

例:シリアライズしないデータがある場合

 例えば下のようなコードを用意します。

gist.github.com

ウィンドウを表示後、Pushボタンを押すと#が増えるという簡単な物ですが、ソースコードコンパイルやゲームの再生を行うとパラメータが破棄されてしまいます。

f:id:tsubaki_t1:20170131230141g:plain

解決方法

この問題は、要するに「シリアライズ出来ないパラメータがある」事が問題となります。なので、シリアライズ出来る項目で固めておけば、良いのです。

シリアライズ出来る項目

シリアライズ出来る項目は、以下の通り。

  • static ではないこと
  • const ではないこと
  • readonly ではないこと
  • [Serializable]の属性を持つクラスまたは構造体
  • UnityEngine.Objectから派生したクラス
    (MonobehaviourやScriptableObject)
  • プリミティブな型(int, float, double, bool, string, 等々)
  • シリアライズ出来る型の配列もしくはList

この項目から外れている物は、シリアライズ出来ないのでホットリロード時に破棄されます。

上のサンプルコードでは、stringはシリアライズ出来ますがstaticに格納していたためシリアライズ出来ず、リロード時に値が破棄されていた訳です。

 

つまり、破棄しないように、もしくは破棄しても流し込むようにすれば、値を保持し続けてくれる訳です。

f:id:tsubaki_t1:20170131235250g:plain

解決法1:シリアライズ出来る場所に移動

手っ取り早い解決方法は、シリアライズ出来る場所にフィールドを持っていく事です。上のコードの場合、staticではなくフィールドに配置すればシリアライズ出来ます。

gist.github.com

解決法2:ScriptableSingletonを使用する

どうしてもstatic値が欲しい場合があります。例えば一つしかウィンドウを出したくないといった場合、staticに自分のインスタンスを登録して有無をチェックするコードが使用されますが、staticがデシリアライズ時に破棄されるため十分ではありません。

そんなときはScriptableSingletonを使用します。

ScriptableSingletonはシングルトンのような動作をしつつ、シリアライズ可能な値をシリアライズして保持してくれるので、staticのように全体で共有して扱う値も保持してくれます。

エディタの情報やアセット、GameObjectのインスタンスを保持する場合、これが何かと便利です。

gist.github.com

但し、シングルトンのような挙動をおこなうせいで、初期化コードを書いた方が良いケースが多々あります。
(これのランタイム版があれば色々と楽なのですが…)

解決法3:シリアライズするタイミングで、IOに書き出してしまう

微妙な方法ではありますが、シリアライズするタイミングのコールバックを取得して、IOに書き込んでしまうというアプローチです。

ISerializationCallbackReceiverを実装している場合、シリアライズ前とデシリアライズ後にコールバックが呼ばれるので、何らかの処理を挟む事が出来ます。

この方法なら、ディクショナリだろうが何だろうが、自分でシリアライズしてデシリアライズ出来るなら、値を保持出来ます。
なお、このコールバック中にUnityAPIは呼べません。つまりEditorPrefsは使えません。まぁ、UnityのAPIが必要な物は大体シリアライズ出来るので大した問題では。

gist.github.com

関連

monkey coders' - 実行中にスクリプトを編集したときのNullReferenceExceptionを回避する

docs.unity3d.com

tsubakit1.hateblo.jp

kanonji.info

 

【Unity】アニメーション中、指定の位置に到達するように位置を補正する

f:id:tsubaki_t1:20170130223038g:plain

ジャンプやダッシュジャンプを用いて障害物を登るというケースはよく有ります。この高さにアニメーションが一致すれば問題は無いのですが、任意の段差や距離をジャンプしたいといったケースは多々あります。

 

そういったケースの場合、幾つか解決の手法はありますが、今回はAnimator.MatchTargetを使用した解決法をメモします。

Animator.MatchTarget

Animator.MatchTargetは、アニメーションの指定タイミングでゲームオブジェクトの位置及び回転が到達するように調整するAPIです。

例えば下のように、ジャンプ開始モーションから補正を開始して着地時に指定位置に到達するような、微妙な位置を調整したり出来ます。

f:id:tsubaki_t1:20170130224713g:plain

到達して欲しい位置は、単純なRoot位置だけではなくBodyやLeftHand、RightHand、LeftFoot、RightFootといった調整が出来ます。

例えば上のGifアニメでは、左足が着地する位置に合わせて位置を調整しています。

実際に使ってみる

StateMachineBehaviourの用意

実際に使ってみます。

まず、普通にジャンプするアニメーションを用意します。そのままだとジャンプ力が足りず、変な所に着地してしまいます。

f:id:tsubaki_t1:20170131002757g:plain

このアニメーションに補正をかける訳ですが、実行時にステートマシンを調べるのも面倒なので、StateMachineBehaviourを使います。Mecanimでステートを選択中にAdd Behaviourで挙動を追加。

f:id:tsubaki_t1:20170130230223j:plain

追加するコードはこんな感じです。

gist.github.com

座標とウェイトの調整

コンポーネントは下のようになります。

まずTarget Body Partは「MatchPositionが到達して欲しいパーツ」です。先程も書いた通り「ルート、体、右手、右足、左手、左足」が指定出来ます。

逆にMatchPositionは、指定パーツが到達する位置(絶対値)で、Match Rotationが回転です。

この動きを、Weightsで制御します。Position Wieghtは、X/Y/Z方向にそれぞれ対応したウェイトです。例えばYを0に設定しておくと、MatchPositionでY軸にズレていてもY方向に動きません。

f:id:tsubaki_t1:20170130232653j:plain

 

今回は単なる移動なので、とりあえずMatch PositionとPosition Weightを調整します。
Target Body PartをLeft footに変更し、Match Positionを想定の位置に調整。

f:id:tsubaki_t1:20170130233027j:plain

アニメーションのタイミング調整

このStateMachineBehaviourのStartとEndが重要なポイントです。
MatchTargetは、Startから開始してEndのタイミングで対象の位置に到達します。そのため、キャラクターが動き始めたタイミングをStart、停止するタイミングをEndに指定します。

見るべきは、時間ではなくパーセントの方です。例えば下のアニメーションの場合、だいたい50.6%~76%くらいの位置で移動していますので、startは0.506、endは0.76と設定しておきます。この辺りは要微調整です

f:id:tsubaki_t1:20170130233452g:plain

f:id:tsubaki_t1:20170130234034j:plain

これで、タイミングや位置の調整が上手くいっているならば、着地のタイミングで対象位置に到達するような感じでアニメーションしてくれます。

f:id:tsubaki_t1:20170130234545g:plain

注意点

ApplyRootMotoinで動いている

MatchTargetですが、ApplyRootMotoinで動作しています。つまり、ApplyRootMotoinにチェックが入っていないと動作しません

が、逆を言えばApply Root Motoinにチェックが入っていればRootMotionの無いアニメーションでも動作します。

例えばユニティちゃんのアニメーションにはRootMotoinが入っていませんが、着地のタイミングに合わせて目標地点に到達するように調整出来ます。

f:id:tsubaki_t1:20170130235601g:plain

もしApplyRootMotoinを付けたくない場合は、下の記事が参考になりそうです。

gametukurikata.com

移動速度は距離を時間で割った速度で、等速

MatchTargetですが、基本的に移動速度は一定速度(距離を時間で割った速度)です。そのため、距離があまりにも想定アニメーションと比較して離れすぎている場合、非常に気持ちの悪い感じの動きになります。

また、基本的に目標地点へ一直線で動くので、カーブを描いて到達して欲しいようなケースでは有効ではないです。

なので、補正程度に使用するのが良さそうです。

MatchTarget補正中にステートの補完が走ると変な位置に到達する

MatchTargetで移動中、アニメーションのステートがブレンドを開始すると、妙な位置に到達する事があります。

f:id:tsubaki_t1:20170131000649j:plain

機能するMatchTargetは一つのみ

機能するMatchTargetは一つのみです。重複する場合、上に配置したStateMachieneBehaviourが優先されます。また、同様にサブステートがある場合は親に設定したStateMachieneBehaviourが優先されます。

なお、下のStartが上より早い場合、無視されるっぽいです。

f:id:tsubaki_t1:20170131002217j:plain

画面外に跳ねて、地面に着地する的な。

f:id:tsubaki_t1:20170131002326g:plain

関連

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

Galaxy S7と接続中のBluetoothヘッドホンがブチブチ切れる問題

先日BoseBluetooth ノイズキャンセリングヘッドホン QC 30を購入して楽しんでいたのですが、最近Bluetoothの音がブチブチ切れ音が遅延する問題に悩まされてました。

てっきりQC30の問題かと思いましたが、プロジェクターやiPadでは問題なく再生出来るのでGalasy s7 edgeの問題と仮定、ググったところ見事に同様の問題がヒット。

smartphone-watch.net

が、しかし

特定のBluetooth機器とだけでなく、複数のBluetooth機器で同じ症状が出るということで、こちらは対処法も見つかっていません。

おおぅ…マジか

解決

他のサイトでBluetoothのON/OFFや端末の再起動を試すも効果がなし。一瞬、専用のiPod Touchでも買おうかとよぎりましたが、もう少し調べてみることに。

すると、どうやらBluetoothのサービスを強制終了すれば治る可能性があるとの記述が…

How To Fix Galaxy S7 Bluetooth Problems | RecomHub

 

実際に試した所、コレが当たりでした。

やり方

  1. 設定を開く
  2. アプリーケーション管理を開く
  3. 右上のその他よりシステムアプリを表示を選択
  4. 一覧よりBluetooth共有を選択
  5. 強制終了を選択して、ついでにキャッシュを削除
  6. これでBluetoothが切断されるので、
    BluetoothをON/OFFしてBluetoothを再起動

再接続時以降はヘッドホンがブチブチ切れる事は無くなりました。

 

上手く行くかはわかりませんが、もし同様の問題があるなら試してみるのも良いかもしれません。