原カバンは鞄のお店ではありません。

Unityを使ったゲーム制作のあれこれを綴っていきます。

【雑記】unity1weekを反省する

シルバーウィーク

とりあえず「連休中どこに行った?」という質問には耳を塞いでいる皆さんこんにちは。三連勤が三連休で挟まれるという珍しいシルバーウィークでしたが、前半の三連休は西日本が、後半の三連休は東日本側が台風被害に見舞われるという、これもまた珍しい一週間でした。
幸いにも私の住んでいる場所ではそれほど被害が出なかったのですが、場所によっては停電、断水等が続いているようで、一刻も早い復旧を祈っています。

 

Unity1Week

シルバーウィークの最終日にunity1weekの結果が発表されました。
私の投稿した作品は残念ながらそれほど評価を得られず、部門別ではランクインしたものの、総合ではランキング外となってしまいました。

◆部門別

  • 楽しさ:3.31
  • 絵作り:4.262(39位)
  • サウンド:3.81
  • 操作性:3.071
  • 雰囲気:4.214(36位)
  • 斬新さ:3.452

「楽しさ」「操作性」の評価が芳しくなかったのが原因ですが、個人的には「雰囲気」「斬新さ」の項目が思うほど評価が伸びず、世間は甘くないなぁ、という感想です。

 

作った物

画面内に表示される[文字]をクリック&ドラッグして進める脱出ゲームです。

 

80年代後半あたりのPCアドベンチャーゲームを意識してデザインしてみましたが、寄せられたコメントを拝見すると特にその点に関しての指摘が無かったのでうまく伝わらなかったのかもしれません。

 

内容はチュートリアルを含めて3ステージ+ほぼイベントのみのステージとエンディングで、実際に遊んでみるとボリューム不足に感じると思います。ここら辺も評価が伸びなかった原因でしょうか。

 

まぁ、作業期間的にこれで手一杯だったので仕方ないといえば仕方ないのですが、各ステージ(特に公園のステージ)はもうちょっと凝った作りに出来たかなぁ、という反省もあります。

 

反省点

unity1weekでは毎度のように遅刻での提出となるのですが、今回はその中でも恐らく最長の遅刻になってしまいました。

元々unity1weekではお題に合わせてゲームを構想するのではなく、その時に作りたい物をお題に合わせる形でデザインしていくのですが、その中で今回の作品でどうしても作りたかった仕組み(システム)とお題とのすり合わせがマッチするまで時間が掛かったこと、作りたかった仕組みの実装に意外と時間が掛かったことが原因だと思っています。

 

作りたかった仕組み(システム)とは、下のようなTextベースのファイル(シナリオファイル)に沿ってゲーム内のオブジェトやUIを制御する、といった仕組みでこちらの方はまぁうまく実装できたと思います。

今後の資産としも生かせそうなので、次にunity1weekに参加する際には今回作ったシステムをベースにして作品を作ろうかと思っています。

 

最後に

投稿した作品のリンクとプレイ動画を下に載せます。
出来れば遊んでいただきたいのですが、それが億劫な方は動画でも見て頂けると幸いです。

unityroom.com

youtu.be

 

【雑記】Unity1Weekが終わらない

スプラトゥーン3

ゲーム開発者なのにスプラトゥーンのような有名どころのゲームを触ったことがない皆さんこんにちは。正直に告白するとスマブラもFFもポケモンも遊んだことがありません。なので好きなポケモンとか答えられないし、『エアリス生存ルート』とか話題に上がっても意味が分らないし、FF7のリメイク版CMとか一切共感できませんでした。勝手に「誰しも遊んだことがあるはず」的な扱いされても困ります。

 

Unity1Week

先週はUnity1Weekでした。決められたお題に沿ったゲームを一週間で作成して投稿する、というイベントです。

unityroom.com

私もゲーム開発者の端くれとして参加しようと意気込んだのですが。。。開発期間は日曜が締め切りでしたね。
今週から二週間が評価期間となり、早速投稿された作品がTwitter等で話題になっていますが、私の方はというと

ええ、、、現在も絶賛開発中です

 

こんな感じですよ。

まぁ、何を作ってるのかというと

Click&Dragのゲームで、今回のお題が「ためる」ということなので、どこかしらに何かしらを「ためる」ことで脱出するゲームとなっています。

 

Click&Dragのゲームは前々から構想はあって事前に調査もしていたつもりですが、先週は基本部分のシステム開発で手一杯でした。

なんとか評価期間内には完成させたいですね。

【小ネタ】影を落とすだけのオブジェトと影を受け取るだけのオブジェト

国葬

例の国葬の日が休日にならないと最近知ってガッカリしている皆さんこんにちは。どうやら休日にすると喪に服すことを強いる事になるから休日としないらしいのですが、意識低い系の一般国民としては何でもよいので休みが欲しいです。そうでないなら日程を前倒しして早々に終わらせて下さい。意識高い系地球市民の方々の騒音が鬱陶しくて仕方ありません。

 

Unity1week

例によって例のごとくunityroomで一週間ゲームジャムが始まりました。

unityroom.com

今回はお題が「ためる」となっています。
前回は制作途中で参加を断念したので今回は何とか作り切って参加したいのですが、ん~・・・動詞のお題は難しいですね。ゲームの方向性がどうしても狭い範囲に絞られる気がします。
私の場合はその時作りたいゲームをお題に寄せる形で構想を練るのですが、今回はどうしようか悩みどころです。

 

影だけ描画

Unityで3Dモデルの影の描画はデフォルトで行われるので通常はあまり意識しませんが、影に特殊な効果を乗せようとした場合はシェーダーを改造する必要があり骨が折れます。

幸いGoogle等で検索すると影用のシェーダーがいくつか公開されているので勉強がてら色々と参考にさせて頂いています。

今回はその中でメッシュに沿って影だけを描画するシェーダーが公開されていたのでそのご紹介。

github.com

レポジトリ中のShadowDrawer.shaderファイルのみを手元のプロジェクトアセット以下にD&DすればOKです。

中央のオブジェトに対してShadowDrawer.shaderを採用したMaterialを適用すると

自身が作る影の部分だけが描画されています。

 

影だけ落とす

このオブジェトに対して影を落とすような板を設置します。

このままだとカメラに映らないので、板に対してメッシュを描画せずに影だけを落とすように設定します。

こちらはMesh RendererのCast Shadowsの設定を「Shadows Only」にするのみです。

 

そうするとこんな感じになります。

これだと良くわからないので、影を作っている平板を細い板に変えてオブジェトの前に並べてみます。

そうすると

これを動かしてみると

 

で、このShadowDrawer.shaderでは影の色を変更できるので、背景に何かしろの色を付けて、影の色を白系に変えると

逆に影がかかる部分が光っているように見えます。

これを先ほどと同様に動かしてみると

ゲーム中の演出に使えそうですね。もしくは「これは何でしょう?」的なゲームにできるかも

【Unity】UIをDrag&Dropで操作する

新生

うっかり買ってしまった信長の野望にハマってしまい寝不足な皆さんこんにちは。今回の新作は寡兵で大軍を打ち破って一発逆転、という展開が難しいため敵の兵力をいかに目減りさせて局面を有利に運ぶか、が重要となっているのですが、これが面白くて時間を忘れて遊んでしまいます。あと、COMがやたら好戦的でモタモタしているとあっという間に大勢力を築いてしまうのも気が抜けなくて面白いです。

 

UIのクリック検知

UnityではボタンやテキストボックスなどのUI機能としてuGUIが搭載されています。
uGUIのButtonコンポーネントを使えばボタンに対するクリックを検知してイベントを発行してくれますが、Buttonコンポーネント以外のUI(テキストやイメージ等)に関してクリックを検知したい場合はIPointerClickHandlerを使う必要があります。
IPointerClickHandlerは先頭に「I」が付いているのでお察しの通りコンポーネントではなくインターフェースなので、IPointerClickHandlerを継承したクラスを作成して使用することになります。

public class ClickEventTest : MonoBehaviour, IPointerClickHandler {

	// クリックイベント
	public void OnPointerClick(PointerEventData pointerData){
		// クリック時の処理を実装
		
	}
}

上のようなスクリプトをクリックを検知したいUIオブジェトにアタッチすることで、そのUIに対するクリックイベントをキャッチします。

 

下の動画ではTextMeshProUGUIに対するクリックイベントを検知し、そのタイミングで別のオブジェトを下に動かしています。

 

Drag&Dropしたい

クリックを検知できるのならDrag&Dropのイベントも検知して操作したいところです。
まず、Dragのイベントを検知するにはIDragHandler, IBeginDragHandler, IEndDragHandlerを使用します。
これらはIPointerClickHandler同様、どれもインターフェイスとなっており、それぞれ「Drag中」「Drag開始時」「Drag終了時」の操作時にイベントをキャッチする仕組みとなっています。

 

public class DragObj : MonoBehaviour,IDragHandler,IBeginDragHandler,IEndDragHandler
{
    public void OnBeginDrag(PointerEventData eventData)
    {
    }
 
    public void OnDrag(PointerEventData eventData)
    {
        // Drag中は位置を更新する
        transform.position = eventData.position;
    }
 
    public void OnEndDrag(PointerEventData eventData)
    {
    }
}

イベント発行時に引数として渡されるPointerEventDataにマウスポインタの位置が渡されてくるので、その位置を参照することでDrag操作を行います。

 

Drop処理

Drop時の処理はOnEndDrag(Drag終了時イベント)で行います。

この時、他のUIと重ねっているか判定したい場合はそれぞれのUIにCollider2Dを設定してOnTriggerEnter2Dで判定します。
この時「IsTrigger」のチェックがONになっている事と、接触判定するUIオブジェトのどちらかにRigidbody2Dのコンポーネントがアタッチされている事を忘れないでください。

    bool isOverlap = false;
    
    void OnTriggerEnter2D(Collider2D other)
    {
        isOverlap = true;
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        if(isOverlap)
        {
            // 重なっている時のDrop動作
        }
    }

 

下の動画では「カギ」というTextを「カギ穴」というTextへDrag&Drop→OnEndDrag内でTextを「オープン」という表記に変更、ドアを開ける操作をしています。

 

ちなみにIDragHandler,IBeginDragHandler,IEndDragHandlerはこの3つで1セットとして動作します。

OnTriggerEnterを使うのにOnTriggerStayやOnTriggerExitを実装する必要はありませんが、DragHandlerはそれとは異なり、IBeginDragHandlerやIEndDragHandlerのみ実装しただけではドラッグ開始終了の検知ができないようです。

 

【Unity】壁に隠れた箇所をディザリング透過で表示する

診断結果

Twitterで「あなたの〇〇診断結果」的な結果をわざわざツイートする人の気持ちが分からない皆さんこんにちは。見も知らぬ人間の面白診断の結果なんて当人以外興味がないと思うんですが、世間から何かしらリアクションがもらえると思って呟いているんでしょうか?ちなみに私のアイドル化した時の担当カラーは"スカイ"だそうです。

 

壁の向こう

カメラ位置が定点的なゲームでは、プレイヤーの操作するキャラクターが壁などの周囲のオブジェクトに隠されて操作不能になってしまうことは避けたい事案です。

この為オブジェクトの配置には注意が必要ですが、どうしても避けられない場合はキャラクターが隠された箇所にそのシルエットを表示してプレイヤーが操作できるする対処が取られます。

このブログでもそうした時にシルエットを表示する方法について紹介しています。

www.karvan1230.com

 

ディザリング透過

一方でオブジェクトの半透明の表現手法としてディザ抜きと呼ばれる手法があります。

これはガラス窓などで使用されるMaterialのTransparency(透明度)を変更する透過法とは異なり、網目の細かい網戸越しに背景を見るような感じで、不透明で描画するピクセルを一定間隔とする(穴を空ける)ことで、半透明であるかのように見せかける手法です。

綺麗な半透明とはなりませんが、あくまで不透明描画なのでTransparencyを使った手法よりもパフォーマンスが稼げるというメリットがあります。

このディザ抜きシェーダに関する説明やシェーダーのソースは以下のリンクで紹介されています

light11.hatenadiary.com

knasa.hateblo.jp

 

隠れた箇所だけ透過させる

上のリンクでは壁全体、オブジェクト全体のディザリング透過が実装されていますが、できればキャラクターが隠れた箇所だけを半透明化させたい所です。

その為、今回はシルエットを表示した時と同じようにステンシルバッファを利用して不透明描画する箇所とディザ抜きをする箇所を分けることにしました。

 

シルエットを表示する手法では壁側のシェーダーがステンシルバッファにマスク値を設定し、キャラクター側のシェーダーがそれを参照してマスク値の箇所を黒く塗りつぶしていましたが、今回はその逆の手順となります。

最初にキャラクター側のシェーダーでステンシルバッファにマスク値「1」を設定します。

 

次に壁側の不透明描画する箇所ではステンシルバッファがマスク値(=1)となっていない箇所だけを描画します。

 

 

最後に壁側に対してステンシルバッファがマスク値(=1)となっている箇所だけをディザ抜きで描画するようにします。

 

 

同時に重ねるとこんな感じ

氷の壁の向こうのペンギンが透けて見えると思います。

 

動作例

実際にゲーム内で動作させた結果は以下の通り、GIF化したのでディザ抜きの箇所が不ぞろいに見えますが実際は上の図のように網目が均等に見えます。

 

今回の動作例では不透明描画するシェーダーとディザ抜きをするシェーダーをそれぞれ用意し、それをそれぞれ適用したオブジェクトを重ねて使っています。(つまり同じ個所にシェーダーの異なる障害物のオブジェトが二つある)

一つのシェーダーでPassを使えば同時に出来そうですが、ちょっとそれを作成する時間がありませんでした。

 

【Unity】アセット紹介:柔軟性の高い基本的な形状モデルを素早く作る「Quick Primitive」

夏休み終了

休日期間が余りに暇すぎてPart1を観てないのに「KingdomⅡ」を観に行った皆さんこんにちは。原作の漫画も途中で脱落した組なのですが、それなりにキャラクターを覚えていたので何とかストーリーは理解することができました。どうやらPartⅢからが本番みたいですね。あと佐藤浩市は日本映画のどこにでも現れるなぁ。

 

アセットで売っていない問題

最近ではBlender等を使って3Dモデルでも自作される方が増えてきましたが、私は造形のセンスや技術が皆無なので、もっぱら自作ゲームのイメージに会うアセットをunityのアセットストアやBOOTH等のストアから購入して使用しています。

なので、ストアに希望通りの3Dモデルが見つからないときは諦めるしか無かったのですが、先日、ゲーム制作の中でどうしても中途半端な中心角(210°ぐらい)の円弧のモデルが必要となり、そんな3Dモデルはどこからも販売されていなかったので、それらが自作できるアセットを購入しました。

assetstore.unity.com

 

Quick Primitive

このアセットでは以下の基本的な形状モデルをシーン内に作ることができます。

ボックス

円柱

球体

ドーナツ

角錐

角柱

階段

グリッド

平面

これらの形状モデルはエディタ上でスクリプトにより作られているので、インスペクタでスクリプトのパラメータの値を変更すればダイレクトに変更することができます

 

使い方

Hiearchy上で右クリック -> Quick Primitiveを選択し、作成する形状モデルを選択します。

シーン内に選択した形状モデルが作られ、Inspectorを確認すると形状モデル用のスクリプトがアタッチされていることが分かります。

 

変更できる内容は各形状モデルにより変わりますが、ボックスや円柱、角柱といった閉多様体ではオプションとしてエッジ部分を削ったり、中を凹ませたりすることができます。

凹ませる値を最大限まで上げると中を突き抜けてパイプのような形状となります。

円柱やドーナツ形状では中心角を変更することができる為、私が必要としていた中心角210°の円弧の形状モデルでも作ることができます。

 

作った形状モデルは[Save Mesh]ボタンを押すことでメッシュ情報として保存することができます。
ただしマテリアル情報は記録されないので保存したメッシュ情報を使う際にはマテリアルを再設定する事が必要です。

 

注意点

メッシュ情報が保存される先は「Asset/QcPrimitives/Meshs」配下で固定の為、「QcPrimitives」フォルダを別場所に移動させることはできません。(Save Mesh時にエラーとなり保存されない)

 

また、各形状モデルはそれぞれで保存されるので、各モデルの親子関係も当然ながら記録されません
Quick Primitiveを使って何かしらの大掛かりなオブジェクトを作っても、メッシュ情報から再利用する際には一から組み上げる必要があります。

 

作った物

以下は一部のパーツをQuick Primitiveを使って作ったものです。

 

 

 

 

デザインセンスの良し悪しは抜きにして取り合えず私のイメージしたオブジェクトは作ることができたと思います。

【Unity】ゲームのフレームレートを向上させるには

休暇の予定

夏休み目前にして未だに休暇中の予定が真っ白な皆さんこんにちは。社会人にも短いながら夏休みというものはあるんですが非リア充の人間には海にも山に旅行にも行く予定はなく、部屋にこもってゲームを作るだけの休暇になりそうです。まぁ、対外的には「コロナのための自粛」と言って誤魔化していますが。

 

フレームレート

今更言うまでもないのですが、ゲームの性能対策で一番の指標となるのはフレームレート(FPS)です。
TVや映画といった被写体が動く映像は連続した静止画を短い間隔で表示することで動画となる仕組みですが、ゲームも同様に画面の描画を短い間隔で行うことで背景やキャラクターが動く映像を作り出しています。
このため、その描画の更新間隔が短ければ短い(FPSの値が高いほど)ほどゲーム内のキャラクターは滑らかに動き、長くなる(FPSの値が低いほど)程ぎこちない動きに見えます。
なので、最近のゲームでは画面の美麗さと共に、このFPSもできるだけ大きな値を維持する事が求められています。

前置きが長くなりましたが、要は制作中の3D脱出ゲームがあまりにもカクカクした動作だったのでStatusからFPSを調べてみると



17.9FPS!!
で、早急な対応が必要!・・・というのが今回の記事の趣旨となります。

 

低レートの原因

フレームレートなどの性能対策を行う場合、本来ならProfilerを利用してボトルネックとなっているところを探っていくのですが、今回は明らかにDraw CallやSetPass Callの値が大きいことが原因となっています。

Draw CallやSetPass Callは画面の描画の為にレンダリング処理がどのくらい行われているのかを測るための指標となる値で、それぞれの値についての意味はLIGHT11さんのブログで詳しく紹介されています。

light11.hatenadiary.com

SetPass CallやDraw Callを減らすには

  • 影を描画しない
  • テクスチャアトラスを作り、複数のマテリアルのテクチャを纏める
  • メッシュを結合する

等の対応が有効です。

ただ今回に関しては影に関しては元々影が描画されないように全オブジェトに反映しているし、MeshBakerというアセット使ってメッシュの結合とテクスチャアトラスの作成を行って見ましたが、微減(SetPass Callが15000⇒11000)に留まり根本的な解決になりませんでした。

assetstore.unity.com

 

オクルージョンカリング

オクルージョンカリングとはカメラから見て壁等のオブジェトで遮蔽されていてカメラに写されないオブジェトを、最初から描画対象から外してしまおう、という機能で、描画対象から外れる=レンダリング処理が行われない=SetPass Call、Draw Callが減る、という効果があり、結果としてフレームレートが向上します。

ただし、オクルージョンカリングを行うにはカリングのための情報を事前に用意しておく(Bakeする)必要があります

 

今回の対象となるのは下の図のようなステージで、長い廊下部分を通った先に左右に部屋が用意されたホールがある、という間取り。

 

プレイヤー(カメラ)が長い廊下部分にある場合、当然ながらその先にある左右の部屋は見えないのでオクルージョンカリングの対象となることがわかると思います。

まず、他のオブジェクトを遮蔽するオブジェクト(廊下の壁等)に対してInspectorからOccluder StaticのチェックをONに設定します。
逆に遮蔽される側のオブジェクトに対してはInspectorからOccludee StaticのチェックをONに設定します。
または、遮蔽する側、遮蔽される側どちらともにStaticのチェックを設定しても同様の設定として判定されます。

 

後はWindow > Rendering > Occlusion Cullingから設定ウィンドウを開き、Bakeボタンを押すだけです。

これで遮蔽物の情報が保管されます。
もし、Bake後に遮蔽する側、遮蔽される側の位置を変更したり、新しオブジェクトを作った場合は再度Bakeを行う必要があるので注意がしてください。

 

Bake後にゲームを動かしてみると



23.3FPS
まぁ、先程よりは随分改善されました、が、できれば30FPSぐらいには持っていきたいtところです。

 

SetActiveで非表示化

そもそもプレイヤー(カメラ)が長い廊下部分にある場合は、その先にある左右の部屋はアクティブである必要はないので部屋を丸ごとSetActiveで非表示化する事にしました。

プレイヤーが廊下を通ってホールの入り口のドアを開けると左右の部屋はアクティブ化され表示されるようにスクリプトを組みます。

 

そうすると



39.5FPS!!
目標としていた30FPSを軽くオーバーする結果になりました。

 

つまり、フレームレートを向上させるには

  • 遮蔽される(見えない)オブジェクトは無闇にアクティブ化しない

という事でしょうかね。

◇プライバシーポリシー

●個人情報の利用目的

当ブログでは、メールでのお問い合わせ、メールマガジンへの登録などの際に、名前(ハンドルネーム)、メールアドレス等の個人情報をご登録いただく場合がございます。

これらの個人情報は質問に対する回答や必要な情報を電子メールなどをでご連絡する場合に利用させていただくものであり、個人情報をご提供いただく際の目的以外では利用いたしません。

●個人情報の第三者への開示

当サイトでは、個人情報は適切に管理し、以下に該当する場合を除いて第三者に開示することはありません。

・本人のご了解がある場合
・法令等への協力のため、開示が必要となる場合

個人情報の開示、訂正、追加、削除、利用停止
ご本人からの個人データの開示、訂正、追加、削除、利用停止のご希望の場合には、ご本人であることを確認させていただいた上、速やかに対応させていただきます。

アクセス解析ツールについて

当サイトでは、Googleによるアクセス解析ツール「Googleアナリティクス」を利用しています。

このGoogleアナリティクスはトラフィックデータの収集のためにCookieを使用しています。このトラフィックデータは匿名で収集されており、個人を特定するものではありません。
この機能はCookieを無効にすることで収集を拒否することが出来ますので、お使いのブラウザの設定をご確認ください。

●免責事項

当サイトからリンクやバナーなどによって他のサイトに移動された場合、移動先サイトで提供される情報、サービス等について一切の責任を負いません。

当サイトのコンテンツ・情報につきまして、可能な限り正確な情報を掲載するよう努めておりますが、誤情報が入り込んだり、情報が古くなっていることもございます。

当サイトに掲載された内容によって生じた損害等の一切の責任を負いかねますのでご了承ください。

●プライバシーポリシーの変更について

当サイトは、個人情報に関して適用される日本の法令を遵守するとともに、本ポリシーの内容を適宜見直しその改善に努めます。

修正された最新のプライバシーポリシーは常に本ページにて開示されます。