UniRxはもう古い?使い勝手の良さそうなMessagePipeを勉強してみた

こんにちは、やまだたいし( やまだ たいし (@OrotiYamatano) / Twitter )です。
イベントが使えるUnityのライブラリが使いたくて色々調べていました。
Unityには標準でもイベントが扱えるものがありますが、寿命管理や使い勝手が少々微妙です。

他にはUniRxもありますが、Linq前提なのと使いこなせる方が意外と現場に少ない&グローバルなスコープには向いてないという現実です。
(一応UniRxにもMessageBrokerがあるんですけどね……)
そこで私はMessagePipeを勉強することにしました。

今回はその時の知見を共有したいと思い記事化しました。

目次


なぜ?イベントが使いたいのか?


そもそもなぜイベントが使いたいのかという話をさせていただきます。
それはゲーム自体が疎結合に作るのが難しいというのがあります。
結合性を下げるためにMessageを使えば良いのではないだろうかと思ったからです。

MessageやEventは昔からありつつも実装が見直されてきている感じがします。
そして現在主流になりつつあるあるのを感じます。
最近ではEvent中心の設計をイベント駆動型プログラミングと読んだりします。
UEなんかでも用いられます。

一般的に、グラフィカルユーザインタフェース (GUI) を使用するオペレーティングシステムアプリケーションソフトウェアでは、イベント駆動型プログラミングを利用している。マウス操作やキーボード操作といったユーザーからの入力や、システム状態の変化・変更といった各イベントに対する処理を統一的に記述することができます。(Wiki引用)

しかしながら安直なイベントはデメリットが有る


イベントは疎結合に利用できますが、どこから呼ばれているか分かりづらくしてしまうというデメリットもあります。
UniRxが基本クローズドなイベントに適した形になっているのもこれが理由だと思います。(しらんけど)

Unityの公式にも引用されている、ScriptableObjectを使った不思議なイベントシステムもありますが、特にコチラ↓はどこから呼ばれているか分からなくしている代表的な例だと思います。

unity.com

UnityAtomsというライブラリが上記のScriptableObjectを改良したものだったのですが、
私が使ってみたところ

スタックトレースをさせるために内部でC#のStackTraceの処理を呼び出していて(実機実行時は大丈夫だが)デバッグ時にイベントが走るだけで数msかかってしまう(場合によっては10msかかってしまう)
・使用するイベントが多くなるたびにエディタ上での参照が多くなって管理がし辛くなる(コーディングが苦手な人には向いてるかも?)
・ぶっちゃけ、UnityEventの上に載ってるので、そこまで早くなく、UniRxのMessageBrokerの方が良さそう

という印象でした。

MessagePipeは良いのか?


github.com

ある程度習熟度がある方なら良いと個人的には思います。
MessagePipeが解説されている記事が少ないですが、ソレには理由があると考えます。

ライブラリ前提で組まれている

MessagePipeはDIライブラリ前提で組まれています。
DIについては割愛しますが、MessagePipeがDIライブラリを使うのには理由があります。
通常パブリックにイベントを使う場合、どこから呼ばれているかわからないというデメリットが生じます。
そこで、DIを使って依存性が注入されるタイミングや寿命を管理してしまうことで期間的にも制限が加わるので多少はスコープが大きくなりすぎてしまうデメリットを軽減できます。

しかし、DI自体を理解しないまま実装するとスコープも大きくなってしまう可能性もあり、
更にインスタンスは増大する可能性もあります。
そうなってしまうと正直良いことがありません。

さらにUniTaskというライブラリも導入が必須です。
正直導入ハードルが高く、解説をするほどユーザー数は少ないのだと思います。

また、DIを高度に利用できているようなユーザーは説明を受けなくても理解できてしまう。
しかもDIライブラリ、Zenjectなどにもイベント機能が入っており、そちらの利用でも十分だったりします。

なので、MessagePipeが解説されている記事が少ないんだと思います。
とはいえ、現状Unityでイベント駆動をするならこのライブラリが最強だと言わざるを得ないでしょう。

(Unity公式のイベントもっと頑張れよ!!!!!小声)

さっそくインストールしてみる


使用ツール


Unity2021.3.1f1
MessagePipe:Ver1.7.4
VContainer: v1.11.1
UniTask:Ver2.3.1

次に基本の実装をしていこうと思います


それぞれライブラリのインストールが済んだら、基本の形になるサンプルを実装してみようと思います。
ちなみに今回は一緒につかうライブラリのVContainerやUniTaskの解説は行いません。

MessagePipeで使える種類


メッセージにも様々なものがあります。
細かいオプションはありますが主に3つ。
どんなものがあるのか一つずつ簡単に説明していきます。

1.送り手と受け取り手(Publish/Subscribe)


送る方と受け取る方を定義して、間をつなぐのをDIが行います。

お互いがつながったところで、
送る方が条件を満たしたらDIされたオブジェクトへPublishします。
(Event発行はライブラリによって呼び方様々ですよね。SendだったりPublishだったりBroadcastだったり)

受け取る方はDIされたオブジェクトから送り手からの通知を読んで、反応をします。
終わり。

この形をPub/Subと呼びます。

で、DIがお互いをつなぐ条件は何かというとですが、Publishする型です。
しかし、コレでは頻繁にPublishされた際にどれがどれに対応しているか不明です。
そこでキー付きにできます。Guidをつけることで簡単に見分けられる!

2.イベントファクトリー


Pus/Subで通知が出来るってのはわかる……。
スゲーよくわかる送信と受信だからな……。
だが、Publishの条件が『型』っていうのはどういう事だぁ~~~~っ!?
いくらクラスがつくれるからってよ、intとか同じ型で別のメッセージやり取りしたい、型ごとにグループ化されていないことって沢山あるじゃねーか!!
それごとにクラスやキーを作れるかつーのよ――――ッ!
ナメやがって!!超イラつくぜェ~~~ッ!!チクショ――ッ!!
ってギアッチョ並にブチ切れた人が居るかもしれない。

安心して欲しい。
イベントファクトリーというものがある。

通常のPub/Subでは、DIにより、型でワイヤリングされていますが、
EventFactoryからイベントの個別のインスタンスを作り出すことが出来る。

言うなればC#のEventと似た機能らしい。
じゃあ、C#のEventでいいじゃんと思うかもしれないが、C#のEventより多機能。
一つ気をつけないといけないことは必ずDisposeしなければならないということ。
無視するとリークする。

コードの書き手によるので、うっかり破棄が漏れることもある。
その辺はアナライザがあるのでソチラを活用してほしいとのこと。

3.リクエスト/レスポンス/オール


個人的に一番オススメしたい機能。

オブザーバー デザイン パターンだけでなくメディエーターパターンで作りたいなら通知に対する返信が欲しくなる。
そこで利用するとよいのがリクエスト/レスポンス/オールだ!

Mediator(仲介者)を介してメッセージのやり取りを行う機能。
これであればいろんなところから参照したい場合にMediatorを起点(エントリーポイント)に考えやすい。
特にリクエスト/レスポンスは1対1なので、追いやすい。(レスポンスは早いものがち?)

2のイベントファクトリーでもエントリーポイントは作成できたが、投げっぱなしで、
現在どこで何の処理が行われているか見失いがちになる気がする。
そこで処理に対する結果を工夫して返却することで安心して通知処理出来るということだ。
(なんというか、イベントファクトリーとかがUDPだとするとリクエスト/レスポンス/オールはTCP的に組めるよね)

オールは1対多の通知を行う。
敵キャラに対して全滅処理を行うなどの実装が楽そうだ。

実際に書いてみる


(ネームスペースの有る無しは適当なので見逃してください)

1.送り手と受け取り手(Publish/Subscribe)(キーなし)


まずはスタンダードなPublish/Subscribe。
ぶっちゃけコレしか使わないならMessagePipe使うメリットはあまり感じない。

スクリプトアタッチ情報

コード

Test1Publish .cs

using MessagePipe;
using UnityEngine;
using VContainer;

public class Test1Publish : MonoBehaviour
{
    [Inject] private IPublisher<int> _publisher;
    private int _num;

    void Start()
    {
        _num = 0;
    }

    void Update()
    {
        if (!Input.GetKeyDown(KeyCode.Z))
        {
            return;
        }
        _num++;
        _publisher.Publish(_num);  //Zを押すとパブリッシュされる
    }
}

Test1Subscribe.cs

using System;
using MessagePipe;
using UnityEngine;
using VContainer;

public class Test1Subscribe : MonoBehaviour
{
    [Inject] private ISubscriber<int> _subscriber;
    private IDisposable _disposable;


    private void Start()
    {
        var d = DisposableBag.CreateBuilder();
        _subscriber.Subscribe(num =>
        {
            Debug.Log(num + "Subscribe");  //Subscribeに成功するとDebugLogに表示
        }).AddTo(d);
        _disposable = d.Build();
    }
    
    void OnDestroy()
    {
        // 破棄されるタイミングでOnAttackイベントの購読をやめる
        _disposable.Dispose();
    }
}

Test1LifetimeScope.cs

using MessagePipe;
using VContainer;
using VContainer.Unity;

namespace Scenes.Test1
{
    public class Test1LifetimeScope : LifetimeScope
    {
        protected override void Configure(IContainerBuilder builder)
        {
            var options = builder.RegisterMessagePipe(/* configure option */);
            builder.RegisterMessageBroker<int>(options);
        }
    }
}

結果

2.イベントファクトリー


多分モノビヘイビアに書いても使えるんだろうけどピュアスクリプト側に持たせてみた。
Unity側の依存を減らせるのは嬉しい。
正直これだけだとPublish/Subscribeと変わらなないように見えるが、
Test2Publish で生成されている eventFactory に紐づいて定義されているので、
Test3Publish などを作った場合も別々に通知される。
+=, -= で購読を管理出来るようですが、やり方が微妙にわからなかったので誰か教えて。

スクリプトアタッチ情報

コード

Test2Publish.cs

using System;
using MessagePipe;
using UnityEngine;

public class Test2Publish : VContainer.Unity.IStartable,IDisposable,VContainer.Unity.ITickable
{
    IDisposablePublisher<int> tickPublisher;

    public ISubscriber<int> OnTick { get; }

    public Test2Publish(EventFactory eventFactory)
    {
        (tickPublisher, OnTick) = eventFactory.CreateEvent<int>();
    }

    int count;
    public void Dispose()
    {
        // You can unsubscribe all from Publisher.
        tickPublisher.Dispose();
    }

    public void Start()
    {
        OnTick.Subscribe(x =>
        {
            Debug.Log(x + "Subscribe");
        });
    }

    public void Tick()
    {
        tickPublisher.Publish(count++);
    }
}

Test2LifetimeScope.cs

using MessagePipe;
using VContainer;
using VContainer.Unity;

namespace Scenes.Test2
{
    public class Test2LifetimeScope : LifetimeScope
    {
        protected override void Configure(IContainerBuilder builder)
        {
            var options = builder.RegisterMessagePipe();
            builder.RegisterMessageBroker<int>(options);
            builder.RegisterEntryPoint<Test2Publish>(Lifetime.Singleton);
        }
    }
}

結果

3.リクエスト/レスポンス/オール

さっき(の2で)はピュアスクリプトにもたせたので今回はモノビヘイビアにもたせてみる。


スクリプトアタッチ情報

コード

Test3Presenter.cs

using System;
using MessagePipe;
using UnityEngine;

public class Test3Presenter : VContainer.Unity.IStartable
{
    IRequestHandler<int, bool> requestHandler;

    public Test3Presenter(IRequestHandler<int, bool> eventFactory)
    {
        this.requestHandler = eventFactory;
    }

    public void Start()
    {
        var pong = this.requestHandler.Invoke(1);
        Debug.Log("PONG" + pong);
    }

}

Test3RequestHandler.cs

using MessagePipe;
using UnityEngine;

namespace Scenes.Test3
{
    public class Test3RequestHandler: MonoBehaviour,IRequestHandler<int, bool>
    {
        public bool Invoke(int request)
        {
            Debug.Log("PONG" + request);
            return true;
        }
    }
}

Test3LifetimeScope.cs

using MessagePipe;
using VContainer;
using VContainer.Unity;

namespace Scenes.Test3
{
    public class Test3LifetimeScope : LifetimeScope
    {
        protected override void Configure(IContainerBuilder builder)
        {
            var options = builder.RegisterMessagePipe();
            builder.RegisterRequestHandler<int,bool,Test3RequestHandler>(options); //モノビヘイビアオブジェクトNewするとWarningで怒られちゃうけど、いいんかな?
            builder.RegisterEntryPoint<Test3Presenter>(Lifetime.Scoped);
        }
    }
}

結果

モノビヘイビアを持つクラスをnewするなと怒られてしまったが、成功。
(Warning回避する方法ってあったりするのだろうか……?)

今回説明を割愛したもの


簡単に一言で説明します。

ISingleton***、IScoped***


寿命やスコープが管理できる機能。
あると便利だよね

Buffered


最後にPublishしたものをSubscribeで取得できる仕組み。
通常のメッセージとは違う使い方でRx的な使い方だったので割愛した。

Subscribe Extensions


メッセージにフィルター機能をつけて、Publishを避けたり
メッセージの変換処理を作ったり出来る。
上級者向け機能だったので解説は割愛。

Filter


メッセージの呼び出しにフックしてログを出したり出来るらしい。
よくしらんけど。

Managing Subscription and Diagnostics


デバッグ用機能。
呼び出された回数などを監視できる。

IDistributedPubSub / MessagePipe.Redis,InterprocessPubSub、IRemoteAsyncRequest / MessagePipe.Interprocess


正直よーわからんかった。
ちゃんと読めば分かると思うがネットワークに紐づく機能っぽかったので割愛。

MessagePipeOptions


MessagePipe 自体の動作の構成オプション設定。
メッセージのライフタイムの設定とかが出来たり、DI側の色々設定。
ISingleton***、IScoped***とも紐づいてくるし様々だったので割愛。

使い込むなら公式読んだほうが良いかも。

まとめ

とこんな感じで様々な形でイベントを通知出来る仕組みが存在する。
グローバルも存在するが、正直グローバルで使うのはコントローラーのインスタンスをInjectするぐらいだろうので説明は割愛した。(正直グローバルはあまり使わないほうが良いとは思うし)
個人的にはEventFactoryで作ったインスタンスをDIでInjectを出来るようになって欲しい。(やり方あんのかな?よく分からん)
またリクエスト/レスポンス/オールのEventFactoryも欲しいと思った。
まぁソレが出来てしまうと一見どこにどのインスタンスが紐づいているのかコード上からソースを追うのが難しくなってしまう側面もあり、
実際に実装されても特定のパターンでしか使わないと思うので、単純に私のワガママに過ぎないのかも知れない。

まだまだ拡張できそうな実装だが、シンプルに実装する分には分かりやすく、
レイアリングには適したライブラリだと思います。
メッセージングライブラリで個人的に一番しっくり来たライブラリです。

みなさんが使い始め、利用法が色々広がれば、きっとUnityでの利用改善も進んで行くと思うのでぜひ皆さん使ってみてください。
以上、やまだたいしでした。

【備忘録】Blenderの使い方個人メモ

こんにちは、やまだたいし( やまだ たいし (@OrotiYamatano) / Twitter )です。
個人ゲーム作成でBlenderを触ることが多々あるのですが、毎回ショートカットなど使い方を忘れるので、
Blenderの使い方のメモです。

目次


環境


Blender 3.0
Windows 10

ショートカット一覧


Shift + c カーソル原点移動
→メニューオブジェクトの頂点を3Dカーソルに

Ctrl + z 戻る
Ctrl + Shift + z 進む
Tab 編集モード、オブジェクトモード切り替え

  • 編集モードで

z ワイヤーフレーム、ソリッド切り替え
Ctrl + 左クリック 投げ縄選択
a 全選択
Alt + m 直線選択
Ctrl + r ループカット
g 移動
gの後 x or z or y 指定方向にのみ移動
Shift + d でオブジェクトのコピー
Pでオブジェクト分離メニュー
Shift+左クリック後→Control+Jで統合
Ctrl + n ポリゴン裏返し
Ctrl + v 頂点メニュー
Ctrl + f 面メニュー 厚みけ等がある
Ctrl+L 選択範囲と繋がっているメッシュを全て選択
Alt+S 法線方向に拡大・縮小
Shift+Alt+s 切り組み円形化
Ctrl+Jオブジェクトの結合
Shift+Ctrl+B:頂点のみ面取り(ベヘル)

面の反転


編集モードに切り替えて操作したいメッシュを選択する。 ビュー左上の「メッシュ」→ノーマル→反転

立体のマスク


まず、
マスクする用の立体を作成、
モディファイヤの追加→ブーリアン差分

内側に縮小

編集モードで面を選択して、Iでインセット

ボーンの親子関係を維持したまま分離させる方法


編集モードで分離させたいボーンを選択して、
Alt+P→コネクト解除

メッシュを埋める


ぽっかりと空いた穴のひとつの辺を選択した状態で、F キーを連打すると、そこから四角形の面で連続して埋めてくれます

maku77.github.io

親子関係の点線の表示


親子関係の線にチェック

メッシュの裏面を表示


ボーンの左右コピー


頂点グループの追加


↑の+で追加。
そして頂点を選択して割当

ウェイトペイントについてまとまってるページ


dskjal.com

AutoRigPro


自動ウェイト、スキニング、ツール。
コレで設定しているならウェイトペイントは基本いじらず、設定をイジってウェイトを入れ直したほうが効率が良さそう。

カスタムBone追加


既に追加されてるコントローラー(制御用)ボーンにくっつく形で追加すればよい。
ちなみにコントローラーボーンとは「Layer 31: Deforming bones」か「Match to Rig後に可視化されるもの」

エクスポート時にボーンをしっかりエクスポートするためには明示的にカスタムボーンであることを設定しないといけない。
方法は3つ(厳密には2つ)

1.カスタムボーンを選択して[Auto-Rig Pro: Export]パネルの[Set Custom Bones]ボタンを押す(3を自動的にやってくれるやつ)
2.カスタムボーン名称の頭に「cc_」とつける(プログラム的に言えばprefixといえばいいかな?)

lucky3d.fr

IKとボーン操作切り替え


ツール内に設定がある

UV展開


自前でやるのはかなり大変らしい。
色々自動でできるところは自動でやるべきらしい。
今回は無料ツールMagicUVを使っていく。
最初から入っているが、非アクティブなのでPreferenceよりプラグインの有効化。

tohawork.com

シームをつける


UVを展開する前にどう切り分けるか、設定できる。

UVEditingで切るところを選択、辺→シームをマーク

展開していく


頂点を選択→U→展開を選ぶ
(色々調整することを考えると、スマート投影UVが良いかも?)

UVのやり方が丁寧な動画


www.youtube.com

辺の切り裂き


辺を選択しV

テクスチャペイント


頂点ペイント→ベイクする場合


Blender 3.0とは若干UIが違うが、配置が違うだけで、ここのリンクが参考になる

bluebirdofoz.hatenablog.com

AOベイク


AO(アンビエントオクルージョン)→直訳すると環境遮断
折り目、穴、互いに近接する表面に発生するソフトシャドウをつける機能。
リアルタイムにやるものと焼き込むものがある。

デザイナーの人に分かりやすく言うと影(Shadow)ではなく陰(shade)の擬似的表現が出来るものです。
標準機能でBakeする機能もあるが、使い勝手が悪いらしいのでTexToolsを使う。

アドオンをインストールしたらテクスチャの変更画面のTexToolsでベイク対象をAOを選び、
Bakeボタンを押してベイクする。

8でベイク後、問題なければサンプリング数を上げて(128~256)ベイクすると良いらしい。
固まったかのようにベイク処理がされてるのか分かりにくいが安心して欲しいちゃんと行われている。

(正直Substanceペインターでやったほうが良いかも……?)

ワイヤーフレームをテクスチャにベイク


ペイントソフトでテクスチャを描くときに目安になるワイヤーフレームを出力したくなる。

編集モードで出力したい頂点を選択し、
「UV Editing」タブを開き、「UV」から「UV配置をエクスポート」を選択し吐き出すと良い。

サイズの調整


Blenderの基本単位とUnityの基本サイズは同じだがグリッド表示などが分かりづらい。
ビューポートオーバーレイのScaleを0.1にすることで10cm単位でグリッドが表示される様になる。

アニメーション

フレームレート設定

ゲームだと60とか30が調整しやすい。

エクスポート設定

まとめ

完全に個人用メモ。

UnityでRoslyn触ってみた

こんにちは、やまだたいし( やまだ たいし (@OrotiYamatano) / Twitter )です。
先日GitLabをつかってCIを走らせるようにしたのですが、さらに便利にしたいと思い
Roslynを触ってみることにしました。
本記事はその内容の備忘録です。

目次


そもそもRoslynとは?


NETコンパイラープラットフォーム(.NET Compiler Platform)のことです。
コード名および通称は「Roslyn(ロズリン)」。(以下、Roslynと表記)
簡単にいうとRoslynはIDEコンパイル時の情報を提供してくれるAPIみたいなものらしいです。
もらえる情報は構文解析・意味解析を行った情報っぽい?
ツールとエンド ユーザーが豊富な情報コンパイラを共有するためにある様子。

具体的にそれを通じて何が出来るようになるのかというと "アナライザー" と "コード修正機能" を構築できるようです。
後、ソース生成も。

UnityでRoslynを使うメリット


Unityを開いた時などにコードの違反を見つけたりが出来ます。
例えば、「UniRxを使ったときは必ずSubscribeにAddToをつける!」というプロジェクトルールを作りたい場合などに適しています。

初心者にわかりやすく、追加する意義を解説をします。

リーダブルコードを読んだことありますでしょうか?
いってしまえば読みやすく良いコード書こうぜ!って話なのですが。
なぜ可読性を良くする必要があるのかというと可読性の悪いコードはソースコード品質が悪くなりがちだからです。

品質の悪いコードはコードスメル(コードの臭い)と言われ嫌われます。
ヤツ(コードスメル)は駆逐しなきゃぁいけません。

とはいえ、ゲーム業界は好き勝手につくりたい人が多く、
コードスタイルの統一を極度に嫌う人が居ます。

また、コードレビューでさえ嫌う人がいます。
「コードの指摘」は「コードを作成した本人の否定」ではないにも関わらず、
混同し「意地悪されている」と勘違いしてしまう人が一定数いるようです。

特に「コードフォーマットの指摘の重要性を理解していない人」は
「コードフォーマットの指摘をする人」を「プレゼン資料の荒探してる人」と同じように見てしまう。

「コード指摘する側」は「キレイなコードを書いて欲しいと思うのに書いてくれない」と思い
「コードを指摘される側」は「好きにコード書きたいのにちょっとしたことで指摘されコードを好きに書かせてくれない」と
思うことになります。
そのようになってしまうと、対人的な衝突を生み、互いが辛い思いする羽目になってしまいます。

そのため、コード規約は大事だと理解していながら
コード指摘によって対人的な衝突を生んでしまうことを忌避し
コードスタイルが悪くても放置されてしまうことが多々あります。

これではコード品質が落ちてしまいます。ジレンマ。

であれば、どうすれば良いのか。
コードフォーマットの指摘は機械(CI)にやって貰えば良いんです。

また、晒されるようにSlackで通知が飛ぶようになれば、必然的に皆、治すようになると思います。

そういったことをするために、このRoslynは有効なのです。

もちろんUnity上だけでなくIDE上でも利用可能ですがUnityのビルド機能を使ってCIで通知を出すならRoslynを使うのが便利です。
(Unity上でつかうならUnity 2020.2以上)

Roslynの基礎的な使い方はコチラが参考になるかも?
swet.dena.com

コード指摘について熱く語っておきながら、残念。今回はSource Generatorを試します。
(コード指摘させるのは本記事のまとめにも軽く触れていますが、他の方が記事を作ってらっしゃったりするのでソチラを読んだほうが良いです)

使い込めばゲーム中に動的にコード生成が出来るのでDIのような挙動が作ろうと思えば作れるはずです。
かなりFrameworkライクな機能だと思いました。

そもそも今回触るSource Generatorが
アップルさんが「動的コード生成駄目」って言うんもんだからRoslynチームが開発したものだそう
なかなかどうしていい感じ。

実際に入れてみる


環境:
Unity2021.3.11f1
Rider:2022.2.3

今回はUnity公式で紹介されているCodeAnalysisを使ってみようと思います。

docs.unity3d.com

今回はJetBrains商品のRiderで入れてみます。
Riderの新規作成(New Solution)でプロジェクトを作成します。

ヘッダメニューのTools>NuGet >Hide Nuget Tool Windowを選択(フッタにあるならソレ選択でもOK)

CodeAnalysis.CSharpを検索します。
Unity2021.3で使えるアナライザーのVersionは3.8のようですので、3.8を選択します。
そして+を選択します。

Unity公式に載っている、ExampleSourceGenerator.csを作成。

そしてリリースを選びBuildを行います。

次にUnityでCodeAnalysisを使えるようにするためにdllをUnityに追加します。

JetBrainsで追加した場合は以下にdllファイルが出来ていると思うので、ソチラを Unity プロジェクトの Assets フォルダー内にコピーします。

dllが出来る場所:(Project名)\bin\Release\netstandard2.0

コピーしたらUnity上でコピーしたdllファイルを選択しInspectorにて各プラットフォームのチェックを外します。
そしてApply

AssetLabelsをクリックして、ラベルマークよりRoslynAnalyzerタグを追加。

↑でエンター

Unity公式に載っている、HelloFromSourceGenerator.csをAsset配下に作成。

で、適当なGameObjectにスクリプトを貼り付けて再生。

できた

他にもライブラリがたくさん


今回使ったソースジェネレーターだけでもいくつかライブラリがあります。
(全部Unityで使えるとは限らないけれど)
↓ライブラリまとめ
github.com

Roslynベースでも色々あります。
↓ライブラリまとめ
github.com

まとめ


今回はRoslynについては以上にします。
本当はRoslynとUnityでStyleCopを触るところまでやったのですが、
Unityは現在EditorConfigやAdditionalFilesをいい感じに処理してくれず思った通りな挙動をしなかったので割愛です。
(デフォルト設定で動かすぐらいなら難なくできます)

厳密に言うとAdditionalFilesは コチラ などで導入すればある程度は処理されるのですが、
「StyleCopで特定ディレクトリのファイルのみ検査させるように」&「AdditionalFilesの設定を適切に読み込む」という2つの条件を満たそうとすると上手く動かない。
特定のディレクトリだけで動かす方法は現在 こちら で紹介しているasmdefの方法がありますが、
前述の拡張の挙動との兼ね合いを考えると無理なのである……。残念。

私個人としてはUnityのエディタスクリプトでRoslynのAdditionalFilesを指定できる部分があったので
「そのへんを頑張れば、なんとか出来る可能性があるかも」とは思いましたが、
そこまでやる気にならなかったので、後はやる気がある人に任せます……。

後、触ってみた所感、
今後SourceGeneratorを使ったUnityでいい感じのゲームFrameworkが出てきそうだと思いました。
私はFrameworkを作る側の人間じゃないのでガッツリは触らないと思いますが、
なにかおもしろい利用方法を浮かんだ人は是非教えてほしいです。

以上、UnityでRoslyn触ってみたでした。

UnityでCI Build。GitLabRunner触ってみた!

こんにちは、やまだたいし( やまだ たいし (@OrotiYamatano) / Twitter )です。
CIに手を出したいのですが色々考えた結果GitLabCI+Runnerが良さそうだと思ったので今回触ってみました。
今回はその時の知見を共有したいと思い記事化しました。

目次


そもそもCIとは


CI(継続的インテグレーション)の略。
本記事で言うCIはCI環境のこと。

CI環境とはビルド・テスト・デプロイという一連のソフトウェアの開発サイクルを短いスパンで行う環境のことです。
その環境を提供してくれるツールをCIツールと言います。

その数多くあるツールのうちの一つのGitLabCI+Runnerの組み合わせが今回良かったように思えたので紹介です。

CIを使うメリット


Unityなどでビルドした方は分かると思いますが、 ビルドには結構な時間がかかります。
その上、ビルドしたらビルドしなかったときとは違うエラーが出てしまうことも少なくありません。
バグを出さないためには高頻度にビルドを走らせ、エラーが出ないかチェックしたほうが良いのですが、
その間ビルドでPCを占拠してしまうのは勿体ないです。
かと言ってビルドせず最後まで放っておくと修正が大変になってしまいます。

そこで登場するのがCIです。

CIツールを使ってサーバー上や別PCでビルドを走らせることで、早くエラーに気づけるようにしようという試みが行えます。

なぜGitLabCI+Runnerなのか


UnityでのCI環境はいくつかあります。
私が知っているものがいくつかあります。

・Unity Cloud Build
Github Actions
・Jenkins
・GitLabCI
・CircleCI
・codemagic
・GitLabCI+Runner

この中でGitLabCI+Runnerを選んだ理由は一番使い勝手が良さそうだったからです。
具体的に他CIを選ばなかった理由も含めて説明を書いて行こうと思います。

Unity Cloud Buildが適さない理由


小規模プロジェクトであればUnity Cloud Buildが有効だと思います。
unity.com

しかし、Windowsでのbuildが$0.02Build minと有料です。 できれば無料でやりたいし、有料なら他ツールでも良さそうです。
後最近は大分良くなってきているようですがカスタイズ性に優れていない感じあります。

Github Actionsが適さない理由


Github Actionsを使ったCIには有名所の設定はGameCIというものがあります。
こちら企業でも使われているものなんですが、 Github Actions無料枠の場合2000分/月の無料枠&スペックそんな良くないので時間かかりがちのため
適さないと考えています。
(有料枠ならありだと思います)

Jenkinsが適さない理由


コチラはカスタマイズ性に優れていますが、こちらはサーバーの機能はないため別途ビルド用のPCをセットアップする必要があります。
過去にセットアップする記事も私が上げているのですが、設定時に2つのPCを頻繁に行き来する必要があるのと、設定が意外と面倒だったので、今回は除外です。
しかしながら、カスタマイズ性が高いため、企業では今もよく使われます。

GitLabCIが適さない理由


コチラは5GB storageとチョット容量が少なめです。
また、1 か月あたりの転送量も10 GBと少なめで大量にアセットを使うゲームでは適しません。
また、オンプレ版でないとLicence認証あたりで躓いてしまいます。

CircleCIが適さない理由


CircleCIはコレまで候補に入れていなかったのですが、
2022年に入ってから、CircleCIが無料枠を大幅拡大し、1カ月あたり6000分のビルド時間が得られるようになりました。
候補に入れるのはありだと思いました。

これまでは無料枠は1ヶ月あたり1000分のビルド時間まででGithubActionsより少なく問題だったのですが、
GithubActionsより大幅にビルド可能時間が伸びたのは嬉しいですね!

Macでの無料buildはRAMが8GB、DiskSizeが200 GBですがストレージがデフォルト2GBで
30,000 クレジット無料で使えますが正直ソチラを利用してもストレージがデフォルト2GBの関係上、残念な価格になりそうです。
バイナリをたくさん使っているプロジェクトだと余裕で超えてしまいます。

www.publickey1.jp

codemagic


codemagicを使う。
FREE版ではmacOS M1 Standard VMが使えるらしい。
サイズはなんとDisk 322GB (Free Space: 122GB)!でかい!
色々入ってない状態での話でXCodeなどが入るともう少し容量は小さくなってはしまうらしいが……。
XCodeがプリインストールされたものはディスク294GB (Free Space: 31GB)ほどらしい。(それでも十分)
月当たり500minのbuildが出来るらしい……。
buildのタイムアウトは120min。

がしかし、Unity Plusもしくは Unity Pro Licenceじゃないと使えないという欠点がある。
稼げるようになったら使いたい……。

GitLabCI+Runner


ということで、GitLabCI+Runnerの組み合わせで使うことにした。
ところでRunnerとは何かというとGitLab Runnerのことで、通常GitLabCIではGitLabが構築されたサーバーなどでのbuildが行われますが、Runnerはジョブをセルフホストで行えるものです。

docs.gitlab.com

GitHubActionsにも似たような機能がありGithubActions+Self-hostedRunnerで構築しても良いのですが、GitLFSを使いたいと考えた場合にGithubでは1GBまでしか無料でGitLFSを使えません。
GitLabならばRepositoryサイズトータル(LFS含めて)で10GBまで利用可能なので、ソチラを使ったほうが良いという判断です。
またGitLab+GithubActions+Self-hostedRunnerやGithub+LFSリポジトリサーバー+GithubActions+Self-hosedRunnerなどの組み合わせも存在しそうですが、やはり構成が簡単なGitLub+GitLubIC+Runnerが良いと判断しました。

環境


今回は

Unity2021.3.11f1
GitLab
Windows ローカルホスト

での利用を想定。

作業手順目次


早速、以下手順で導入をして行こうと思います。

(GitLubへの登録・初回コミットは済んでいる想定)

1.Runnerのダウンロード
2.Runnerの登録
3.実際にRunnerを使ってみる
4.Unity側のスクリプト
5.yml(ビルドパイプライン)の設定
+α 6. Slackへの通知
+α 7. deployGateとの連携(理想)

1.GitLabRunnerのダウンロード

今回はWindowsでの利用を想定しています。

Runnerを動かしたいビルドサーバー(Windows)にてRunnerのダウンロードを行います。
以下リンクよりダウンロードを行います。
docs.gitlab.com

Install on Windows を選択
私の手元のPCはWindows10の64bitなので64bitを選択

ダウンロード。

パワーシェルを管理者権限で立ち上げ、先程インストールした gitlab-runner.exe (ダウンロードした物によって名前が違います。以後は私の環境で行うので gitlab-runner-windows-amd64.exe とします)を指定してインストールする。
コマンド的にはこんな感じ

.\gitlab-runner-windows-amd64.exe install


↓のようなメッセージが出てきたらそれは管理者権限じゃないので昇格します。

FATAL: Failed to install gitlab-runner: Access is denied.
## ちなみに昇格コマンドは↓
Start-Process powershell -verb runas

 

Runtime platform arch=amd64 os=windows pid=xxxxxxx revision=xxxxxx version=15.4.0

などのようなメッセージが問題なく表示されてれば多分OK

2. GitLabRunnerの登録

GitLabRunnerが問題なく動いたのを確認したら、Runnerと実際のRepositoryを紐づけるためにGitLabにRunnerを登録します。

↓参考
docs.gitlab.com

Runnerは様々な単位で登録出来るのですが今回はプロジェクトと直接紐づけたいと思います。
(ちなみに他には共有ランナー、グループ ランナーという単位があります)

まず、GitLabのプロジェクトRepositoryをブラウザで開きます。

次に左のサイドバー→設定→CI/CDを選びます。
(CI/CDの項目がない人は 設定→一般→CI/CDのToggleをオンに切り替える)

Runnerの項目を見ます。

そうしたら 1. で開いたパワーシェル画面で、

.\gitlab-runner-windows-amd64.exe register
を実行

そうするとURLを登録する旨が出てくるので、ブラウザのRunnnerのSpecific runnersというこうもくの 2. に表示されているURLを打ち込みます。
ちなみに今回はオンプレじゃないウェブサービスのGitLab使ってるので https://gitlab.com/ を入力。

次はtokenの入力を迫られるので、ブラウザに出ているtokenをコピペします。
ランナーの説明を入力します。
これはブラウザ側でも後で変えられるそうなのでテキトーに。

タグをつけろと言われますコチラもテキトーに(私はWindowsというタグにしました)

ランナーのメンテナンスメモの追加テキトーに

どの形式で実行するかを聞かれます。
今回は直接PCで実行したいので shell と入力します。

これでようやく登録完了です。

ブラウザを再起動すると追加したランナーが表示されているはずです。

3.実際にRunnerを使ってみる


今回用意したRunnerは specific runner と呼ばれるものになるのですが、実際に使うためにはyamlに追加記述が必要になります。

といっても tags の項目を追加し、どのランナーで起動するか指定するだけです。
タグなしで実行する方法もあるにはあるのですが、今回は割愛。

Window11の場合、コマンドを実行しても以下のようなエラーが出て実行できません。

Job failed (system failure): prepare environment: failed to start process: exec: "pwsh": executable file not found in %PATH%. Check https://docs.gitlab.com/runner/shells/index.html#shell-profile-loading for more information

理由は.Net版のパワーシェルPowerShell Coreが入っていないためです。
Windowsで使われている標準のPowerShellWindows PowerShellと呼ばれるものです。

.Net版のパワーシェルをダウンロードして解決しても良いのですが、Win11にあった挙動ではない可能性もあると考え今回はPathを修正する様にします。
Runnerのデフォルトシェルは、Windows OSに作成したRunnerフォルダーの下に自動作成されているファイル config.toml を編集することで変更できます。
(.\gitlab-runner-windows-amd64.exe installした時に生成されてるはず)

runners セクションにあるパラメーター shell を pwsh から cmd (全部小文字)に変更することで解決します。
(PowerShellでやっても良かったのですが、ymlの構文解析が一部上手く動かなかったので今回はcmdで対応)

プロセスをスタートします。

.\gitlab-runner-windows-amd64.exe start

動かしたら
今回は一旦build Testと表示させるだけのものを動かします。
リポジトリ直下に以下のようなファイルを作成。

.gitlab-ci.yml

stages:
  - build
prepare-job:
  stage: build
  tags:
    - Windows #Runnerでつけたタグ名
  script: 
    - echo "build Test"

ファイルをアップロードすると .gitlab-ci.yml が読み込まれ既に起動してあるCIが反応して実行されます。

一時停止マークが表示されて動かない場合

ランナーが上手く登録できてないかtagsの設定が間違っており、実行できるRunnerがない状態だと思われます。(もしくはジョブを待っているマシンがネットワークから切れたとか……?)

.\gitlab-runner-windows-amd64.exe restart

を行う、ウェブ側でtagの設定をし直すなどすれば直ると思います。

4.Unity側のスクリプト


コチラは通常のビルドスクリプトで大丈夫です。
以前↓の記事で紹介したJenkinsで使ったものを流用しようと思います。

orotiyamatano.hatenablog.com

今回もHTML5でのBuildのスクリプトです。

using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;

    public static class BuildScript
    {
        private static void Build()
        {
            bool isSuccess;
            const string path = "/../output";
            FolderCreate(Application.dataPath+path);

            PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.WebGL, "");
            // ビルド処理
            BuildPlayerOptions buildOption = new BuildPlayerOptions
            {
                options = BuildOptions.None,
                scenes = GetAllScenePaths(),
                target = BuildTarget.WebGL,
                locationPathName = Application.dataPath+path,
            };
            UnityEditor.Build.Reporting.BuildReport reports = BuildPipeline.BuildPlayer(buildOption);
            isSuccess = (reports.summary.result == UnityEditor.Build.Reporting.BuildResult.Succeeded);
            

            Debug.Log(Application.dataPath + path);
            Debug.Log("isSuccess:"+ isSuccess);
            EditorApplication.Exit(isSuccess ? 0 : 1);
            
        }

        /// <summary>
        /// 出力先フォルダ生成
        /// </summary>
        /// <param name="path"></param>
        private static void FolderCreate(string path)
        {
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
        }
        //GetAllScenePath
        private static string[] GetAllScenePaths()
        {
            var levels = EditorBuildSettings.scenes
                .Where(scene => scene.enabled)
                .Select(scene => scene.path)
                .ToArray();

            return levels;
        }


        [MenuItem("Build/Build Develop App")]
        private static void BuildApp()
        {
            Build();
        }
    }

↑のようなビルドスクリプトをエディターフォルダにいれてaddしてcommit・Pushします。

5.yml(ビルドパイプライン)の設定


まず、Buildを走らせるサーバーに同じバージョンのUnityをインストールしておきます。
そして、3で追加した、ymlを変更します。

.gitlab-ci.yml

stages:
  - build
prepare-job:
  stage: build
  tags:
    - Build #Runnerでつけたタグ名
  script: 
    - echo "build Test"
    - echo %UNITY_VERSION%
    - echo %CI_PROJECT_DIR%
    - chcp 65001 #そのままだとログが文字化けしてしまうので文字コード変える
    - '"C:\unity\%UNITY_VERSION%\Editor\Unity.exe" -quit -batchmode -projectPath %CI_PROJECT_DIR% -executeMethod BuildScript.Build -logFile -' #Unityのexeとプロジェクトのフォルダを選ぶ

UNITY_VERSIONは後から自由に変えられるように設定、CD/CIの変数にプロジェクトごとに変更します。

(ProjectSettingsフォルダのProjectVersion.txtの中身を見てきて自動的にUnityのダウンロードをするみたいなこともやろうと思えば出来るのですが、面倒だったので割愛)

変更し、PushするとBuildが走ります。
問題がなければエラーなく最後までBuildが行われるはずです。

+α 6. Slackへの通知


Slackから通知が受け取れるともっと楽になります。
SlackアプリとしてIncoming Webhookを追加し、ログを吐き出したいチャンネルを指定。
するとWebhook URLが出来上がるのでソレをコピーして、
GitLabのプロジェクトの設定→インテグレーション→Slack notificationsのWebhookに設定し変更を保存します。

するとログが出るようになるはずです。
また、SlackAppとしてGitLabを追加することで便利なコマンドも使えるようになるのでソチラも追加して置くと良いかも知れません。

+α 7. deployGateとの連携(理想)


暇があれば書きます。多分。知らんけど。

まとめ


以上で、GitLabRunner触ってみたを終わります。
Jenkinsより比較的設定が楽だった感じがします。
また、この仕組を利用すればUnity Test FrameworkやRoslynアナライザなどを使って詳しいテストをしてみるなど、
色々使用方法が広がりそうです。

GameSynth使ってみた

こんにちは、やまだたいし( やまだ たいし (@OrotiYamatano) / Twitter )です。
サウンド(SE)を作るツールGameSynthが使いこなせれば結構良さそうだと思ったので今回記事化しました。

目次


GameSynthとは


効果音生成ツールです。
様々なゲーム会社で使われています。

GameSynth ゲーム効果音生成ツール | Tsugi

39,000円ほどでお高めですが、効果音アセットを毎回買うよりは安く済みますし、
まれに40%OFFセールとか半額セールとかやってるので、安いときを狙って買うのがオススメ。

機能紹介


様々な機能があり、プロシージャル(自動的・自動生成的)にサウンドを生成可能です。
風を切るような音のWHOOSH、打撃音のIMPACT、機械的なボタン音を生成できるRETRO
他にも、いくつも音を生成出来る機能があります。

ツールの見た目的に目を惹くのはWHOOSHやFOOTSTEPSで、
買う人もソレを目当てで買う人が多いと思います。
WHOOSH↓
www.youtube.com

しかし、個人的に一番魅力的だと思う機能は、一見見た目が地味なMODULARです。
コレまで、サウンドを加工する場合、重ねがけするような形で適用し、更に加工ということをされている方が多いと思います。

このGameSynthのMODULARは、ノードベースでパズルを組み合わせるように音の加工が可能です。
むしろ、WHOOSHなどで作れる音もMODULARで製作可能で、ぶっちゃけMODULARさえあればこのツールは十分です。
サウンドに深い理解がない私のような方でも感覚的に音を加工することができます。

視覚的ではなく、英語なため遠慮してしまいたくなるMODULARですが、
中々面白いので、今回はコチラを紹介していこうと思います。


モジュールの使い方


モジュールの使い方の参考になる記事を作ろうとして資料などを集め書いていたのですが
正直ちゃんと、調べてみると意外と公式が充実していましたので、今回はソチラを紹介します……。


(ヘルプに沢山の資料がある)

モジュール周期表


www.tsugi-studio.com

コチラはモジュールの各ノードがどのような役割を果たしているかの一覧です。
音に詳しい方はコチラをみるだけでノードが作れてしまうかも知れません。

基本的なモジュールの使い方のPDF


http://www.tsugi-studio.com/Software/GameSynth/HelpCenter/221/Manuals/JP/Modular%20Reference%20(JP).pdf

公式の使い方PDFです。
これだけでは使いこなすのは少々不十分ですが、網羅されており参考になります。

サンプルとその作り方


www.tsugi-studio.com
www.tsugi-studio.com
www.tsugi-studio.com
www.tsugi-studio.com

公式の実装サンプルと、その作り方です。
これらをみればどのように作ればいいか一目瞭然です。

実際に作る時の手順


では、あなたが実際に新規に音を作ってみようと思ったとします。
私が↓作った例に簡単に手順を説明します。

1.公式の大量のサンプルを参考にする


公式には大量にサンプルがあります。
ツールのGetから参照出来るのですが、ノード以外も含めるとゆうに100は超えます。

私は紙をペラリとめくる音を作りたかったので、紆余曲折探りましたが、
結局公式サンプルから似たような音を探して来て探すのが一番です。

サンプルにてpaperで検索するといくつかサウンドが出てきました。


紙を破る音、紙を擦る音、風に吹かれる紙の音、紙コップが落ちる音。

2.サンプルの音を開く


風に吹かれる紙の音が一番近い音だったので、ソチラを開きました。
サンプルの音を開くとこのような、ノードが表示されました。


しかしながら、風に吹かれる紙の音は音が連続しており、私の要望のペラリとめくる音には程遠いです。

3.音を加工する


そこで、先ほど紹介した、モジュール周期表が役に立ちます。
モジュール周期表を参考にしながら、音がどのような構成になっているのか、
どのように加工すればそれっぽくなるのかがなんとなく掴めます。
何階か試行錯誤を重ね、最終的には以下(↓)のようなノードになりました。

終わり!
全然説明になってないように移るかも知れませんが、それほど手軽に音が出来てしまうのです。

まとめ


サウンドアセットを買うとなると大量に入ったサンプルは1万円ほどしたりします。
無料のアセットは音の品質も怪しいですし、ほかアセットと組み合わせるとなると音質の差が気になってしまいます。

高品質で一定の音を揃えたいのなら割と低価格で済み、自作なのでオリジナリティも出せます。
そう考えるとGameSynthはかなりの低コストです。セールの際にでも購入検討してみてください。

FMODでダッキングする

こんにちは、やまだたいし( やまだ たいし (@OrotiYamatano) / Twitter )です。
FMODシリーズです。
ダッキングの方法を毎回忘れてしまってググるので、今回は忘れないように書き留めて置こうと思い記事化しました。

目次


過去の記事


orotiyamatano.hatenablog.com

ダッキングとは?


かがめるという意味がありますが、
音楽ではメインの音声が鳴る際に他の音を絞って目立たせる事をいいます。

なぜダッキングが必要なのかというと、理由は2つだと私は考えます。

1.音割れが発生しやすくなってしまう

コンピューターが表現出来る音には限界があるのですが、音声を同時に鳴らした場合、「ビリビリビリ」とそのリミットを超えてしまうことが多々あります。
それを回避するためです。

2.入れた音が聞こえない

同時に音を鳴らしたらせっかく入れたSEやボイスが聞き取りづらくなってしまうことがあります。
BGMと鳴らしたい音源の周波数がかぶらないようにするという手段もありますが、簡単に回避できる方法としてダッキングがあげられます。

Unityで自前でダッキングを実装することも可能なのですが、ライブラリ側でやったほうが処理不可も少なく、ソースコードを汚染せずに済みます。

早速作っていく


今回は前までのFMODの最低限の操作を覚えた前提で記事を書いていきます。

バージョン


FMOD 2.01.07
Unity 2021.3.1f1
FMODプラグインバージョン:2.02.04

FMODStudioの設定


(何もない、まっさらな状態から開始)

まず、bank(バンク)を作っていきます。
右クリックしてBankをSEとBGM作成。
今回はBGMを鳴らしている間にSEを鳴らしてダッキングさせるものを作ります。

次にアセットの追加。
SEとBGMを追加します。

次にイベントを作ります。
今回は3D的に音声を配置しないので、2Dでそれぞれ作ります。

イベントに先程追加したSEとBGMをアサインします。

ミキサーの設定をしていきます。
まず、ミキサーウィンドウを開いて……。

グループを作ります。
グループには先程追加したイベントのSEとBGMをいれます。
(イベント名、分かりづらいので変えても良いかもしれないですね)
(今回は特段設定はしませんでしたが、グループは階層にも出来ます。マスターの下にぶら下がる形にすると音量調整のオプション画面も作りやすく非常に良いです)

次にダッキングさせるBGMにコンプレッサーを追加します。
コンプレッサーの設定はなんか適当に。
とりあえず、反応するThreshold(しきい値)の値だけ少しいじっています。

サイドチェインをSEに追加。
どのサウンドグループで音が鳴るとダッキングが起きるかの設定ですね。
サイドチェインをSEに追加したら先程のコンプレッサーにリンクさせます。

これで設定は完了です。
確認してみましょう。

イベントエディタでBGMを再生して、
新規ウィンドウで更にイベントエディタを開き、SEを再生した際にダッキングが働いているか確認します。

グループのコンプレッサーの反応あたりを確認すれば分かりやすいと思います。
後は通常通りプロジェクトをビルドして、Unityで再生させるだけです。

Unity側はプロジェクトをビルドさえすれば設定は勝手に引き継がれるので、特段設定をする必要なくただ再生すればダッキングが適用されます。

簡単ですね!

参考動画


www.youtube.com

まとめ


このように各イベントに対してグループを設定することですべてのSEにダッキングの設定が一括で行なえます。

もちろん、イベントごとに特殊な設定も行えますが、一括で設定したほうが色々と管理が楽だと思われます。
どちらにしてもビルドさえしてしまえば、SEの差し替えなどでプロジェクトのソースコードに影響を与えてしまうこともありません。
ダッキングの実装は意外と面倒なのでミドルウェアライブラリ導入してみてはいかがでしょうか?

【備忘録】ゲームUI入門した

こんにちは、やまだたいし( やまだ たいし (@OrotiYamatano) / Twitter )です。
UIを入門したいと思い学んだが、忘れてしまいそうだったので今回は学んだことの備忘録として残しておくことにした。

目次


なぜ?UIを勉強しようと思ったのか


それはゲームを作る上でUIを作るのは必須。
ゲーム制作だけにとどまらず、様々なものを作る上でUIはなくてはならないものだから。
作り方を理解していればもっとより良くスムーズにUIを作れるのではないかと思ったから。

そもそもUIとは


UIそれはUserInterfaceの略でシステムや機械と人間をやり取りするための手段のこと。
ここではUIデザインのことを略してUIと呼称する。

UXとは


UIと似たような言葉にUXという言葉があるが、こちらはUserExperienceの略。
ユーザーの体験のこと。似てるようで全然違う。ここではUXデザインのことを略してUXと呼称する。
UI=UXではないが、UIとUXは切っても切り離せない関係。
見た目が素晴らしいデザインでも体験が良くない、使い勝手が悪いUIというのは意外と多い。

アフォーダンス


環境の中にある情報のことをアフォーダンスという。
例えば、現在の日本人25歳ぐらい以上であればフロッピーのマークを見て、
「フロッピー」、「保存出来る」とアフォーダンスを知覚する。
しかし、25歳より下になると、よくわからないマークという認識になる。
人によって知覚されるアフォーダンスは違う。

25歳以上にも、25歳以下にも分かるようにする場合はどのようなマークが適切だろうか。
最近ではダウンロードを意味する以下(↓)のようなアイコンが一般的になりつつある。

このような誰にでも分かる適切な手がかりのことをシグニフィアというらしい。

制作フロー


UIを作る上で実際には順序というものが存在する。
個人制作、チーム制作どちらも変わらない。

1.素材が必要になる、要件確認


何かしらがあって、UIが必要になる。
ゲーム制作、Web、もしくは何かのアプリかもしれない。
そうした場合、使用用途に応じてデザイン的成約が生まれる。

例えば全年齢対象ならば、漢字は使えない。
海外対応もあるなら、英語や中国語などの複数パターン必要かもしれない。
文字を置き換えるならアラビア語はかなり長くなり、右揃えになる。
余白を多めに取ったり、レイアウトも気をつけなければならない。
はたまた、文字情報は含めずアイコンだけになるかもしれない。

スマホアプリならば規約を守る必要がある。
特にiPhoneは厳しいので事前にチェックしておくと良いだろう↓
developer.apple.com

筆者はノッチの部分のセーフエリアの背景は黒一色ではNGなど、リジェクトになってしまうデザインがありソチラでリジェクトを貰ったことがある。
現在はNGと明記されていないようだが、ガイドラインは更新されるため毎回チェックするのをおすすめしておく。

宣伝用のランディングページなら、スクロールした際にUIが動くようにしないといけないかもしれない。
デザインコンセプトが決められていたり、イチからデザインコンセプトを決める必要があったり……。

なんにしても前提条件の確認は必須だ。

今回はゲーム制作前提で進めていこうと思う。
ゲーム制作の場合、私が思う確認しておくことは以下の通りだ。

・すでにデザインコンセプトがあるか?
・ターゲットは誰か(日本人?小学生は含める?男性?女性?、色覚異常のチェックは必要?)
・ゲームの趣旨(例えば短時間でできるゲームを作りたい場合はゲーム早くアクセスでき、ゆっくりとしたUIアニメーションは適さない)
・今回満たしたいニーズは何か(その画面が何のために必要か、キャラが見栄えするメニュー?)
・動作環境や性能(解像度はいくつか、タップ重視かコントローラー入力か、フレームレートはいくつを担保するか)
・締切はいつか?

2.コンセプトを決める


決まっていない場合は、ターゲットや必要な要件から具体的なコンセプトを決める。
トンマナ(トーン&マナー)を決めてしまう。

例えば、スプラトゥーンでいえば、「イカ」と「スポーツ」をキーワードにして、
軟体、液体、ゆるい、太い、強い、明解、速さなどを言語化
更に、イメージを形に落とし込んだ。
careerhack.en-japan.com

チーム内に共有する場合参考画像があると分かりやすい。

3.素材集め


コンセプトが決まったら、素材集めだ。
ゲームであれば、ステージに合ったUIにしたい、世界観にあったUIにしたいという要望が出てくることが多い。
企画が素材を集める場合もある。
特にない場合、素材を集めて、デザインを事前に共有しておくと良いと私は思う。
(素材はチーム内だけにしか見せないのであれば版権画像を使用する場合もあるが、外部共有を考えると出来れば版権画像は避けたほうが好ましい)

私の身の回りではデザインの検索やイメージの共有にはPinterestを使ったり、既存のゲームUIであるゲームUIブログ、GameUIDatabaseなどを使うことが多いように感じるので以下でリンクを共有しておく。
www.pinterest.jp

gameui.matme.info

www.gameuidatabase.com

NGサンプルなど、似ているが、指定とは違うパターンなども用意すると良さそうだ。

4.ガイドラインの策定


UIでデザインをする場合、似通ったUIを使用することが多い。
またフォントなどもゲーム全体で統一する場合もある。
決めておくとよいだろう。

決めるべきことを雑多に下に書き出していこうと思う。

使用ツールやバージョンの決定(ツールバージョンによってデータ形式が変わってしまう可能性があるため)
納品データ形式やフォルダ格納ルール、レイヤー/ファイルの命名規則。解像度。テクスチャサイズルール

メインカラーコード、フォントカラー、テキストルール、フォントサイズパターン、
共通パーツデザイン:ポップアップ、リストビュー、アイコン、バック、バツ印など。
挙動ルール(ボタンをタップしたら彩度を落とす、カーソルフォーカス時はカーソルを明滅させるとか)
テキストメッセージはゲーム上で変更する場合もあるため、テクスチャにベイクするかどうかも相談しておいたほうが良さそうだ。
テキストウィンドウやボタンを9スライス形式で統一する場合もあるのでソチラの検討も必要だ。

他に、ポップアップは何層まで表示を許すか、
またレイヤー構成ルールなども用意しておくと便利かもしれない。
このあたりのレイアウト決めはCygamesが秀逸だった。

www.youtube.com

gamebiz.jp

責任者・承認フローを決める。
表示など形式がまずいのはエンジニアしかわからない
最終的なレイアウトがOKはプランナーやディレクター
表示崩れはデザイナーしかわからないbr>

各セクションでOKを出す承認フローを決めておきたい。

また、決まった内容についてはWikiなどの資料にまとめて誰でも見れる状態にするべきだろう。

5.プロトタイプを作ってみる


ルール決めたばかりで、いきなりUIをいざ作ると印象と違う、
こうして欲しいといった要望が出ることが少なくない。

また、この時点で良くないゲームフローについては口出ししてしまっても良いかもしれない。

作り込んでからやり直すとなると大変だ。
そのために軽く作ってからフィードバックを貰うのが賢明。
また、仮素材をエンジニアに渡しておくことで、デザイナーが本格的にUIを作っている間にエンジニアが先行して作業を進めることができる。
その後、本格的にAdobiXDでUIを作るプロジェクトもあるが、そこは要相談すると良いだろう。

↓プロトタイピングに使えるツール
www.adobe.com

www.figma.com

www.sketch.com

6.素材を作り込む


プロトタイプもGOが通ったら本格的にUIを作り込む。
ゲームUIではIllustratorで素材を作り、Photoshop詳細なUIを作る方が多い。
アニメーションがあるUIはエンジニア側が作るか、デザイナーが作るかは要相談。
デザイナーが作る場合は、Adobe After Effectsでサンプルを作る場合が多いように感じる。
もちろんUnityのエンジン上のAnimationツールで作る方も居る。

エンジニアにはPhotoshopのPSDを自動的にゲーム上UIに変換するツールをつくる人も居る。
(↓例) blog.applibot.co.jp

どのようなデータ形式で素材をアップロードするかは相談すると良いだろう。

7.Ta-da!完成!


最終的にデザイン監修が通って、エンジニアの実装も完了すれば終了だ。
エンジニア側でUI差分データが欲しいなど、要望があったりする場合もあるので、そこまで終了したら完了となる。


デザインの基礎


実際にデザインを作る上で、
基本原則がある。
古くから伝わるデザインには適用されていることが多い。
基本原則を覚えておくとデザインがしやすくなる。

レイアウト基礎


1.コントラスト(対照/対比)


違う要素の比較をする場合、似たような要素では互いに衝突してしまう。
「大人と大人」より「大人と子ども」で対比させた方やよりコントラストが強い。
似たような要素ではメリハリがなくなってしまう。
明示的に似せたいのでなければあえて、そういうことはしない方が好ましい。

2.接近


要素の関わりがあるものは近くに配置させるのが常套手段である。
わかりやすい例で言うと漫画のコマ割りなどであろう。

接近したものほど、関連性があるように感じられる。

3.整列


整列させることで統一感、まとまりを表すことが出来る。
中央揃えと右揃え2つを同じ画面やページで行うのは出来れば避けたい。

4.反復


繰り返しである。
ソーシャルゲームでもよく見る。
例えば↓が繰り返しだ。


(版権じゃない画像を用意したかったがめんどくさかった)
このような反復要素があれば一体感や一貫性を加えることが出来る。
ボタン内の文言が違っても同じサイズが揃った物を並べるのも、この反復の応用だ。

UIボタンの種類


UIのタップできるボタンには2パターンある。
タスク型とオブジェクト型だ。

1.タスク型


・やることを選ばせる
・UIが動詞(何がしたいか)→「削除」「参照」などの動詞
・何がしたいかから設定する
・やることが決まっているものについてはコチラのデザインが好ましい

例(ゆうちょのATM)

2.オブジェクト型


・オブジェクトを選ばせる
・UIが名詞(オブジェクト)→ゴミ箱フォルダなど
・ファイルや対象を選んでからどうするか決める。[名詞→動詞]
・概要から埋めるようなもの
・なにがどこの要素に含まれるのか整理が必要

例(イラストやの自動販売機)

基本的にはオブジェクト型の方が抽象的でUIとしては良いとされる。
例えばゲームで言うならキャラ一覧画面と、キャラの編成画面を別々で用意するよりも、
キャラ一覧機能からキャラ編成を出来るようにしてしまうのがふさわしい。

色の基礎


色は様々な色選びを擦ることで、大人向け、子供向けそういった印象を与える。
色選びは需要だ。

1.補色


カラーホイールの向かい側の色は補色の関係にある。
どちらかをメインカラーにした場合、もう一方はアクセントカラーにすることで効果を強く発揮する。

2.トライアド


均等に色を選んだ場合、それはトライアドと呼ぶ。
その中でも原色の色(赤黄青)はプライマリートライアドと呼ぶ。
ちなみにGoogleはこの3色の赤、黄、青を使った上で「緑」を追加している。
この緑には常識やルールにとらわれないという強いメッセージが込められているらしい。

3.スプリット・コンプリメント・トライアド


最初に補色関係で色を取得し、その横にずれた色を2つ取得する。
似たような色2つと補色カラーが生成出来る。

4.類似色


ホイール上で隣り合う色のことを類似色と呼ぶ。
親和性が高い。

素材の作り方


素材の作り方については今回詳しく解説しない。
というより作りたい似たUIを他ゲームから探してきて、真似ればよいだろう。
作り方自体は↓リンクのゲームUI演出やGoogleで「How To Making Game UI」などでググったりツール自体の使い方の動画を探せば沢山動画が出てくるはずだ。

gameanimation.info

hanasaqutto.com

個人的所感


1.スマホゲームではフラットデザインをあまり使わない?


最近はフラットデザインUIも増えてきたが、スマートフォンゲームではフラットUIをあまり使わないように思う。
理由としては背景が動き回るゲームでボタンがただの情報の表示なのかボタンなのか分かりづらいからだと思う。
WebUIを触ったことがある層が増えてきたため最近はフラットデザインも増えてきたように思うが、どこがタップできるか分かりづらく、デザインとして遊びが少ないフラットデザインはあまり使われない気がする。
もしフラットデザインを採用するなら決まったボタン、決まったレイアウトで表示することを心がけたい。

ちなみにコンシューマーの場合、選んでいる項目がハイライトされたりするため、気軽にフラットデザインを使うことも少なくなく感じる。

2.ゲームUIの難しいところ


UXとしては見やすく分かりやすいUIが好まれるが、ゲームUIでは「遊び」が求められる。
しかしながら「遊び」を数多く入れてしまうと使い勝手が悪くなってしまう。
今後、アニメーションするUIが増えてくると思う。
例えばペルソナ5↓だが、吹き出しやカーソルが常に動いている。
www.famitsu.com

こういったアーテスティックな側面が強いUIが求められるようになってくるのでは無いかと個人的には思う。

参考書籍


(アフィリンクではないので、やまだたいしに報酬入ってほしくない人も、気軽にクリックできるはずだ)

www.amazon.co.jp

オブジェクト指向UIデザイン──使いやすいソフトウェアの原理 WEB+DB PRESS plus | ソシオメディア株式会社, 上野 学, 藤井 幸多, 上野 学 | コンピュータ・IT | Kindleストア | Amazon

www.amazon.co.jp

www.amazon.co.jp

その他、オススメ書籍

絵には何が描かれているのか ──絵本から学ぶイメージとデザインの基本原則 | モリー・バング, 山本 貴光, 細谷 由依子 |本 | 通販 | Amazon

誰のためのデザイン? 増補・改訂版 ―認知科学者のデザイン原論 | D. A. ノーマン, 岡本明, 安村通晃, 伊賀聡一郎, 野島久雄 |本 | 通販 | Amazon

最短合格! 色彩検定2級・3級テキスト&問題集 第2版 | カラボ色大学 |本 | 通販 | Amazon

Amazon.co.jp: ロゴデザインの現場 事例で学ぶデザイン技法としてのブランディング eBook : 佐藤 浩二, 田中 雄一郎, 小野 圭介: 本

www.amazon.co.jp

まとめ


一旦私が学んだことや知っていることは、大体ここまでなので以上にしておく。
デザインのNGパターンやUXについては様々な書籍で語られている。
更に深いところに踏み込みたい場合、上のその他オススメ書籍の内容を読むと良いだろう。
特に私が紹介したUXの教科書は難しいが網羅的にUXの紹介をしており参考になるのでオススメだ。
他にゲームUIを作る上で参考になる情報があれば教えて欲しい。