ブルーノのC#プログラミング & unity勉強日記

プログラミング素人、ブルーノの自主勉強ノートです。他のプログラミングを勉強したい方の助けになれば幸いです。その他趣味の雑記もしていきたいです

No.002 進捗状況10[オブジェクトプーリング][ビルボード]

f:id:covory10101101276:20190415125226j:plain
グヌン・ムル国立公園 -マレーシア-

みなさんこんにちは🌚

ステファノス・チチパスってなんか口に出したくなっちゃうよね。ブルーノです。

では今回もオブジェクトを製作していきます。
今回作ろうと考えたのはズバリ「雷」。雷を避けるなんてかっこいいですよね。というわけでこれを作成していこうと思います。
雷ってぐにゃぐにゃしてるから3Dモデルを用意したらその表現がとても難しいしめんどくさそうですよね。というわけで今回はまずこの雷の表現に「ビルボード」という技法を使いたいと思います。

ビルボード
ちょっと昔のゲームをやっていると時々かなりグラフィックが写実的なのにどこからみてもその面しか見えないオブジェクトとかありますよね?

f:id:covory10101101276:20190415130319j:plain
コース脇の木々はみんなカメラを向いている
これはビルボードという技術で2Dの見た目のものを常にカメラの方を向かせることで立体感を出す技法で、3Dモデルの節約ができます。
nn-hokuson.hatenablog.com
こちらの方がとても詳しく解説しています。というかこれ見て作りました🌝
まずは背景を透過させた雷の画像をインポート
f:id:covory10101101276:20190415131156p:plain

背景の透過仕方は
mtimsno.hatenablog.jp
こちらに詳しく載っています。

そして新しく作ったQuadオブジェクトに適用。名前はLightningにしときました。

f:id:covory10101101276:20190415131259p:plain
見た目はこんな感じ。雷っぽいがペラペラ
見た目はペラペラですがコライダーは普通にCapsule Colliderを使っているので当たり判定はあります。
そしてビルボードスクリプトを作り、Lightningにアタッチ。
f:id:covory10101101276:20190415131617p:plain
なぜか裏面がどうしてもこっちに向いてしまったのでLookAt()のあとに180度回転

f:id:covory10101101276:20190415131954p:plain
シーンビュー(上)と実際のゲームビュー(下)
常にカメラの方を向くようになりました。良かった良かった。

しかしこの雷、実際に光を発しているわけではないので日陰だととても暗くなってしまうんですよね。

f:id:covory10101101276:20190415132320p:plain
暗い。まるでスルメ

オブジェクトへの光の当たり具合や見た目の影響を管理するのはマテリアルのエミッション(Emission)が関係しているようなのですがこちらのサイトを参考にしてみたもののUnityのバージョンが違うためかメニューが変わっていて記事通りにいかなかったです。
[Unity]色を失わないオブジェクト | KENスクールブログ

f:id:covory10101101276:20190415132651p:plain
実際のマテリアルのEmissionの欄。サイトとは違う項目になっている
しかたないのでオブジェクトの目に前に光源を置くという強硬手段に。
f:id:covory10101101276:20190415132849p:plain
なんか結構いい感じなので結果オーライ
そして下に降る動きと地面の下に入ったら消えるようスクリプトで制御します。ちゃんとタイマーで遅くできるようpublicなスピードの値も導入。ただ落ちるだけだと物足りない気もしたので34行目で地面に落ちた時に光っぽいパーティクルも発生させました。
f:id:covory10101101276:20190415133119p:plain
しかし、これが後述するオブジェクトプーリングというあらたな壁に大きく関わってくることになるのです。

オブジェクトプーリング
さあさっき作ったLightningを生成するスクリプトを作ってたくさん雷を降らせるぞーと思い、こちらのジェネレータースクリプトを作ったところ....

f:id:covory10101101276:20190415133932p:plain
タイマーリセットと座標リセットをそれぞれ別メソッドで作ってUpdate()メソッドを見やすくしたぞ。我ながら玄人っぽいじゃないか😏

f:id:covory10101101276:20190415134225p:plain
お、重い。。。。
全くゲームプレイができないわけではないですが結構な頻度で画面が角つきました。パソコンでこれならスマホはどうなってしまうんだ....
どうやら先ほどスクリプト内で頻出していたInstantiate()メソッドが原因で、新たにオブジェクトを生成する作業は負荷が大きいそうです。でもこの量でもこれだけカクつくのにシューティングゲームとかはどうやってあれだけの弾を動かしているのでしょうか。
そこでオブジェクトプーリングという技法の出番というわけです。
【Unity】オブジェクトプーリングでオブジェクト節約術 | Unity | DoRuby
こちらのサイトを参考にしました。どうやらオブジェクトをゲーム開始時にたくさん作っておき、そのアクティブ/非アクティブを切り替え使い回す方法のようです。なるほど。
では実際にスクリプトを書いていきます。var型とかforeachとか自分では全然使わないから理解が大変だ😵😵😵
f:id:covory10101101276:20190415135250p:plain
オブジェクトプールのスクリプトはリストの生成と取り出し周りだけなので全く同じ記述で良いですね。
f:id:covory10101101276:20190416164208p:plain

f:id:covory10101101276:20190416164226p:plain
雷生成スクリプト
こちらの雷生成スクリプトは大幅な変更が余儀なくされましたが、おかげでオブジェクトプールの仕組みと使い方がよくわかりました。使用する際はGetObject()メソッドのみなので楽ですね!
f:id:covory10101101276:20190416164435p:plain
f:id:covory10101101276:20190416164447p:plain
雷自身のスクリプト
一応雷のスクリプトもオブジェクトプールの仕様により用済みになったら非アクティブにするように変更。このスクリプトの22行目で世界時間をかけているので加速に伴って雷のスピードが1/10になるのは当然なのですが雷の生成も遅くなるように前の雷生成スクリプトの51行目でも工夫してあります。
結果は....
f:id:covory10101101276:20190416164848p:plain
成功!!
雷の中を加速して避けるのはなかなか面白いですよ。さあゲーム内容が面白くなってきた!!今回はここまでにしておきます。