へっぽこ日記

Unity関係のつぶやきまとめ。マイコンとかもいじります。

2022年やったことの振り返り

はじめに

こんにちわ、まかろにです。今年やった事の振り返りを雑にしていきます。振り返ってみて、今後のやりたいことをまとめたいと思います。

 

初めてのチームでのゲーム制作

GlobalgameJamで、初めてチームを組んでゲーム開発を行いました。UI関係の意匠を担当していました。個人で作るのも良いけど、複数人で作る方が楽しいとこの時気づき始めます。

www.youtube.com

 

技術ブログ開設

技術ブログを始めてから半年たちました。開設した当初はUIに関して発信していましたが、現在はUnity全般の技術的な事を発信しています。

あと少しで500レビュー突破しそう!

 

インターン参加

嬉しいことにいくつかのインターンシップに参加することができました。中には会社に行って体験できたものもあり、貴重な機会になりました。

 

東京ゲームショー参加

学内メンバーで制作したゲームを東京ゲームショーに展示しました。東京ゲームショー辞退初参加だったので、展示側と一般来場者側として手に入れたものがありました。

メディアに掲載されたりして、かなり嬉しかったです。

 

内定ゲット

運が良いことにゲーム会社から内定を頂きました。予定よりも早い時期に内定を頂けたので、安心しました。

 

 

おわりに

来年は現在制作中のゲームを東京ゲームダンジョンなどで展示したい思ってたりします。あとは、シェーダーについて勉強したいですね。

 

是非、読者登録をしていただくと助かります!

UIの最適化について色々試してみる

はじめに

この記事は Unity Advent Calender2022 の15日目の記事です

qiita.com

今回はUIの最適化について色々試してみる記事です。

今まで処理負荷を意識しないで実装していたので、そろそろ意識して実装したほうが良いと思い、色んな方法を試してみました。

以前作ったゲームのタイトルを最適化していきます

 

 

バッチング

一度の描画で複数のオブジェクトを一括で描画する仕組みをバッチングと云うみたいです。できれば一括で描画できた方が処理負荷が低いため、是非この仕組みを活かしたいです。その時に便利なのがSpriteAtlasです。

SpriteAtlas

SpriteAtlasは複数のテクスチャをまとめて、ひとつのテクスチャにするアセットなのですが、バッチングは同じテクスチャを参照しないと出来ないため、SpriteAtlasの機能を利用して実現します。

異なるテクスチャから参照されているのでバッチングできていない

以下のような感じで、複数のテクスチャをアトラス化します。単純にテクスチャをまとめただけですが、これだけで基本的な処理は終わりです。

テクスチャ同士が重なってしまうこともあるので、注意が必要だったりする

SpriteAtlasで一つのテクスチャにまとめることでバッチングができた!

一応FrameDebuggerで確認


バッチングを行う条件は他にもあるようで、「同じCanvas内にある」、「同じマテリアルを使用している」、「同じテクスチャを使用している」、「Z座標が同じ位置にある」、「同じマスクでクリップされている」といった条件があります。詳しくは、山村さんのUnityでパフォーマンスの良いUIを作る為のTipsを参照することをお勧めします。

 

Canvasを分ける

一つの要素でも変更があると、Canvas全体の描画をやり直すようです(リビルド)。そのため、基本的に動的なUIと静的なUIは、分けて別々のCanvasとして管理しておくべきようです。

今回は、フェードイン・フェードアウトのアニメーションを繰り返す画像を別のCanvasで管理するようにしました。

独立した形でCanvasを分けましたが、分けるCanvasが親子関係であっても問題は無いようです。親Canvasは、子Canvasの変更まで確認しないためです。

 

GraphicRaycasterを削除、RaycastTargetをオフにする

通常時はONになっているので、タッチやクリックを検知してくれますが、そういった動作を検知する必要が無い場合は基本不要です。

今回はボタンなどのクリックが必要なイベントがないため、OFFにしておきました。

 

おわりに

最適化前と後を比較したんですが、特に負荷自体は変化していませんでした(使用しているテクスチャとかCanvasの数が少なすぎるためですね)。他にも様々な方法があると思います。是非調べて試してみてください。

是非、読者登録をしていただくと助かります!

 

参考リンク

Unityでパフォーマンスの良いUIを作る為のTips

Unity UI の最適化に関するヒント – Unity for Pro

インターンで発表予定だったスライドのアーカイブ

はじめに

長期のインターンシップでゲームの設計について学んできました。最終的に実習課題を制作して、スライド資料を作ったりしたのですが、特に発表しないで終わってしまったのが心残りなので、スライド資料を置いておきます。

参考記事

スライドを観る上で参考になる資料を置いておきます

developers.cyberagent.co.jp

 

是非、読者登録をしていただくと助かります!

Unityがデザインパターンに関しての記事を出したので、ぼちぼち目を通していく (1/2)

はじめに

今回はUnityがデザインパターンに関しての記事を出したので、ぼちぼち目を通していく記事です。

 

唐突に公式がデザインパターンのサンプルを公開したので、自分なりに咀嚼して意見を述べたいと思います。ちなみに翻訳版ブログでは一部のみの解説になっているので、本家のブログを見るのをお勧めします。

blog.unity.com

github.com

 

 

SOLID原則

単一責任の原則

ひとつのクラスにひとつ機能だけを持たせる。なので、所謂神マネージャーのようなクラスはNGってことですね。PlayerMoveとか、PlayerAnimationとかにすることで他のクラスに変更を与えないようにしましょう!ってことですかね。

 

オープンクローズの原則

機能の拡張を行いやすくしましょう!ただし、その際に修正が入らないようにしよう!Unityを始めたての時は以下の様にTagや衝突したObjectの名前などで判定をしがちですが、この場合衝突を判定したいObjectが増えた時は、その都度名前やTagの条件分岐を増やしていくのでこの原則だとNGです。また、兎に角見にくいので辞めたい方法でもあります。

gist74e2a7d2a1488768185f42e1d0561241

 

こんなかんじでInterfaceで実装することで、機能を追加しても修正が入らないようになりました。

gist97867156eed274e682422ef51e7c1da5

 

リスコフの置換原則

基底クラスでのルールを派生クラスで破ってはいけない。具体的には、フィールドやメソッドのアクセスレベルとか条件を上書きしたり、強めるのはNGみたい。単純な話派生クラスで基底クラスのメソッドとかを上書きする形でいじると、基底で実装した内容が消えたり、意図した動作をしなくなるので辞めようね!と云う事らしい。

 

インターフェース分離の原則

インターフェースは細かく分けて定義しよう。細かく分けることで、使わない機能を実装しないようにしようってことらしいです。Interfaceは何個でも実装可能なので細かく分けちゃいましょう!

 

依存性逆転の原則

上位モジュールは下位モジュールに依存してはいけない。ここで云う上位モジュールは、下位モジュールを使う側の事で、下位モジュールは上位モジュールに使われるクラスの事です。まあイメージとしては、クラスAとBがあってAが直接BをNew()してから、Bに定義されているメソッドを呼ぶのはいかんよねって話ですね。

Destroy()自体が一つのクラスのみで使用するなら問題はないのですが、他のクラスでも同じように呼べるようにしたい場合や、引数を変更した場合はその都度修正しなきゃいけないのでめんどいってことです。

これはInterfaceを使うことで解決します。Interfaceを介して実行することで、引数がそれぞれ変わっていたとしても呼べます。これがInterfaceを使う前の物と比べて依存性が逆転しているので、そのまま「依存性の逆転」と呼ぶみたいです。まあ、抽象に依存するべきってことですね。

 

Factory

抽象クラスと具象クラスを使って、クラスの機能・責任を小さくすることで、変更があった際にも少しの修正で、生成をまとめて管理するぜ!って考え方です。また、使う側は単純にCreate()を呼び出せば良いので便利だったりします。以前Factoryパターンについて試したので、記事を置いておきます。

makaroni3018.hatenablog.com

 

おわりに

原則として知らなくても意識していたことが多かった印象でした。次回も引き続きデザインパターンを観ていきますよ!

 

是非、読者登録をしていただくと助かります!

UniRxとZenjectで以前作った体力ゲージを改造する

はじめに

今回はUniRxとZenjectで以前作った体力ゲージを改造する記事です。

前回の記事で作ったゲージをZenjectと混ぜて魔改造します。以前の記事からUniRxを使って作っていたいので、今回はZenjectを中心に紹介する記事になると思います。以下のリンクから前回の記事に飛べます。

 

makaroni3018.hatenablog.com

サンプルプロジェクト

github.com

 

 

ちょっとした修正

以前から思っていたことを修正しました。例えばModelはMonoBehaviour継承する意味ないよねとか、Start関数が汚くなるとかですね。

gist6118aab73439fd3ed65d1466946c7663

gistf07c961791e58e758a30238f9098b6c5

gist136722a8cf47a5d8202db310ec180aa6

InitializedとかSetEventとかでStart周りを綺麗にしました。ちなみにBindは購読処理をまとめたメソッドです。ModelはMonoを継承していないので、StartでNew()して生成しています。

そもそもZenjectって?

Unityで使えるDIライブラリです。今回はNew()の場所を変えたいのと、DIを自作するのが面倒くさいので使います。またZenjectとありますが、実は使用するのはアセットストアで公開されていて、現在もアプデもされているExtenjectです。

 

実際に学ぶなら以下の書籍がおすすめです。

booth.pm

Zenjectを実際に使っていく

試しがてらMonoBehaviourを継承していないModelクラスを依存注入してみます。Zenjectではコンストラクタインジェクションや、プロパティインジェクションなど様々な方法がありますが、今回かメソッドインジェクションを使います。また、注入先に [inject] をつける必要があります。

そして、Installerを使ってmodelを生成・注入します。今回は MonoInstaller を作って、 [inject] がついているメソッドインジェクションに注入していきます。

このクラスでModelをNew()して[inject]に注入します

後はSceneContextを生成して、先ほど作ったInstallerと結びつけます。これで準備完了です。

これでPresenterクラスでNewする必要が無くなりました。

 

Viewも注入したい

Modelクラスも注入しましたがViewクラスも注入したいです。そうなるとPresenterはインスペクターから直接アタッチしないので、Monoを継承する必要が無くなります。

そして実際に帰るとこうなりました。

gist3fb23edd27d08e8b695cd66e11b7963f

変わったところは、Viewの [SerializeField] が無くなりました。Zenjectで注入されるので使う必要がなくなりました。そして、メソッドインジェクションだったのがコンストラクタインジェクションになりました。

ちなみにコンストラクタがStartの役割をしていたりする

コンストラクタインジェクションは [inject] をつける必要が無くなります。自動でや注入先を見つけたり、エラーを吐いてくれたりするので基本的にZenjectではコンストラクタインジェクションが推奨されています。

PresenterがMonoを継承しないので、購読処理のリソース破棄がうまくいかなくなります。なので、IDIsposableを実装、CompositeDisposableをNew()してクラスのオブジェが破棄された時点で購読を中止するように結び付けました。

Installerは最初にPresenterを生成した後、Modelを生成して注入しています。ここでキーなのはNonLazyです。こいつがPresenterを明示的に一番最初に生成することで、注入できるようにする。

ViewはGameObjectなのいままでと少し変わります。Installerを作ってやるのではなくすでに準備されている ZenjectBinding を使います。こいつを使うことでViewの公開フィールドをいじらないで注入できます。

最終的にこうなりました

 

すこし気になるところ

コンストラクタをある種Start関数として使っていますが、実は純粋なクラスでもZenject側がStart関数の代わりを用意しています。IInitializabletのInitialized()というStartと同じタイミング・一回だけ実行される関数を使えばわざわざコンストラクタ内で実行する必要ないのですが、問題として実行順序がおかしくなることがあったので、今回使うのはやめました。

 

おわりに

正直またZenjectには慣れていないので間違っているところが多々ありかもしれませんが、一通りはこのパターンで実装していくと機能の追加などが楽になると思います。後、有用なスライドなどがあったら教えてくださると幸いです。

 

是非、読者登録をしていただくと助かります!

UnityでFactoryMethodを試してみる

はじめに

今回はUnityでFactoryMethodを試してみる記事です。

最近クラス設計を意識し始めているので、FactoryMethodを試しました。

 

 

FactoryMethodパターンとは

既にわかりやすいのがあったので、下記の記事を見ていただければわかると思います。

qiita.com

簡単に云えば、クラスの機能・責任を小さくすることで、変更があった際にも少しの修正で済み、生成管理をまとめて管理できるのが特徴だと思います。

 

試しに使ってみる

実際に作ってみました。鬼とかを生成するファクトリです。攻撃ができたりします。

gistb98e5c6e955a514ab9d534f8ad86f091

gist684c61b7695ac341366bf6d90c326aa8

gist6ff2719675c310f8b1023cbd6176a1d8

gistce337cd96454fb5ce2609d26cd196fce

giste9db1d56bf4f00a581d28ab5ae1b4b3d

やっぱり生成するタイミングをまとめて管理できるのは良いですね。UniRxと混ぜて全体の流れを管理したい。

おわりに

FactoryMethodを試してみました。試す機会があまりなかったので、どんなものかおおよそ理解できたと思います。

 

是非、読者登録をしていただくと助かります!

TextMeshPro対応したフォントをPushしようとしたら、Gitの100MB以上はPushできない制限に引っ掛かってしまった場合

はじめに

今回はTextMeshPro対応したフォントをPushしようとしたら、Gitの10MB以上はPushできない制限に引っ掛かってしまった時の対応策を紹介する記事です。

 

Unityでモデルや画像をgitのリモートリポジトリにPushなどを使用すると以下のようになることがあります。

この時の対応策を紹介していこうと思います。

 

 

そもそもこのエラーの意味は?

このエラーはいわゆる該当のコミットが100MB以上だったため、Pushなどが出来なかったことが原因です。

もともとGtiはコードを保存する目的で運用されているので、大きなバイナリーデータなどを扱うようにできてないようです。

50MB以上のコミット段階で警告がでる

LFS(LargeFileStorage)を使う

今回の問題を解決する機能です。リモートリポジトリに直接ファイルを上げるのではなく、別々に保管しておくことでリポジトリのサイズを抑えます(リポジトリは、ファイルの保存先を保持・操作することで実現しているみたいです)。

 

*事前にGitをインストールしておいてください。

GithubDesctop

1. GithubDesctop=>Repository=>Open in Command promptでコマンドプロンプトを起動

2. コマンドプロンプトに git lfs install と入力して、lfsを使えるようにします

3. git lfs track * 拡張子 と入力して、100MB以上のファイルを登録します

TextMesProて生成したフォントを登録しました

4. 登録すると .gitattributes が追加されるので、リモートに反映させます

5. 登録後に100MB以上のリモートに持っていきたいファイルをコミット・プッシュすれば完了です!

SourceTree

1. リポジトリ=>Git LFS=>リポジトリの初期化を選択

2. リポジトリ=>Git LFS->追跡/未追跡のファイル から追加したいファイルの拡張子を追加

3. 登録すると .gitattributes が追加されるので、リモートに反映

追加したいファイルの拡張子を選択

5. 登録後に100MB以上のリモートに持っていきたいファイルをコミット・プッシュすれば完了です!

 

ちなみにLFSは月ごとに使用できる制限があります(ここから自身が使用しているリソースを確認できます)。

そもそも容量が大きいファイルをリモートに置かない

元も子もないですが、そもそも大きいファイルを置かなければ良いわけです。なんだかんだでこれが安全かもしれません(以前ファイルが消し飛んだことがありましたし...)。しかもLFSは容量制限があり、無課金であればストレージ容量は1GB、転送量1GB/月なので、なんだかんだで使い切ってしまうと思います。案としては、サーバーやDropBoxで管理するのか良いと思います。

おわりに

今回はGitに100MB以上のファイルを上げる方法の一部を紹介しました。

 

是非、読者登録をしていただくと助かります!