2013/09/02

【Unity】DetonatorをiOSで動かしたとき発生するエラーについての検証

後藤です。先週分のブログです。

インターンシップ中、UnityのDetonator Explosion Frameworkという、爆発を簡単に表現できるアセットを利用していましたが、このアセットを利用するに際して 何故かMacOSX上ではちゃんと爆発するのにiOS上へ移すと爆発しない という謎の症状を2度経験したので、今回はそれについて検証してみたいと思います。

※ そもそもDetonatorはiOSでの動作をサポートしていないということではありますが、今回はやむを得ないのでそれを踏まえた上で原因追求しています。


■ エラーが出た環境と仕様


環境は、MacOSX10.8.4。Unityは4.2、Xcodeは4.6.3。Unityのライセンスは、現在はUnityさんにインターンシップ用で頂いたイベント用ライセンスを使わせて頂いています。実機のほうはiPhone4SとiPodTouch第5世代で試しておりどちらもiOS6(同じ症状が出るので実機の違いは症状には関係ないと思われる)。

実例1)シーン上に配置されているCylinderのオブジェクトにボールが衝突(OnCollisionEnter)したときにInsitantiateでDetonatorに用意されているプレハブが生成され爆発が発生する。はずだが、Mac OSX上では爆発が確認できるのにiOSで動かそうとすると爆発しない。
実例2)上とほとんど同じ。元々はCubeをTriggerにしてOnTriggerEnterしたときにInstantiateするような書き方だった、がiOSでは爆発せず。ただDetonator-Baseのプレハブをシーン上へ置いただけというふうに変更してみたり、他のアセットやオブジェクトを全部なくしてみたりと色々と試したが治らなかった。

実例1の時には結局Detonator自体を削除してもう一度インポートすれば解決したが、実例2の際にその方法を試したときは解決しなかった。


■ とりあえず表面上の原因




XcodeのDebug Areaを見ていると、Explosion2スクリプトのOnCollisionEnter → Instantiateでインスタンスを作ったときの FillDefaultMaterials → DefaultFireballAMaterial → MaterialのShaderうんぬんのところでNullReferenceExceptionが出ていることが分かる。
おそらくマテリアルとかが存在しないというようなエラーだと思われる。Shaderがどうのとあるので、new Material()ができていないのか、Shader.Findが失敗しているのか?
今回はDetonatorのプレハブを設定等をいじらず使っていたので(ただ今回はインターンに参加された学生さんたちの作るゲームで発生したものなので、いじっていないのかどうかは定かではない)、FireballAMaterialをはじめとしたマテリアルのところには何も設定をしておらず、そのためこのDefaultFireballAMaterial()、FireballBMaterial()、SmokeAMaterial()…(以下略)はSystemのデフォルトのマテリアルが使われることになっていた。ここがダメらしい。


■ とりあえずの解決策


Default〜がダメだったら、プレハブにマテリアルを直接指定してDefault〜の中でマテリアルを作らせなければいいのではないかと思ったら、それで良かったらしく、一応iOSでも爆発するようになった。
マテリアルは初め一々自分で作ってDetonatorの中にあるTexturesを指定しShaderの設定とかも行っていたのだが、そんなことをしなくてもSample Supporting Emitters→Materialsフォルダの中にマテリアルが用意されていた。ので、それをプレハブのInspectorのところで設定した(図2)。HeatwaveはProのみの機能だそうなので設定していない。



しかしなぜPCでは動くのに実機ではそれが反映されないのか…。


■ 原因の追及


他人が作ったものではどうしてこのバグが発生するようになったのかがはっきりと分からないので、自分でその状況を作るべく色々試してみることにする。

(手順)

【1】プロジェクトを作成し、シーンをAssetsフォルダ直下へ保存しておく。
【2】DetonatorをAssetStoreからインポート。場所はAssetsフォルダ直下。Test Sceneは最初からインポートに含まずチェックを外しておく。NormalMap SettingはIgnoreにしている。
【3】プレハブDetonator-Baseをそのままシーンにオブジェクトとして追加し、MainCameraに映るところへ配置


【4】Mac上のUnityでちゃんと爆発しているか確認
【5】Build SettingsでプラットフォームをiOSに変更、Add Currentで現在のシーンを追加してiOS向けにビルド

さっそく例のエラーが出た。

【6】オブジェクトに適用させたスクリプトでInstantiateさせるようにしてみる
インターンのカリキュラムではCubeオブジェクトにスクリプトを当ててそのスクリプト中でInstantiateし爆発させる方法をとっていたので、一応そちらでも試す。
書いたスクリプトは以下のとおり(Explosion.cs)。

using UnityEngine;
using System.Collections;

public class Explosion : MonoBehaviour {

     public GameObject bombType;
     private float INTERVAL = 5.0f;
     private float timer;
    
     void Start () {
          timer = 0.0f;
     }

     void Update () {
          timer -= Time.deltaTime;
          if(timer < 0.0f){
               Instantiate(bombType, this.transform.position, this.transform.rotation);
               timer = INTERVAL;
          }
     }
}
そのままHierarchyへ放り込んであったDetonator-Baseのプレハブを削除。CubeにExplosion.csを適用させ、InspectorでBomb TypeにはDetonator-Baseを設定しておく。
Explosion.csを適用させたオブジェクトが(というかその位置で)爆発するといった感じの書き方になっている。Startの時だけInstantiateしても良かったが、最初の1回だけだとiOSへビルドしたときに爆発したかどうかよく見忘れてしまうので5秒おきに爆発するようにしてある。
が、しかしやっぱりエラーが出るままだった。

【7】他のDetonatorのプレハブを試す
BombTypeを他のものに変えて試してみた。ら、これがちゃんとiOSでも爆発するものとしないものがあることに気づいた。
ちなみにうまくいかないものは以下のプレハブ。どれもMacOSX上では動作することを確認している。
  • Base
  • Crazysparks
  • MultiExample
  • MushroomCloud
  • Sounds(これに至ってはXcodeでアセンブリのが出て起動前に止まってしまった…)
  • Spray
  • Tiny
  • Wide
※ Heatwaveは試していない。

【8】各プレハブに関連付けられているスクリプトを比べる

このスクリプトの何かがいけないのではないかと見てみたが、特にそういうわけではなさそうだった。強いていえば大丈夫だったほうはSimple以外Sprayがついており、ダメだった方はSpray以外Sprayがついていないというのはあったけれど…。
というよりBaseとSimpleは同じDetonator.csの基本のファイルしかついてないみたいなので、この設定内容の違いなのではないだろうか、と。

【9】BaseとSimpleのDetonatorの設定内容を比べる
 

Simpleの方にはDirectionの中で全てSparksが設定されている(左)。Baseの方は全てNone(右)。
他のものも見てみたが、Detonatorスクリプトの中でマテリアルが指定してあるものは他にない。

【10】Simpleのコピーを作ってみて設定をBaseに近づけて動かなくなるか試す
ちゃんと動いていたDetonator-Simpleプレハブを複製してDetonator-Simple_copyとし、それをCubeのExplosionスクリプトのBombTypeに適用させることで実験してみる。
とりあえず一番大きな違いである、Derectionのところに設定してあるSparksマテリアルを全て外してみる。
ダメだった。やっぱり原因はこれのよう。

OKだったプレハブの共通点は、
  • Chunks:SprayスクリプトのSpray ObjectにChunkがついてる
  • Ignitor:ForceスクリプトのFire ObjectにBurninatingがついてる
  • Insanity:SprayスクリプトのSpray ObjectにChunk/ExplosionArmsがついてる
  • Simple:Detonatorスクリプトにマテリアルがついてる
  • Upwards:SprayスクリプトのSpray ObjectにChunk/ExplosionArmsがついてる
と、マテリアルが設定されているか、〜〜Objectという名前のところにプレハブが設定されているよう。逆にNGだったプレハブの共通点はオブジェクト・マテリアルを設定する箇所が全てNoneになっているという点だった。
(SprayプレハブはExplosionArmsがついていたが、おそらくこれはマテリアルとかが設定してあるオブジェクトではないということだと思われる。)(上記OKだったものはExplosionArmsがついてたSprayスクリプトの他にChunkオブジェクトがついているSprayスクリプトも持っていたので、これのおかげで動いていたのだろう。)

ForceスクリプトにはFire Objectを設定する箇所があり、このスクリプトがつけられているMashroomCloudとTinyのプレハブに、Ignitorについていたのと同じBurninatingオブジェクトを設定してみたら、この2つに関してはiOSでも爆発するようになった。(何かちょっと違う感じだけど…)

Burninatingプレハブを見てみると、これにはFireballA・Bとその下のSmokeプレハブにもSmokeA・Bが設定してあり、同じようにChunkの方もSmokeTrailに色々設定されていたので、そういうことなんだろう。


ということで、どこが原因だったのかは分かってきたので、次に同じエラーが出たら対処はできるはず。けれど、そもそもなぜMacだと良くてiOSだとダメなのか(他のプラットフォームではどうなのか)とか、そもそも前に他のプロジェクトでやったときはBaseとかのNGだったプレハブも普通にiOSで動いていたような気がするけど何の条件でできなくなるのか とか、そのあたりが未だ不明なので追及していく必要がある。

また、今までDetonatorの仕組みがよく分かっていなかったので(インターンシップの)資料の通りにPrefab Examplesを利用していたが、そもそもプレハブではなくてオブジェクトにCompornent→Detonatorで自分で設定を作りプレハブを作った方が安心安全なのかもしれない(しかもそうすれば最初からマテリアルがついてるし…)。
ちなみにCreateEmptyで作った空のオブジェクトにCompornent→Detonatorで基本のDetonatorスクリプトとDetonatorForceスクリプトをつけて何も設定は変更しないでビルドしてみたら、(ForceのFireObjectがNoneのままでも)ちゃんとiOSでも爆発した。ので、今のところ爆発の色だとか煙のマテリアルを変更したいとかそういう予定はないし、このエラーが発生したときはとりあえずDetonatorスクリプトにデフォルトのマテリアルをつけておくのが一番楽な対処法かな、という結論に至った。


それでもって、Xcodeを見ていてDetonatorをiOSで動かすとフレームレートが下がりまくりでとてもよろしくなさそうなことにも気づいたので、そもそもやっぱりiOSのゲームでDetonatorは利用しないべきなんだろう、ということがよくわかりました。


13/09/06補足:今きているインターンシップの子たちに試してもらったところ、(今までの子たちはDetonator(Base)を入れた後すぐにiOSで動くか確認するという作業をしていなかったため気付かなかったが)全員実機では爆発しなかった。ので、UnityからXcodeだか、C#からObjective-Cだかに変換するときに何か起こっているのですね。。Detonatorが持っているバグ(サポートしてないのでそう言っては語弊があるかもですが)なのか、言語の違いによるものなのか…は今の私には分からないので機会があったら調べたいと思います。

3 件のコメント :

  1. Thanks for sharing, nice post!

    Tại Bruno.vn chúng tôi còn hướng dẫn bạn chọn quần áo cho nam giới hay hướng dẫn cách chọn quần Jeans nam hay chọn sơ mi với cách chọn áo sơ mi cho nam hay hướng dẫn cách phối đồ với áo sơ mi nam cực hiệu quả hay cách phối màu quần áo nam cho nam giới. Tại Bruno, bạn có thể thấy các kiểu áo sơ mi đẹp nhất hiện nay hay cách chọn cách chọn size áo theo chiều cao cân nặng hay chọn size áo khoác nam hay hướng dẫn cách chọn size áo sơ mi nam hiệu quả hay bảng size áo sơ mi nam cho bạn lựa chọn hay cách chọn size quần jean nam phù hợp hay hướng dẫn các bạn cách tính size quần nam hay bài viết quần size S là bao nhiêu cho bạn lựa chọn. Bạn có thể tới trực tiếp hoặc dịch vụ mua quan ao tren mang giao hang tan noi hay thắc mắc mua quần jean nam ở đâu đẹp TPHCM thời trang hàng hiệu hay mua quần jean nam rẻ ở đâu thì đến Bruno nhé. Bạn có thể giải đáp ở sài gòn nên mua quần áo ở đâu uy tín, hàng hiệu hay và Bruno là địa chỉ shop thời trang nam online TPHCM uy tín, hàng hiệu hay shop quần áo nam đẹp ở tphcm thì lựa chọn hàng đầu là Bruno.

    返信削除
  2. ありがとうございました..
    Pidato

    返信削除