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

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

【雑記】ゲーム制作進捗報告「W.T.」

先行上映

鬼滅の刃の先行上映を観に行ったら子供よりおばさんの集団が多くてビックリした皆さんこんにちは。舞台挨拶のライブビューイングが併映される回でしたが声優さん目当てなのでしょうか、体積多めなご婦人たちが劇場を埋めていてビックリしました。来週は上弦の鬼役の声優さん達の舞台挨拶もあるらしく「私、来週体調不良にならないかなぁ」という声がチラホラ聞こえてきたので、きっと来週もそういったご婦人たちで埋め尽くされるのでしょう。

 

Indie Game Connect2023

牛歩のような速度ながらもコツコツ制作を進めていた脱出ゲーム「W.T.」ですが、ようやく完成の兆しが見えてきたので思い切ってインディーゲームの展示会に応募しました。

www.konami.com

出展料は無料ながら応募多数だと抽選となるので出展できるかどうかは不明ですが、一応開催日までにはお客さんに遊んでもらって恥ずかしくないぐらいまで仕上げて、色々な準備をしていきたいと思っています。

 

プロモーション

Indie Game Connectの応募に際して3分程度のプロモーション動画が必要だったので、ここまで完成した箇所のダイジェストを動画にまとめてYoutubeに投稿しました。

Indie Game Connectの抽選に外れた場合、これを流す機会は少なくなると思うので怖いもの見たさ程度に是非ご覧ください。(別にホラー動画ではありません)

youtu.be

 

これからの予定

前回の進捗報告は去年の10月ぐらいでした。

www.karvan1230.com

そこから4か月経ち、現在では全5章中4章まで完成することができました。4章では上のプロモーション動画にあるように動きのあるパズルが多めで、ステージ構成も少し凝ったものになっています。

 

こういうパズルとか

 

こういう演出

 

本来ならこのまま第5章の制作に取り掛かるのですが、現状第三者によるテストが行えていない状況で最終章の制作に取り掛かっても、作者(私)が気付かない問題点等が放置されたままとなりそうなので、最終章の制作を一旦中断して、ここまで出来上がった部分のブラッシュアップに制作の時間を割こうかと思っています。

また、実際に遊んで頂いた方からのレビューも欲しいので、3月頭ぐらいに全5章中の2章までをふりーむ! に投稿し、それ以後に現在完成している4章までをアーリーアクセス版としてSteamでリリースする予定としています。

そして、最終章の制作はふりーむ!版、およびアーリーアクセス版からのユーザレビューをフィードバックする形で進めていこうと思います。

これら計画全てが思い通りにいくかはわかりません。特にふりーむ!やSteamにリリースしても思ったようにダウンロードされなかったり、レビューをもらえないかも、といった不安もあります。
それでもゲームを完成させるには前に進むしかないので、これから最終コーナーに向かってこれまで以上に気合を入れて制作に勤しんで行きたいと思います。

 

【ゲーム制作】ChatGPTを使ってゲーム内テキストを翻訳する

アパレル

あまり馴染みのないアパレルショップでズボンを購入して「他に何か御用はございませんか」と店員に言われたので手頃そうなニットに手を出したら以外に高額でそっと棚に戻した物価高が憎い皆さんこんにちは。ただのニットに五万オーバーとか手がでません、カシミヤでも入っているんか。「えー、五万円とか普通じゃん」と言える身分に早くなりたいものです。

 

ChatGPT

2022年11月にOpenAIという企業がリリースした「ChatGPT」は対話型のAIサービスで、キーワードを指定するだけで小説や脚本を書くだけでなく、プログラミングまで記述してくれるという事で今現在、IT界隈で非常に話題になっています。

openai.com

また「ChatGPT」では他AIサービスよりもより自然な会話が日本語でも行えるようで、その特徴を利用して日本語の文章を添削してもらうことも可能です。
日本語の文章が添削できるという事は、日本語から英語に翻訳した文章に対して「英語として不自然な翻訳となっていないか」や「日本語の文章と同じようなニュアンスの文章となっているか」等々も確認してもらえそうです。

これまでゲーム内のテキストはGoogle翻訳等を使って英訳した後、その文章を日本語に翻訳しなおして不自然な文章になっていないか確認を行い、原文を翻訳しやすい文章に修正するなどして対応を行っていましたが、ChatGPTを使えばその手間も省けるかもしれません。

 

アカウントの登録と使い方

最初にOpenAIのページにアクセスします。

ChatGPT: Optimizing Language Models for Dialogue

 

色々と文字が書かれたページが表示されますが、左下の「TRY CHATGPT」をクリックします。

 

次にアカウント登録の画面に遷移するので「Sign Up」をクリックし、GoogleやMicrosoftのアカウントを持っている場合はそのアカウントで登録します。
(別のアカウントにしたい場合は新規のカウントで登録が行えます。)

 

登録が完了するとChatGPT内で使用する名前を聞かれるので好きな名前を入力します。

 

この後、いくつかポップアップが表示されますが、全て『Next』で進んでしまって問題ありません。

 

最後まで進むと以下のような画面となります。
Slackや他のWebサービスのチャットのように、画面下にあるボックスにChatGPTへ質問したい内容を入力して、Enterキーを押して送信することでChatGPTと会話を行うことができます。

 

添削してもらう

早速、現在制作中のゲームで使用する英訳テキストについて添削してもらいました。
日本語の原文はこちらです。

 

これを、Google翻訳等使って英訳した文章に対して「不自然な箇所があれば教えてください」と尋ねてみます。

『文章全体に不自然な点はありません。』と回答をもらいました。

一瞬、”おぉ、問題なかった。Google翻訳もすごいなぁ”、と感心しかけたのですが、念のため、質問の文章を少し変えて「英語として不自然な箇所があれば教えてください」と尋ねてみると

なるほど、やはり『英語として』不自然な箇所が幾つかあったようです。

つまり、最初の"不自然な箇所はありません"という回答は、質問が日本語で行われているということで、ChatGPTの中で英語→日本語変換を行い不自然な箇所がないか、の返答らしく、英語として間違っているか尋ねる場合は、きちんと「英語として不自然な箇所を教えて」と正確に伝えないと意図を理解してもらえないようです。

 

翻訳してもらう

というわけでChatGPTへ先程と同じ原文を「以下の文章を英語に翻訳してください」とお願いしてみると、以下のように翻訳してもらえました。

前述の「英語として不自然な箇所」は改修されているようです。

次に原文が描いているの場面(数学科の講師R.D.が同じ研究室の講師W.T.へ手紙を送っている)についての説明も加えて英訳をお願いすると

おおむね同じような文章となりましたが、微妙に異なる英文となっている箇所も見受けられます。

なので、今度は異なる英訳となっている箇所について、そのニュアンスの違いについて説明をお願いしてみます。

なるほど、それぞれの文章では、個人として純粋に驚いているか、研究室への利益も含めて驚いているか、の違いがあるようです。

 

まとめ

ChatGPTを使うと解像度の高い翻訳が行えることが分かりました。
英語力が低い人間にはわかりずらいニュアンスの違いも細かく解説してもらえるので、おかしなローカライズも避けられそうです。
ただ、正確な回答を得るには質問を省略せず正確に伝える必要があることも分かりました。

  • ChatGPTに対する質問は意図を正確に伝える必要がある
  • 場面の説明も加えて翻訳してもらうことができる
  • 英語のニュアンスの違いついて確認することができる

現在ChatGPTは試行中の為、誰でも無料で使用することができます
ただ今後は有料化も検討されているようなので、使うなら今のうちかもしれません。

 

【Unity】Action型を利用してInvokeをラムダ式で記述する

寒波襲来

天気予報の「午前中は晴れますが午後からは景色が一変します」というアナウンスを余り信じていなかったけれど午後になると天気予報通りに景色が一変して天気予報のお姉さんに心の中で土下座した皆さんこんにちは。窓の外が一気に真っ白になって、あっという間に雪が積もっていきました。雪国以外では数センチの積雪でも交通機関は麻痺するので、こういう強烈な寒波は台風と同じレベルの脅威ですね。

 

忘れられたゲーム

エルデンリングが発売されてもう少しで一年経ちます。このゲームはそのクオリティもさることながら、ボリュームも一般のオープンワールドゲームを凌駕するほど膨大だったため、発売されてから数か月間はゲーム関連の各種雑誌やYoutube等々はエルデンリング一色となっていました。
この為、その間に発売されたゲームは例え出来が良いものでも余り話題に上らず、そのまま忘れられていく運命となったものが数多くありました。
忘れられた都市 - The Forgotten City』もそうした不幸な運命を辿ったゲームの一つだと言えます。

 

store.steampowered.com

 

元ネタはスカイリムの有名なMODであまりに好評だった為、独立したゲームとしてリメイク仕直したというこのゲーム。
ジャンルは一人称視点のアドベンチャーゲームで、探索や謎解き、キャラクターとの会話がメインですが、一部アクションゲームの要素もあります。

古代ローマ時代の小さな都市に迷い込んだ現代人が、なんとか元の時代へ戻る方法を探そうとしますが、その都市は「黄金律」と呼ばれる恐ろしい規律によって縛られた閉鎖都市で、その呪縛を解かない限りに現代へは戻ることができない、主人公はこの「黄金律」の規律を侵さずに、その呪縛の謎へ迫っていく・・・といったストーリー。

このミステリーに対する謎解きに加えて、「Outer Wilds」や「Twelve Minutes」のようなタイムリープの要素も加わって非常にやりごたえのあるゲームとなっています。
マルチエンディング形式で世界的な脚本家組合賞も受賞したストーリーは本当に秀逸です。
大団円の真エンディングはご都合主義ながら全ての謎が解け、スッキリと晴れやかな気持ちになると思います。初見の人は、先ずは何も見ずに遊んで欲しいゲームです。

 

Action型

ゲームに限らず色々なシステム開発で、とあるクラスの処理終了を待ってから処理を行いたい、というケースはよく直面しますが、UnityではそういうケースではDelegateを使用することが多いです。

Delegateは一言でいうと「メソッドを代入できる」型です。

「メソッドを代入できる」とは正確には関数が保存されているアドレスを指すポインタを保持する、という意味で、要はこれを使えばコールバック(Callback)という仕組みが実現できるようになります。

 

例えば下の図のようなカウントタイマーがあり、その終了によって右側の文字盤の文字を変更したい場合、

カウントタイマー側のクラスにdelegate型の変数を定義します。

public class CountDownTimer : MonoBehaviour
{
   public delegate void OnCompleteDelegate();	// delegate 型の宣言
   public OnCompleteDelegate CompleteHandler;	// delegate 型の変数を宣言

   public void RegistDelegateFunc(OnCompleteDelegate argCall)
   {
       CompleteHandler += argCall;		// メソッドを代入
   }

   private void Complete_CountDown()
   {
       CompleteHandler?.Inovke();	// コールバックを実行
   }
}

 

文字盤側のクラスではCountDownTimerクラスのRegistDelegateFuncにてカウント終了のコールバックを受け取る関数を指定することで、カウントタイマーの終了時に文字盤の文字変更の処理を行うことができます。

public class WordBoard : MonoBehaviour
{
    public CountDownTimer _timerCtl;
    
    void Start()
    {
        // コールバックを指定する
        _timerCtl.RegistDelegateFunc(()=>CallBack_Timer());
    }
    
    public void CallBack_Timer()
    {
        // 文字盤の文字を変える
    }
}

 

上記の仕組みを実装して動作させた結果が以下の動画となります。

Action型(System.Action)とはこのDelegate型から派生した型の一つになります。

 

Action型の使い方

Action型(System.Action)はDelegate型から派生した型であるため、Delegate型と同様の使い方で使用しますが、Action型はDelegate型とは違い、型宣言を行う必要がありません。型の定義と変数宣言を一度に行うことができます。
なので、先ほどのCountDownTimerクラスのソースはAction型を使うと以下のように変更する事が出来ます。

public Action OnCompleteAction; // Action型の変数宣言

public void RegistActionFunc(Action argCall)
{
    OnCompleteAction += argCall;		// メソッドを代入
}

private void Complete_CountDown()
{
	OnCompleteAction?.Inovke();
}

 

最初の二行が一行になっていることがわかると思います。型宣言がないため、Actionでは戻り値を定義できません引数はAction<string, int, ....>のように<> の中に型を列挙することで指定することができます。

 

Action型の仕様を利用する

例えば先程のカウントタイマーと文字盤のシステムで

上の動画のようにタイマーの文字盤が変わると「少し遅れて」背景の色を変更する、という処理を行いたい場合、通常はカウントタイマーの文字盤が変わったタイミングでBackgroundColorを変える処理をInvokeを使って呼び出します。

public class CountDownTimer : MonoBehaviour
{
    List<Color> _skyboxColorList;    // 背景色のリスト
    int _colorIndex = 0;                 // リストのIndex

    // 文字盤が変わったときに呼ばれる関数
    public void  ChangedTimer()
    {
        // BackgroundColorを変える関数を0.2秒後に呼び出す
        this.Invoke("ChangeSkyColor", 0.2f);
    }
    
    // BackgroundColorを変える
    private void ChangeSkyColor()
    {
         _colorIndex++;
         Camera.main.backgroundColor = _skyboxColorList[_colorIndex];
    }
}

 

Invokeは実行する関数を関数名(string型)で指定するので、必ず関数定義が必要となり、その為、2,3行程度の短い処理でも関数化する必要がありました。

前述のようにAction型では変数宣言のみで使用することができるため、この仕様を利用すると「Actionデリゲート → ラムダ式」のように間接的な関係を作って関数名指定の箇所をラムダ式で記述することができます

this.Invoke(new Action(() => {
    _colorIndex++;
    Camera.main.backgroundColor = _skyboxColorList[ColorIndex];

}).Method.Name, 0.2f);

 

まぁ、コーディングの作業量が減る程度の効果しかありませんがTipsとして知っておけば自慢できる・・・かも。

【はてなブログ】Unityアフィリエイトプログラムの参加と、はてなブログでの設定について

機種変更

機種変更でスマホをキャリアから初めて購入したら余計なアプリや無駄な通知が多くて購入早々ウンザリしている皆さんこんにちは。使う気のしない〇〇サービスやら配信アプリやら一々アンインストールするのも面倒くさいです。やっぱり直接メーカーから白ロムを購入するのが一番ですね。

 

黒ファントム

そういえば年末年始休暇中に購入したデモンズソウルですが、各エリアのボス(デーモン)よりエリア傾向最黒の時に登場する黒ファントムの方が格段に強くて衝撃です。中ボスですらないユニークNPCがここまで強いとかこの仕様を決めた人は何を思ってこう決めたのでしょうか?
やたら固くてほぼワンパンで殺されるのでデーモンよりも黒ファントムを倒す方が時間が掛かります。PS5をお持ちで未だ体験されていない方は、ぜひ購入して体験してみてください。
コントローラーを投げて壊しそうになります。

 

Unityアフィリエイトプログラム

このブログを始めてから幾年か経ちますが、これまでUnityのアフィリエイトプログラムには参加していませんでした。
UnityアフィリエイトプログラムとはブログやSNSでUnity Asset Storeのアセットを紹介して、そのアセットの購入が成立した場合に報酬(価格の5%)が発生するプログラムです。

unity.com

ブログ開始当初はこのブログを自作ゲームの進捗やらゲーム開発中に学んだUnityについての情報を共有することを目的に記事を書いていたのでアフィリエイトには興味が無かったのですが、時が経つにつれてネタの枯渇と共に購入アセットの紹介記事が増えているので、新年を迎えたタイミングで参加することにしました。

 

参加手順

上記のURLにアクセスします。
Unityアフィリエイトプログラムの題字の左の下にある「今すぐ申し込む」をクリックします。

 

サインアップページが表示されるので名前、パスワード等々を入力して「Continue」をクリックします。

 

画面左上のLanguageのプルダウンを「日本語」に変更すれば、日本語で各項目が表示されます。

 

最後のページでアセット紹介を行うウェブサイトのURLを求められるので、ブログのURLを入力します。

 

最後まで入力し終えて「サインアップ」をクリックすると申請完了の画面に飛びます。

 

するとほぼ同時に申請を確認した旨のメールが届きます。申請内容について審査があり、5営業日以内に返信があることを知らされます。

私の場合は2日ぐらいで申請が承認され参加OKとなりました。

 

はてなブログでの設定

申請承認メールには文中に「アフィリエイト・トークン」の記述と共にIDが記載されています。

このID(Affiliate ID)をアセットへのリンクに付与することで、アフィリエイトの計測が行われる仕組みとなっています。

 

アフィリエイト用のURLはアセットのURLの末尾に「?aid=発行されたID」を設定するだけも良いのですが、はてなブログで記載する場合にはバナーとして表示した方が見栄えが良いと思います。
バナーの作成はアセットストアのリンクメーカーを使うと簡単に作成できます。

assetstore.unity.com

上記のサイトにアクセスすると先頭にAffiliate IDの入力があり、その下に検索用の入力フィールドがあることが分かります。
このページで行うアフィリエイトリンクの作成手順は以下の通りです。

  1. Affiliate IDのフィールドにUnityから発行された「アフィリエイト・トークン」のIDを入力する
  2. 宣伝したいアセットを検索
  3. 検索結果の中からアセットを選択し、「Create Link」のボタンをクリックする

 

すると選択したアセットのバナー候補が表示された画面に遷移するので、その中からブログで表示したいバナーを選択します。

バナーを選択すると画面下にそのバナーのHTMLタグが表示されているので、これをコピーしてはてなブログの「HTML編集」タブで直接貼り付けます。

 

するとアフィリエイトリンクが貼られたバナーがブログ内に表示されます。

 

収益化の確認

アフィリエイトプログラムへの申請を確認した旨のメールに、収益化を確認するためのダッシュボードへのURLが記載されています。

そちらからアクセスして収益と報酬について確認することができます。

 

【Unity】色の三属性(色相・彩度・明度)を使った画面造り

年始の挨拶

「新年明けましておめでとうございます。今年もよろしくお願いいたします。」と年始の挨拶がいい加減億劫な皆さんこんにちは。社会人になると学生のような一年毎の大きな変化がないので年の節目とか結構どうでも良いのですが、この挨拶だけは毎年同調圧力の下で強いられます。
年始といっても一週間ぐらいの休暇期間が開けただけなのに、顔を合わせる度に同じ挨拶をしなければならないのは非常に面倒くさい。これって日本だけなのでしょうか。海外ではどうなんでしょうね?

 

デモンズソウル

年末にPS5が購入できたものの、あまりに遊ぶゲームがないので懐かしさも手伝ってPS5版デモンズソウルを購入しました。

気が付くとPS3版の発売から13,4年も経つみたいですが、さすがに全てのソウルシリーズの祖というだけあって今プレイしても遊びごたえのあるゲームだと思います。
当時は苦戦したデーモン達が以外にあっさり倒せたり、逆に金目黒骸骨や黒ファントムに苦戦したり、とPS3版を懐かしい気持ちで振り返りながら楽しむことが出来ました。
PS3版より画面が美麗になった分、ホラー感は減りましたが(PS3版では怖かったラトリア1がちっとも怖くない)リアルな画質で迫力があるし、最近のソウルシリーズにはない仕様(ソウル傾向等)は初め遊ぶ方には新鮮で面白いと感じるのではないでしょうか。

 

色相・彩度・明度

技術畑の私にとって色を決定する要素と言えば光の3原色(RGB)のみで、それ以外の要素に関してはあまり意識していませんでした。
でずがデザイン方面では色はRGBではなく色相・彩度・明度の尺度(色の三属性)で測るのが基本のようです。
色相・彩度・明度の三属性はそれぞれ「H(Hue)=色相」「S(Saturation)=彩度」「V(Value)=明度」の文字で表現され、色を決定するツールではRGBと合わせて画面上に表示されていることが多いです。

 

このうち色相はわかりやすくて、赤・黄・緑・青のように、色を特徴づける色みのことで色相環と呼ばれる色相を円上に配置したものを使って表現されます。

 

彩度明度はそれぞれ「色の鮮やかさ」と「色の明るさ」の尺度を指すのですが、言葉で説明するのは少しわかりづらい為、光の三原色(RGB)とその混色に対して彩度と明度を段階的に変えた表を下に作ったので、これを参照してイメージを掴んでください。

 

彩度・明度を変えた奥行表現

先程のカラー表から彩度と明度を変更すると、色みを保ったまま色の濃淡や明るさを変えられるという事がわかると思います。
この性質が画面作りにどのように利用できるかというと、例えば下のような山間部を表現した画面の場合、

山の部分は奥行に関係なく同じ色のマテリアルで作られているため、最奥にある山でも近くに感じる画面となっています。

これを奥行に応じて彩度・明度を変えた色のマテリアルを配置するようにしてみます。

具体的には奥に行くほど彩度が低くて明度は高くなるように、手間は逆に彩度が高くて明度が低い色を配置します。色相は変更しません。
そうすると

元の画面と比べると画面に奥行きが出るようになったと思います。

次にこの彩度・明度の関係を保ったまま、今度は色相を変えてみます。
インパクトを出すために一か所の色相を大きく変えて、合わせてSkyBoxも変更すると個性的な画面が出来ると思います。

 

彩度・明度の違いによる季節の表現

彩度の高低と明度の高低はそれぞれの組み合わせて四季を表現するグループに分けることができます。

実際にこのグループを使うとどのくらい違いが出るのか検証してみました。
箱庭的なモデルが欲しかったので下のアセットに付属していたサンプルを使いました。

このアセットのWorld - Tropicalというプレハブを使います。

このモデルに使わているマテリアルの色をすべて夏のグループ(高明度&低彩度)に沿った色のマテリアルに変更します。

 

かなり夏感が増した画面になりました。

 

次にWorld - Forrestというプレハブに対して

冬のグループ(低明度&高彩度)に沿った色のマテリアルに変更します。

 

冬の訪れを感じる画面になったと思います。

 

まとめ

色は色相・彩度・明度の尺度で考えると以下の表現が簡便に行えることがわかりました。

  • 低彩度高明度=奥、高彩度低明度=手前で奥行表現
  • 彩度・明度の違いによる季節感の表現

また、色相を同じにすると画面に統一感が出て、逆に一部を大きく変えると個性的な画面となることが分かりました。
今後はこれらのことを考慮して画面造りに励んでいきたいと思います。

 

【Unity】公式サンプルプロジェクトから学ぶデザインパターン:MVP

PS5

とっくの昔に忘れていたAmazonの招待リクエストに当選していまい年末の金欠の中でPS5を購入した皆さんこんにちは。「せっかく(当選したの)だから」と貯金をはたいて購入しましたが、PS4と比べてグラフィック性能がアップした実感は未だ感じていません。あとデカい。想像以上にデカくて置き場に困ります。これから購入される方はちゃんと置き場を確保してから購入した方が良いでしょう。

 

福岡インディーゲームエクスポ

前回の記事でも紹介通り、12/17に福岡でインディーゲームの展示イベント「福岡インディーゲームエクスポ」が開催されました。

www.fukuoka-indiegame.com

当日は生憎の雨模様で、かつ真冬日だったのですが、それでも会場はお客さんが多くてほとんどのゲームの試遊が順番待ちの状態でした。

スマホ向けのハイパーカジュアルからPC向けの本格的なアクション、ストラテジーゲームまで幅広いゲームが展示されており、私もできるだけ多くのブースを回って試遊したのですが、人の列が全然途切れなかった為プレイできなかったゲームも幾つかありました。

出展者の方も試遊している私の横で熱心にゲームの説明をして下さる方から、全くリアクションの無い方まで様々でしたが地元の福岡でもインディーゲーム界隈が盛り上がっていることを感じられてとても有意義なイベントだったと思います。
もし来年も開催されるなら今度は出展者として参加したいですね。

 

最終回

長らく続けてきたデザインパターンに関する連載も今回で最終回です。

github.com

www.karvan1230.com

www.karvan1230.com

www.karvan1230.com

www.karvan1230.com

www.karvan1230.com

www.karvan1230.com

www.karvan1230.com

 

MVPパターン

MVPパターンとは、システムの処理をロジック(Model)、表示(View)、中継(Presenter)という役割にそれぞれ分割して実装する設計思想のことを指します。

同じようなパターンでMVCやらMVVMといったものもありますが、これらはデータの流れやアクションの呼び出し方が異なるぐらいで、表示とビジネスロジックを分離してそれぞれが役割を受け持つ設計思想の根本はMVPパターンと同じです。
このパターンは業務系のシステムでは広く用いられていて、このパターンをベースにした独自のフレームワークによる開発案件も多く見かけます。

例えば、とある商品の販売に関してお客の要望に応じたカスタマイズを行う場合、商品の概要説明をお客向けに行う販売担当者(View)はお客からの要望をあずかると、本社の管理部(Presenter)にその要望を伝えます。
管理部(Presenter)は商品設計を行っている設計者(Model)に連絡し、設計者(Model)はその要望を取り入れてカスタマイズした結果を管理部(Presenter)に返信。
管理部(Presenter)はカスタマイズ内容を販売担当者(View)に伝え、販売担当者(View)はそれを受けて再度お客に向けてカスタマイズされた商品の説明を行います。

ここで重要なことは販売担当者(View)と設計者(Model)は互いの存在を認識せず、それぞれの仕事に注力しているという点です。
また管理部(Presenter)は間を取り持ちますが、取り持つだけで独自の判断やロジックを持ちません。
つまりそれぞれ互い(View,Model,Presenter)のコンポーネントは疎結合状態となっており、これによりテスト容易性や可読性が向上されていると言えます。

 

サンプルシーン

このデザインパターンのサンプルシーンを実行すると以下のような動作が見られます。

画面中央の的に対してクリックすると、それに応じて下のメーターが短くなっていきます。リセットボタンをクリックすると元に戻ります。
メーターの長さは内部で保持しているHealth値に応じて決まり、Health値が大きいほど長く、小さいほど短くなります。

このシーンのシステムを先程のMVPパターンに当てはめてみると

  • View:クリックイベントの受信、メーターの表示更新
  • Model:Health値の増減処理
  • Presenter:ViewとModelの間を取り持つ

上記のような役割分担となります。

一般的なシステムの場合、View、Model、Presenterはそれぞれでクラスを作成しますが、このシーンではメーターにはUnity標準のSliderコンポーネントを使用しており、メーターの表示更新はPresenter役のHealthPresenterクラス内でSliderコンポーネントにHealth値を直接渡すことで行われているので、標準的なMVPパターンとは少し実装方法のイメージが異なると思います。

サンプルシーン内の各クラスの役割と処理の流れを以下に記します。

 

まとめ

MVPパターンとはシステムの処理を「ロジック(Model)、表示(View)、中継(Presenter)」という役割に分割するパターンです。

これによりテスト容易性や可読性が向上されます。

ただ、Unityでこのパターンを採用する必要性はそこまで・・・
(基本的にスクリプトはMonoBehaviourを継承してオブジェクトにアッタチする形式なので、ViewとPresenterに分ける必要がない)

 

最後に

デザインパターンとはオブジェクト指向のプログラミング言語を採用するシステムにおいて品質や開発効率を高めることを目的として考案された設計思想です。

昨今ではあまり必須というわけでもありませんが、基礎的な知識として学んでおくことは損になりません。
公式のサンプルプロジェクトを通じて各種デザインパターンの具体的な内容とUnityでの採用例を学習することができました。
ネット上では各デザインパターンについて色々な解説を読むことができますが、実際に適用されたシーンを触ることはそれよりも学習効果が大きいのではないでしょうか。

もし、この掲載を通じてUnityによるゲーム設計のスキル向上に繋がっていれば幸いです。長い連載でしたがお付き合いありがとうございました。

 

丁度切りが良いので今年のブログ更新は今回で最後にします。
年明けからは通常の内容で更新しますので、来年もよろしくお願いします。

 

それでは良いお年を!

来年こそはゲームをリリースするぞ!

 

【Unity】公式サンプルプロジェクトから学ぶデザインパターン:Observer

福岡インディーゲームエキスポ

12月17日に開催される福岡インディーゲームエキスポが待ち遠しい皆さんこんにちは。インディーゲームに関する展示会は既に幾つかで行われていますが、開催地が関東関西方面ばかりだったので九州の人間にとっては縁遠い存在でした。しかし、地元で開催されるという事でこれまで触れる機会が無かった国産インディーゲームを体験でき、開発者さんとも交流できるという事で今から楽しみで仕方ありません。

www.fukuoka-indiegame.com


私自身は今回の出展は見合わせたのですが、地元九州を中心に様々な開発者・チームが出展しているという事で昨今のインディーゲームの盛り上がりに興味のある方は会場を覗いてみてはどうでしょう?

 

全てが絵になるゲーム

ずっと以前から注目していたのですが、ようやく日本語化対応されたとの事で購入しました。

store.steampowered.com

砂漠の大地をホバーバイクで旅するアドベンチャーゲームで、バンド・デシネ風の絵作りが印象的なこのゲーム。
主人公Sableは部族の掟として独り部族を離れて旅に出る。旅の目的は「一生の生業を決めるため」、この世界の人間は皆が生業を象徴する仮面をかぶっており、その生業はこの旅を終えた後に決定する。
Sableは砂漠の世界を旅しながら様々な人と出会い、彼ら彼女らの依頼をこなし手助けをしながら自分の生業とは何かを考えていく。
といったストーリーを進めて行くアドベンチャーゲームなのですが、このゲームのウリはなんといってもその圧倒的な芸術性の高さで、ゲーム内のどの場面を切り取っても一枚のイラストが出来上がると思えるほど。

探索とパズルのような謎解きがメインとなっており、戦闘やサバイバルなどの要素は一切ありません。この為、人によってはゲーム内容が退屈に思えるかもしれませんが、ホバーバイクによる疾走、高所からのグライダー移動、スタミナが許す限り壁を上ることができるなど、異世界を自由気ままに旅する、異世界の建造物を思うままに探索する、といった楽しみ方に注視すれば十分なクオリティにあると思います。
目的を達成する為の手順、方法を楽しむことより世界観に浸れることを重視する雰囲気ゲームって今後もインディー界隈中心に増えていくのではないでしょうか。私もいつかこのようなゲームを作ってみたいものです。

 

デザインパターン

さてさて、Unity公式から公開されているデザインパターン学習用のサンプルプロジェクトについての記事、今回で7回目になるでしょうか。

github.com

結構長い連載となりますが、ようやく終わりが見えてきました。

www.karvan1230.com

www.karvan1230.com

www.karvan1230.com

www.karvan1230.com

www.karvan1230.com

www.karvan1230.com

 

Observerパターン

Observerパターンとはシステム内の、あるクラスで起こったイベント(事象)を他のクラスが感知して、その後の処理を行う事を目的としたデザインパターンです。

出版-購読型モデルとも呼ばれることもあり、UnityではUniRxがこのデザインパターンの設計思想を具現化して、より使いやすい形に纏められています。

 

例えば、子供がお使いを頼まれてスーパーマーケットに出かける場合、何もしなければスーパーマーケットにたどり着いたとしても、行列が出来ていた等々の理由により目的の商品が品切れになっているケースも考えられます。

 

この為、事前に「子供がお使いに出かける」ことを察した親(=Subject)が事前にスーパーマーケット(=Observer)にお使いの内容を通知して、スーパーマーケット(=Observer)は子供が到着する前に目的の商品を準備しておきます。そうすることで「子供のお使い」はスムーズに目的を達成する事ができます。

つまり、Observerパターンを導入することで「出発」→「到着」→「購入」のシーケンシャルな動作と並行して「準備」の処理を非同期で行うことが可能となるわけです。
また、「準備」を行うのは一つのスーパーマーケットに限らず、複数の店舗で行うことも可能となります。

 

サンプルシーン

このデザインパターンの基本は、イベントを通知される側(=Observer)のクラスインスタンスを、通知する側(=Subject)のクラスインスタンスに登録することにあります。

サンプルシーンではSubject側のアイコンをクリックすると、Subject側アイコンのアニメーションと同時にObserver側のスピーカーからパーティクルが再生され、(GIFなので音がでないけど)音声も流れることが確認できます。

 

この「アイコンのアニメーション」「パーティクル再生」「音声鳴動」はそれぞれObserverのクラスとして実装されており、各クラスのAwake(起動時に呼ばれる関数)内にてSubjectクラスの定義済デリゲート(Action)のClickedイベントに各クラスのイベント受信時処理(OnThingHappend)を登録しています。

Subject側のアイコンをクリックすると、Subjectクラスにて定義済デリゲート(Action)のInvokeコールしてAwakeで登録された各Observerクラスのイベント受信時処理が呼び出されていますInvokeはNULL許容型でコールされている事に注意が必要です。

 

まとめ

Observerパターンとは通知側(=Subject)と観察側(=Observer)の2つの役割が存在し、SubjectからObserverに通知されるデザインパターンです。

通常はObserver側のインスタンスをSubject側に登録することで通知を可能としています。

サンプルシーンでは定義済デリゲート(Action)を使い、Invokeコールで通知を行っています。

 

◇プライバシーポリシー

●個人情報の利用目的

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

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

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

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

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

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

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

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

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

●免責事項

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

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

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

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

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

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