ゲームジャムでUnreal Engine 4を使ってみよう

ごあいさつ

はじめまして、セガ・インタラクティブ 第三研究開発部の若井です。アーケードゲームのプログラマーをしています。携わったタイトルはえ~でる すなばWCCF FOOTISTA 2019 などです。Unreal Engine 4 (以下UE4)の活動としては昨年の「UNREAL FEST EAST 2019」にてWCCFシリーズのUE4移行について発表いたしました。スライド(リンク先の説明欄より、動画と台本付きの資料をダウンロードしてください。)

記事の対象

今回はゲームジャム(文章中は「ジャム」と略します)の定義を、会場へ集まって1、2日で制作するものから期間1ヶ月程度までのコンテストとします。期間が長いものは当てはまりません。当てはまらない例:期間が10年もあるジャム

また、記事内容はジャム特化の内容となっておりますので、製品開発に必ずしも役立つものではない(技術的負債になりえる)ことをご了承ください。

記事のモチベーション

今回は私がUE4を使用したジャムで実際に活用したノウハウの内、他のジャムにも転用できそうなものをご紹介します。全体の話もしますが、主にプログラマー向けの初歩的なものが多いです。

ジャムでは結果よりもプロセスを楽しむことや経験することが重要であります。とはよく言われるものの、躓きが多いと楽しくない印象で終わることもあります。記事内のコンテンツで皆さんのジャムを快いものにすることができれば幸いです。

f:id:sgtech:20200126210259g:plain思惑と違ってしまうジャムもしばしば

おまけで記事の末尾にこれまでに制作したジャム作品を羅列しておきました。

ジャム当日までの準備

前日の十分な睡眠の他に、開発環境など事前に用意できるものがあります。

開発PCや実行環境

UE4を用いた開発PCについて、公式の推奨環境があります。会場に集まるジャムの場合はノートPCを持ち込むことになります。ご自身のノートPCスペックを確認してみてください。ジャムの会場によってはPCの貸し出しを行っている場合があります。

経験上UE4を使用する場合は3Dゲームを作ることが多いので、グラフィックカードの搭載された「ゲーミングノートPC」を持ち込むことをおすすめします(プログラマーの場合は特に必須)。

ノートPCの例

私はMSIのノートPCを愛用しています。冷却性能が優れておりジャム中に安定稼働しています。MSIさんのPRではございませんが製品名を挙げさせていただきます。各PCのスペックを参考にしてください。

・PS63 Modern

ジャムに持ち込んだときにゲーミングノートPCとしての役割を持てます。コンパクトでバッテリーも多いので、ジャム以外にも長めの勉強会などでメモ取り用として持っていける機種です。スペックとしては最低限で、2日程度の期間内でも処理負荷が大きいとゲーム開発中のカクつきが見受けられます。

・GE75 Raider

スリムでありながらVRゲームの開発にも対応できます。MSIのノートPCにはボタン1つでクーラー出力が最大(プロファイルの変更)となる機種があり、私はこのボタンをとても気に入っています。

スペックが低い環境の極端な例

おまけの④では、コンパクト性のためシングルボードコンピュータ (Latte Panda)上でアプリケーションを動作させました。デフォルトの状態では処理速度が追いつかなかったため、ジャム中にゲームのプロファイリングをして重い処理を取り除いていく必要がありました。おすすめしません。

f:id:sgtech:20200126210128p:plain←FlyingTemplateで10FPS

マウスを使用する(重要)

テンプレートを使用したゲームではカメラ視点操作をマウスで行ったほうが楽な事が多々ありますので、用意しましょう。

ビジュアルスクリプト「Blueprint」を使って開発することになります。慣れた操作でBlueprintノードを組み立てるためにノートPCと一緒にマウスを持ち込みましょう。

特にプログラマーは短時間で大量のBlueprintノードを操作すると腕が痛くなります。湿布を用意するか軽いマウスを使用することをおすすめします。

↓ ノードの総量はこのグラフ(おまけの⑩のBlueprint)くらいの量になるのではないでしょうか。ジャム中は試行錯誤でノードの作成と移動、ワイヤー接続と切断を繰り返しますので、グラフの見た目以上に手を動かすことになります。

f:id:sgtech:20200126210317j:plain

おまけの⑩では、制作時のグラフ切り替えやクラス間の画面切り替え時間を減らすためにほぼ1つのグラフに処理が集約されています。

仕事では書かないグラフなので見せるのはちょっと恥ずかしいです。

USBメモリ

どのジャムでも、素材やプロジェクトを共有するための手段が必要になります。1人1つUSBメモリを持っておくのが吉です。

共有ドライブが整備されたジャムもありますが、多くの会場では貧弱な無線環境ですのでUSBメモリのほうが共有しやすいです。

チーム内の数が少ないとUSBメモリ使用のための待ち時間が発生することがあります。発生したことがあります。

コントローラ

XInput形式のものを持ち込む

UE4は標準でXInputに対応しており、UE4のテンプレートは最初からキャラクターやカメラ操作のインプットアクションがアサインされています。

ジャムで制作するゲームはXboxコントローラのようなインターフェースが適することが多く、キーボードが必須であるアイデアは稀です。

持っている人は持ち込んでみましょう。

f:id:sgtech:20200126210552j:plain

年季の入ったコントローラや自作のアーケードコントローラ

お気に入りのコントローラを持っていて、ジャムで使用したくなることがあります。しかしXInputに対応していないことがあります。

UE4はDirectInput形式に対応しておらず、実際にUSBで繋げてみたがUE4のゲームで認識されない場合は概ねこちらが原因でしょう。

DirectInput形式はXInputより古い形式であり、UE4で扱うにはコードを書く(OSSのPluginを導入するのが楽)必要があります。こちらの導入については後述します。

f:id:sgtech:20200126210612j:plain自作コントローラそれはロマン

やってみたいことの妄想

こんなゲームを作りたい、こんな技術を作りたいといった思いはジャムに反映されやすいです。アイデア出しの種にもなりますので、考えてみてください。末尾のおまけには私のジャム参加前のモチベーションを添えてみました。

ジャム当日:アイデア出し

アイデア出しの裏で、UE4がインストールされていない人はこの間にインストールしましょう。

ワードマップから始める

私がよく使う手法を紹介します。

ゲームジャムはテーマとして単語や文章が与えられることが多いです。与えられたテーマより連想するワードを付箋などに書き出し、ワードマップにします。

このとき、名詞・動詞・状態(ゴールや目的)などを意識します。

f:id:sgtech:20200126225159j:plain

出てきたマップについてみんなで議論することになります。ここでの強力な手法の1つに「EMS Framework Method」というものがあります。

EMS Framework Methodについて紹介されている記事

こちらを少し簡略化して、「プレイヤー(名詞)が〇〇して(動詞)、□□という結果になる(状態)」という枠にワードを当てはめます。名詞、動詞、状態のうち2つ当てはめれば、ワードマップに無い言葉も生まれてくることでしょう。 

例えばおまけ⑫では、「☆」というテーマが与えられて「ヒトデ」「流れ星」といったワードが出てきました。枠内の名詞・結果に当てはめてみると、「ヒトデが〇〇して(流れ)星になる」となるので、残りの〇〇を皆で考えた結果、ビッグなスターになるということで「巨大化」という動詞が生まれてきました。

f:id:sgtech:20200126210936p:plain

アイデアの大枠が決定した時、UE4のテンプレートが使えそうか考える

UE4の使用経験のあるプログラマーは、決定されたアイデアにUE4のテンプレートを流用できるか考えてみましょう。流用できる場合は制作が楽になります。

f:id:sgtech:20200126210623p:plain

流用しない場合は考える楽しみがあります。おまけ⑨ではテンプレートを使用しませんでしたが、未知のものを作れそうなワクワク感がありました。

末尾のおまけでは、各ゲームが使用したテンプレートを記載しました。

ToDoリストを作成する

ゲームに必要な機能、要素を分割して、やるべきこと・やっていることを可視化します。

f:id:sgtech:20200126210428p:plain

運用につきましては過去の記事に詳しく書かれておりますので、こちらをご覧ください。

techblog.sega.jp

 

ジャム当日:最初にやること

テーマ決めより使用するテンプレート(または空のプロジェクト)はプログラマーが判断すると思うので、その方がプロジェクトを作成して配布するといいでしょう。

バージョン管理システム(VCS)を決める?

今現在Blueprintは更新が衝突したときのマージをマージツールで実現することが難しいです。よって衝突を防ぐためにファイル単位で担当を決めて作業することになります。

もし衝突した場合はUE4プロジェクトを両方開いて、Blueprintグラフ上で作業することになります。幸いBlueprintグラフはコピペが効きます。

おまけの⑪では、画像↓のようにPlayerやEnemy、大砲(Cannon)から放たれるMEGA DRIVEなどに分けました。Playerと大砲を担当する人とEnemyを担当する人に分かれ、各々でクラスファイルを実装しつつ相手のクラスに処理を追加したい場合は相手に仕込んでもらうようにしました。

f:id:sgtech:20200126210419p:plain

では、どのVCSを選びましょうか。

VCSを使用せずにUSBメモリを使用する

私のオススメUSBメモリを使用することです。経験上これがベストでした。

最初にプロジェクトを共有した後は図のような手順でローカルからUSBメモリへの更新と、USBメモリからの更新をローカルに適用します。

 f:id:sgtech:20200126210424p:plain

②のUSBメモリにコピーする際、周りのメンバーに何を更新したのか共有することを忘れないようにしてください。

私のオススメは定期的に全員で進捗確認の時間を設け、確認後にUSBにコピーすることです。確認をしたので、どんな更新がマスタープロジェクトに入っているか把握することができます。もちろん、プランナーやレベルデザイナーが最新の状態を触るために細かくやり取りすることも大事です。

USBメモリ側でもバックアップをしてもいいですが、ジャムの後半になるとそんなことは忘れます。①の部分も忘れられ②と③になることでしょう。しかし、このファイル共有作業において自分の更新分がどこかで消滅するとモチベーションが結構下がってしまうものです。面倒でも自分のローカルでバックアップを取るようにしましょう。そうすれば手違いが起きてしまったときに担当者がバックアップから取り出して確認し復旧しやすいです。

私の主観ですがUSBメモリの受け渡し形式はコミュニケーションの機会が増えるので、実装内容や予定の相談を行いやすいと感じます。

VCSを使用する場合
  • 安定したネットワーク環境であること
  • VCSを全員が操作できて問題解決もできる

といったチームであれば問題ないと思います。また、チームのプログラマーが3人以上であれば検討してよいと思います。

私は無線環境での更新の遅さやSVNのCleanupに悩まされた経験があります。ジャムの後半に問題が起こるととても焦ります。

Content直下にゲームジャム用のフォルダを作成する

このとき、名前を「数字_ゲームジャム(プロジェクト)名」にします。記号や数字を頭に持ってくることで並びが一番上に来ます。フォルダ名をチームで共有して、作業フォルダを明らかにしましょう。

f:id:sgtech:20200126210121p:plain

ゲームジャム後半などで、作業フォルダを見失うことを避けることができます。

例えばテンプレートやスターターコンテンツまたはMarket Placeのアセットなどを導入すると、Content「コンテンツ」フォルダ以下が肥大化することが多々あります。

下図は過去のゲームジャム(おまけの③)フォルダ構成なのですが、主な作業フォルダである「SGJ201707」を見つけることに苦労します。

f:id:sgtech:20200126210125p:plain

ゲームジャム2日目などはフォルダ名がとっさに思い出せないことやアルファベット順に並んでいることも頭から抜けていることがあります。ぜひ一番上に表示されるような名前を付けてみてください。

「Debug」フォルダを作成するときも「00_Debug」などにすると探しやすくなります。

各々の名前のフォルダで作業する

個人名のフォルダを作成し、自分の名前のフォルダ以下で開発を行うで複数人が同じアセットに対して作業することを防ぐことができます。

デバッグフォルダと同様、先頭に数字を入れると探しやすくなります。

f:id:sgtech:20200126210940p:plain

外部デバイスや使用したいコードのプラグインがある場合は、C++プロジェクトを作成する

UE4の標準機能では実現できないために外部のOSSを使用するときは、プロジェクト作成時にブループリントベースではなくC++ベースのプロジェクトを作成する必要があります。

これまでジャムで使用したことがあるサードパーティのプラグインを紹介します。

UE4Duino:Arduinoとのシリアル通信

傾きや照度などセンサー情報の受け取りや、回路へシグナルを出力してLEDを点灯させる等の場合に使います。(おまけの④で使用)

GitHub - RVillani/UE4Duino: Unreal Engine 4 plugin for COM communication on Windows

使用方法はGitHubのREADMEに載っている画像がわかりやすいです。

OpenSerialPort関数で得たSerialObjectの参照を使用してメッセージ送受信の関数を呼びます。Arduinoからメッセージを受け取る場合はRead〇〇関数、メッセージを送る場合はPrint関数です。

f:id:sgtech:20200126210730p:plain

 

おまけ④では複数発のLEDを制御するため、やりとりするメッセージの形式を「LED_(インデックス)_(点灯か消灯か)」に決ました。

Arduino側では受け取ったメッセージを解釈してLEDを点灯(消灯)させる処理を書き、UE4アプリ側では形式に合ったメッセージの文字列を合成して送信する処理を書きました。

f:id:sgtech:20200126210734p:plain

 

おまけ④以外のジャムでもUE4Duinoを使用する機会があり、傾きセンサの情報の取得を試みましたが、期間中にうまくいかず挫折したことがあります。

2日間のジャムで1日目にUE4で挫折して2日目でUnityを使って1から作り直したという苦い思い出です。悔しくて家でUE4バージョンも作り直しました。

f:id:sgtech:20200126210133g:plain

DirectInput:Joystickの使用

XInput非対応のコントローラを接続したいときにOSSのPluginを導入します。

GitHub - Ikarus76/UEJoystickPlugin: Unofficial Joystick Plugin for the Unreal Engine

 フォーラム:Joystick Plugin - Unreal Engine Forums

 

UEJoystickプラグインではスティックの軸値関数とボタンのインプットイベントより、望みの値を簡単に取得できます。PluginのReadmeにもあるように、Input用のActorまたはComponentを配置することを忘れないようにしてください。

f:id:sgtech:20200126210619p:plain

 

おまけの④ではAmazonでアーケードコントローラのDIYセットを購入し、専用のコントローラを作成しました。よく売っているタイプのエンコーダ接続は下図のようになります(4ボタン)。

f:id:sgtech:20200126210615p:plain f:id:sgtech:20200126210946j:plain

スティックはAxis値が中途半端(1.0ではなく、0.999などの値)になっていることがありますので、0.0や1.0を計算のしきい値にするような場合は注意してください。

OceanProject:リアルな海と浮力のシミュレーション

おまけの⑪では、海と船を使用するためOSSのOceanProjectを使用しました。

GitHub - UE4-OceanProject/OceanProject: An Ocean Simulation project for Unreal Engine 4

f:id:sgtech:20200126210556g:plain

とてもリアルな海、浮力のシミュレーションなどが含まれています。

素早く自分の好きな物体へ浮力を適用するためのヒントとしては、OceanProject内で既に浮力が与えられているBlueprintのメッシュを差し替えて流用することです。

↑の動画で見えるように、オブジェクトへ◇型をした浮力シミュレーション用のテストポイントがアタッチされています。テストポイントの位置や、細かい浮力パラメータを調整することができます。

OceanProjectを初めて触る場合、導入して使い方を覚える時間を考慮すると2日のジャムでは時間が足りないかもしれません。三角関数の単純な浮き沈み処理を書いた方が早くて楽だと思います。

プロジェクト作成者が最初に配布する内容

以下のフォルダを共有します。

  • Configフォルダ
  • Contentフォルダ
  • DerivedDataCacheフォルダ
  • 〇〇.uproject ファイル
  • Pluginsフォルダ(追加した場合。中のIntermediateは除外)
  • Binariesフォルダ(C++プロジェクトの場合)
  • Sourceフォルダ (C++プロジェクトの場合)

また、大きなテンプレートやアセットを最初から導入していた場合、共有DDCを設定してあげると初回のシェーダコンパイルが走らず、親切です。こちらの記事を参考に、

[UE4] DDCを共有してストレスフリーな開発を!|株式会社ヒストリア

「Path=%GAMEDIR%/DDC」を記述、.uprojectと同じフォルダに「DDC」という名前のフォルダを作成してプロジェクトのエディタを起動しましょう。

エディタを起動し、シェーダのコンパイルが終了したらDDCファイルごと共有します。

おまけの⑪では、サイズの大きいOceanProjectというOSSを最初に導入しました。導入時の共有DDC設定をすることで、渡してすぐに実行を試してもらうことができました。

初めてUE4を触る方・初めての方に教える方

おまけ⑫のジャムではメンバー5人のうちUE4の経験者は私だけでした。教えながら・調べながらのスタイルもゲームジャムですので、やってみたいという気持ちだけで当日を迎えても大丈夫です。

操作方法を教わりながら、初めての方が間近で挑戦されているところを見てきたので、事例を紹介します。

書籍を見ながらコインを実装

おまけ⑥のジャムでは、学生のプログラマー(UE4やUnityの経験無し)が書籍を見ながら、プレイヤーが触れると消滅するコインを作成しました。

Unreal Engine 4 で極めるゲーム開発 | ボーンデジタル

f:id:sgtech:20200126210326p:plainf:id:sgtech:20200126210330p:plain

f:id:sgtech:20200126210349p:plain

具体的には15章3節の「ピックアップアイテムを作る」の部分です。

UIのチュートリアルを見ながらメニュー、ゲーム中UI、結果画面を作成

おまけ⑫のジャムでは、内定者学生のプログラマー(Unityの経験者)が公式webのチュートリアルドキュメントを見ながらUIを実装しました。

UMG UI Designer Quick Start Guide | Unreal Engine Documentation 

f:id:sgtech:20200126210334p:plainf:id:sgtech:20200126210338p:plain

f:id:sgtech:20200126210341p:plain

制限時間を表現する処理にも挑戦していました。

レベルデザインやランドスケープツールの利用

おまけ⑫のジャムでは、Unity経験者のプランナー2人がプレイヤーのパラメータ調整とステージ作成を分担や協力をしてレベルデザインや見た目の調整をしていました。

f:id:sgtech:20200126210949p:plain f:id:sgtech:20200126210954p:plain



Unity経験者は慣れるスピードが早いのだとは思いますが、右の画像の海感は素晴らしいです。パラメータ調整も小数点第二位の値までこだわっており、完成度の高いゲームができあがっていました。

わからないところは質問しよう、わからなさそうなところに気づいたら教えよう

エディタ操作方法やBlueprintの実装方法など、初めての方にはわからないことが沢山あります。UE4の経験者は都度補足してあげることが重要ですし、初心者の方はわからないことを都度経験者に伝えることが重要になります。

初心者の方はUE4エディタに慣れてきたら、次はwebで検索して試すことにチャレンジしてみましょう。

こちらの写真は前回記事の写真でして、↑のUIチュートリアルを進めている方に対してドキュメントの内容と自分たちのゲームを照らし合わせて補足しているときのものです。

f:id:sgtech:20200126210345p:plain

よく聞かれたもの

UE4初めての方よりどういった質問や回答が多かったかを挙げてみます。

ビューポートやアウトライナについて

レベルデザインにおいて物体の配置(移動や回転)や見たい位置へのカメラ移動のとき、操作に対して思ったより動きが小さい場合や大きすぎる場合があります。

ビューポートの上部にある設定項目をいじりましょう。特にカメラ速度とフィールドの大きさが噛み合っていないと移動に時間をとられます。

f:id:sgtech:20200126210756p:plain

 

アウトライナの中でフォルダ分けしたいときは、フォルダのアイコンを押します。

おまけの⑫では捕食対象の種類によってフォルダ分けし、パラメータ変更時に選択しやすくなっていました。

f:id:sgtech:20200126210759p:plain f:id:sgtech:20200126210825p:plain

 

フィールドが広大な場合は、オブジェクトをアウトライナで選択した状態で「F」キーを押すとカメラがオブジェクトの近くに移動してフォーカスされます。

f:id:sgtech:20200126210830g:plain 約1.5kmの距離を一瞬で移動

Blueprintの基本的な操作

隣に座って画面を操作してもらいながら口頭で説明することが多いです。ドキュメントを見て貰う場合はマウス操作の説明や、画像に赤い枠などの印をつけて説明されているものを紹介しましょう。 

 

さわりとして、マウスの操作方法や画面の説明をすることが多いです。

↓こちらのドキュメントと同様な話をします。

【UE4】ブループリント入門【第1回】 | TECH Projin

 

算術演算子や、変数の定義方法もよく聞かれます。

↓こちらのドキュメントと同様な話をします。

ブループリントの基本を覚えよう | Think IT(シンクイット)

 

Blueprintワイヤーの切断方法

Blueprintワイヤーの切断方法は質問率ナンバーワンです。しかし多くの入門ドキュメントでは接続方法の近くに切断方法が書かれておらず、「Blueprint 切断」といったキーワードで検索しなおすケースが多いです。

切断と、ついでに付替のショートカットを覚えましょう。

  • 切断:ワイヤー上でAlt+Click
  • 付替:ワイヤー(切断側)上でCtrl+Click

f:id:sgtech:20200126210803g:plain

ノードのピンから右クリックでも切断できますが、ショートカットの方が早く便利です。

プランナー、ゲームデザイナー向け(プログラマーも見てね)

アイデア出しが終わったあとには、プレゼン資料の作成や詳細仕様を考えることに頭を悩ませると思います。今まで一緒にジャムをした方の立ち回りについてプログラマーの目線からご紹介します。

レベルデザイン

動くものを触ってみることが重要です。触ってみた結果、当初考えていたイメージと異なっていることに気づき、改修や調整の判断ができます。レベルデザイン担当者の試行回数が多かったときほど、手触りのよいゲームになっていると感じます。

なので、プログラマーにお願いしてパラメータを調節できるようにしてもらいましょう。プログラマー向けTipsにヒントを書いておきました。

例えばおまけの⑫では、プログラマーがプレイヤーの成長率(ジャンプの高さや身体の大きさ、乗り越えられる段差の高さなど)を調節できるようにして、プランナーの2人が地形とパラメータの調整を進めました。↓の画像は地形の調整用マップと、見た目の最終マップです。

f:id:sgtech:20200126210404p:plain f:id:sgtech:20200126210408p:plain

 

待ち時間が発生したとき

まだ基本的な動きが完成しておらず、ゲームを実行しての確認ができず手が空いてしまうケースはよくあります。むしろ、動きを早期に確認できるジャムは稀だと思います。

仕様を簡略化できるか・どこまで削ってよいか考える

アイデア出しのとき、ゲームが単調にならない要素を考えると思います。ゲーム中のキャラクターや制限の種類を増やすと面白そうなものになるでしょう。しかし期間の短いジャム中にアイデアの全てを入れ込むことは至難です。

アイデア出しの部分で言及したToDoリストなど要素分けしてリスト化したものに優先度をつけて、最低限必要なものが何であるか考えましょう。

 

おまけの⑫において削った仕様の例を紹介します。

・ゲームの終了条件

アイデア段階では「ゴール地点にたどり着く」「制限時間に達する」「自分より大きい捕食対象より一定のダメージを受ける」でした。開発を進める中で、ダメージを受ける要素が無くてもゲームになることに加え、捕食対象の動作(ダメージを与えようとしてくる)実装と調整の時間が足りないと判断してダメージの仕様は無くなりました。

・キャラクターの種類

アイデア段階での捕食対象は大きく4種類、さらにカラー変更で見た目のバリエーションも増やす考えがありましたが、最終的には3種類(最低限、水中・陸上・空中に存在するもの)となりました。プログラマー側から提案して種類を減らさせていただきました。

チームにサウンドさんが居ない場合、音素材を集めましょう。

UE4で使用できるオーディオファイルの形式はWAV形式です。UE4.22以降ならAIFF、FLAC、Ogg Vorbis形式を使用できます。

フリーの音源など外部より取得したものは音量にばらつきがある可能性がありますので、確認して波形の正規化をしてあげると扱いやすくなります。

フリーソフトのAudacityを使用した正規化とWAV形式への変換を紹介します。

Audacityはこちらより入手します。https://www.audacityteam.org/

Audacityへ音源をインポートしたときに、波形の枠上下いっぱいになっていなければ音量が小さいです。右の画像は-1.0dbで正規化されたものです。右の画像のようになっていれば扱いやすいです。

f:id:sgtech:20200126210531p:plain f:id:sgtech:20200126210548p:plain

 

正規化をします。Ctrl+Aで波形を全選択したあと、「エフェクト」>「ノーマライズ」を実行します。出てくるウィンドウはそのままでOKです。

f:id:sgtech:20200126210535p:plain f:id:sgtech:20200126210540p:plain

 

WAVファイルのエクスポートは、「ファイル」>「書き出し」>「WAVとして書き出し」を実行します。

f:id:sgtech:20200126210544p:plain

UE4へのインポートは、フォルダを選択してインポートボタンです。右クリックからもできます。

f:id:sgtech:20200126210706p:plain f:id:sgtech:20200126210710p:plain

 

インポートされたアセットを右クリックし、キューを作成します。

f:id:sgtech:20200126210714p:plain f:id:sgtech:20200126210718p:plain

 

例えばBGMの場合はループさせたいので、キューアセットを開いてWave Playerノードを選択し、詳細パネルのLoopingにチェックを入れます。

また風の音や爆発音といったSEについて、アウトプットノードを選択したときの詳細パネルでピッチ項目を弄ってゲームの雰囲気と合わせます。

f:id:sgtech:20200126210726p:plain f:id:sgtech:20200126210721p:plain

プログラマー向けTips

タイトル→ゲーム→リザルト→タイトルのゲームシーケンスループを作成

ゲームに備わっているべきシーケンスだと思います。もちろん、ゲームの部分を作ることに熱中して作成できなかったとしてもOK。それもゲームジャムです。

このシーケンスがスムーズに作られていると、プレイする人の頭が準備されるだけでなく、試遊する方がプレイするときに制作者がいちいちスタートボタンや停止ボタンを押さなくても良くなります。

ゲームジャムでは試遊の時間が設けられていることが多いです。自分のゲーム近くで案内操作している時間が多いと、他のジャム作品を遊ぶ時間が少なくなります。それはもったいないので、ぜひ自立したゲームシーケンスを目指してください。

f:id:sgtech:20200126210252g:plain

↑おまけ⑥を制作したジャムで配布されたテンプレートにおける遷移動作です。

マップを分割し、遷移処理を作成

ゲームジャム中はメインとなるゲームのマップを繰り返し実行して開発するので、タイトルを切り離しておくべきです。

ゲーム中にリザルトを表示させようとなると、表示の裏で動く様々な処理を止める必要があるかもしれません。意外と手間である場合もありますので、リザルトも分かれていると悩まなくて良いです。タイトルやリザルトの表示は一瞬でも、それを遷移する時間がちりつもで嵩んでいきます。

分割することで、UI作成+表示+マップ遷移の役割としてゲーム部分の役割と切り離すことができます。これは重要なことで、プログラマーが2人以上の場合はプレイヤー+ゲーム部分担当と、UI+シーケンス(+他のキャラクター)担当に分かれることがとても多いです。同じマップファイルを触らなくなるので、更新が衝突することも無くなります。

 

レベルの遷移はOpenLevelノードで行います。正しく該当のマップに遷移するか、必ず確認するようにしましょう。

f:id:sgtech:20200126210437p:plain

実行時にLevel Nameの名前を持ったマップアセットの探索が走ります。ジャム規模のプロジェクトで探索時間が問題になることは無いと思いますが、Gameからのフルパスを指定しておけば転ばぬ先の杖です。指定方法は、マップアセットを右クリックして「リファレンスをコピー」を実行してペーストした結果より、「World'」から「.マップ名'」までの文字を抜き出します。例えば

「World'/Game/00_GameJam2020/Map/Result.Result'」がコピーされるので、「/Game/00_GameJam2020/Map/Result」を使用します。

f:id:sgtech:20200126210440p:plain f:id:sgtech:20200126210445p:plain

繰り返しになりますが、正しく該当のマップに遷移するか必ず確認するようにしましょう。

得点などをリザルトで表示したい場合はGameInstanceクラスを作成して情報を持たせる

Mapを遷移するとActorがベースクラスのBlueprintは破棄されます。プレイヤーのキャラクタークラス等に得点情報を持たせてしまうと、マップ遷移時に情報が失われてしまいます。

GameInstanceクラスはプロジェクトに1つだけ設定され、アプリケーション起動時より常駐となります。このクラスにリザルトの情報を持たせる実装が楽です。

GameInstanceクラスの作成

コンテンツブラウザ上の右クリックメニューよりブループリントクラスを選択し、親クラスの選択ウィンドウにて「すべてのクラス」を展開した中よりGameInstanceクラスを選択します。

f:id:sgtech:20200126210456p:plainf:id:sgtech:20200126210502p:plain

 

今回はBP_Jam_GameInstanceという名前にしました。

f:id:sgtech:20200126210506p:plain

 

「編集」 > 「プロジェクト設定」で開いたウィンドウより、左側の「マップ&モード」を選択、中の「ゲームインスタンス」に先程作成したクラスを設定します。

f:id:sgtech:20200126210512p:plainf:id:sgtech:20200126210509p:plain

 

作成したゲームインスタンスの参照を取得するには、GetGameInstanceノードのアウトプットをキャストします。関数ライブラリなどに取得関数を作成すると便利です。

f:id:sgtech:20200126210518p:plain

※技術的負債ポイントです。GameInstance参照が各所に飛び散ると、起動と同時に芋づる式に参照アセットがロードされるので、規模が大きくなるうちに気づけば初回起動にとても時間がかかる問題にぶち当たります。

回避策の1つに、BlueprintInterfaceを使用する方法があります。ジャムではおすすめしませんので、もしあなたがジャム中であれば読み飛ばしてください。

他のBlueprintクラスと同様に右クリックからクラスを選択します。

f:id:sgtech:20200126210849p:plain f:id:sgtech:20200126210852p:plain

 

ダブルクリックでクラスの編集画面に入り、「+」ボタンでインターフェース関数を追加します。続いて引数や返り値を定義します。

f:id:sgtech:20200126210855p:plain

 

次に今回プロジェクトのGameInstanceクラスを開き、「クラス設定」よりBlueprintInterfaceクラスを指定し、インターフェース項目に追加された関数の中身を実装します。

f:id:sgtech:20200126210900p:plain f:id:sgtech:20200126210905p:plain

 

使用するときは、GetGameInstance関数のアウトプットから呼び出すことができます。右上にメールが開封されたようなアイコンが付いているものがインターフェース関数です。

f:id:sgtech:20200126210910p:plain

ジャム中にこの方式を使用するデメリットとしては、ノードをダブルクリックしても実装した部分が開きません。BlueprintInterfaceクラスが開きます。実装内容を調整したいときは自分でBlueprintInterfaceクラスを実装したクラスを開いて該当の関数を見つけるい必要があります。ちょっとした手間が貴重な時間や精神を削ります。

もしジャムのGameInstanceに適用する場合、何度も調整する必要がないように変数のSet, Get程度にとどめましょう。

もう少しこの辺りの問題について知りたい場合、こちらの記事の「プログラム編」を読んでみてください。

特徴的なアートスタイルはこうして作られた。「OCTOPATH TRAVELER」開発秘話 - GamesIndustry.biz Japan Edition

 

UIのWidgetBlueprintをGameInstanceに持たせた例

おまけの⑫では、この図のような構成で作りました。

f:id:sgtech:20200126210433p:plain

WidgetBlueprintクラスをGameInstanceに持たせておくと、ゲーム中のUI情報をリザルト画面で流用することができて楽になります。リザルトのマップにおいて、ゲーム中に更新されたWidgetBlueprintを表示(AddToViewport)してUI上部のゲージを非表示にするだけで、スコアのリザルトを反映することができました。

f:id:sgtech:20200126210448p:plain f:id:sgtech:20200126210453p:plain


パラメータを調節してもらうようにする

例えば、Blueprint関数ライブラリにパラメータを取得する関数を作成して、ゲームデザイナーの役割の人にアウトプットの数値を弄ってもらうようにします。

f:id:sgtech:20200126210354p:plain f:id:sgtech:20200126210357p:plain

 

関数ライブラリではなくマクロライブラリにする場合は、FormatText(テキストをフォーマット)ノードなどに気をつけましょう。この場合、関数ライブラリの出力は正しく値が渡りますが、マクロライブラリの出力値はnullとなります。
f:id:sgtech:20200126210401p:plain

値を画面に表示し続ける

PrintTextやPrintStringノードにおけるDuration(表示時間)を0にすると1フレームだけ描画されるので、Tickで毎フレーム呼び出すことで常に1つ表示されているように見えます。

例えば以下のように残り時間、体力、得点といったパラメータを表示しておくことをおすすめします。FormatText(テキストをフォーマット)ノード内に{hoge}を記述することでInputピンを増やすことができます。

f:id:sgtech:20200126210608p:plain


ずっと左上に出続けます。
f:id:sgtech:20200126210116g:plain

見ながら動作確認やレベルデザインに活用できます。短い期間でも数値の扱いでバグが生まれやすいので、おかしいなと思ったときにすぐ気づくこともできるでしょう。

 

デバッグキーを用意する

「ゲームをクリアしたことにする」「アイテムを取得したことにする」「次のレベルへ飛ばす」といったショートカットはレベルデザインやデバッグ作業を高速化します。キーボードを押した時に呼ばれるイベントを作成しましょう。

f:id:sgtech:20200126210914p:plain

グラフ上で右クリックして任意のキーボードイベントを検索するときに、なかなか見つからず苦労している方をジャム中によく見かけます。

たとえば「a」キーの場合、日本語環境では「a キー」、英語環境では「a keyb」まで入力することでサジェストを絞り込むことができます。

f:id:sgtech:20200126210918p:plain f:id:sgtech:20200126210922p:plain

 

または検索窓に「@」を入力(サジェストにキーボードイベントしか出てこない!)してインプットイベントをとりあえず作成し、イベントノードを選択した状態の詳細パネルから、Input Key部分から対応するキーやボタンを変更します。グラフ上で右クリックするよりも探しやすいと思います。

f:id:sgtech:20200126210927p:plain f:id:sgtech:20200126210932p:plain


エディタで配置するか、外部ファイルで配置するか、ランダムに任せるか

エディタでの配置

ゲームプレイのイメージをしやすく、プレイの実行自体もすぐに行えるので思ったことをすぐ試せる強みがあります。

熱中しだすと時間を消費するので、レベルデザインの担当者が時間を区切って取り組む必要があります。

f:id:sgtech:20200126210653p:plain

プログラマー側では、調整してほしいパラメータを公開するようにしましょう。

ブループリント変数 | Unreal Engine ドキュメント

 

おまけの⑥ではコインのBlueprintに「BigCoin」フラグを設けて、レベルデザイナーがフラグをオンオフすることでサイズとスコアの異なるコインの使い分けができるようにしました。

f:id:sgtech:20200126210703p:plain f:id:sgtech:20200126210656p:plain

外部ファイルに記述

設定箇所が多くエディタ内の操作では時間がかかる場合には、外部ファイルでまとめて設定できるような方法を検討するといいでしょう。

おまけの⑩では、ステージの起伏設定箇所が100個以上有ったため、Excelに入力してcsvよりUE4のDataTableへインポートするようにしました。Excelを使用する場合は、「条件付き書式」> 「セルの強調表示ルール」を設定することをおすすめします。

f:id:sgtech:20200126210626p:plain

 

例えばゲーム中の見た目と同様な色の使用や、設定の種類によって色をアサインすることで入力の段階から動作イメージをしやすくなります。

f:id:sgtech:20200126210630p:plain f:id:sgtech:20200126210642p:plain

CSVのインポートや、どのようにCSVを記述したらよいかは、こちらの記事がわかりやすいです。

ランダムに任せる

限られた時間の中で、手が回らない場合はランダムな配置に任せるのも手です。

プレイごとに内容が変わるので、いままで判明していなかった面白い部分や面白くない部分が見つかります。またジャムの終了後、試遊のために並んでいる人や気になって近くで見ている人達が自分でプレイするまでに飽きないです。

ただし同じゲーム内容を再現できないので、バランスを担保することが難しいです。

おまけの⑨のゲーム設計は、プレイヤー進行方向より流れてくるアイテムを取り続けるというものでした。しかし、アイテムをステージ上に手動配置する時間が足りず、ランダムを使用することにしました。

f:id:sgtech:20200126210634p:plain f:id:sgtech:20200126210647p:plain

 

0.35秒ごとに前方の4箇所からランダムで出現させる処理(右の関数)を書きました。

f:id:sgtech:20200126210638p:plain

40秒程度のゲームで100個以上のアイテムを出現させています。プログラムは1時間以内で書けましたが、同じ量を手動で配置して調整するとなると2, 3時間必要でしょう。

「とりあえず爆発させましょう」

ジャムの終盤でよく聞く言葉です。

理由はどうあれ、もう爆発させるしかない。爆発は全てを解決します。

Content Examples(機能別サンプル)より爆発を持ってきてみましょう。

 

Epic Games LauncherのUnrealEngine(左側)より、ラーニング(上側)より「機能別サンプル」を探してプロジェクトを作成します。

f:id:sgtech:20200126210138p:plain

 

作成してプロジェクトを開いたら(シェーダコンパイルを待つ必要はありません)、コンテンツブラウザの検索窓に「explosion」と入力します。

f:id:sgtech:20200126210156p:plain

 

爆発アセット「P_Explosion_Bomb」を右クリック、「アセットアクション」→「移行」を選択します。(英語環境では「Asset Actions」→「Migrate」)

f:id:sgtech:20200126210144p:plain

 

下図のように爆発アセットに参照されているテクスチャやマテリアルが階層表示されます。OKを選択し、移行先プロジェクトのContentフォルダを選択してOKします。

f:id:sgtech:20200126210147p:plain

 

画面右下に移行完了のメッセージが出ます。

f:id:sgtech:20200126210152p:plain

 

移行先のプロジェクトを開き、アクターを作成します。コンテンツブラウザで右クリック→ブループリント→ブループリントクラスを選択。

f:id:sgtech:20200126210202p:plain

ウィンドウからActorを選択します。

f:id:sgtech:20200126210246p:plain

 

作成したActorは「BP_Explosion」としました。

f:id:sgtech:20200126210206p:plain

 

ダブルクリックで開き、コンポーネントタブの「コンポーネントを追加」をクリック、検索窓に入力して「ParticleSystem」を絞り込んで選択します。

f:id:sgtech:20200126210210p:plain

 

コンポーネントタブはこのようになります。このParticleSystemを選択した状態(色が黄色になっている状態)にします。

f:id:sgtech:20200126210214p:plain

 

同じ画面の詳細タブから、「Particles」の項目を探し、中の「Template」行にあるプルダウンエリアをクリック、出てきたサジェストより移行してきた「P_Explosion_Bomb」を選択してください。

f:id:sgtech:20200126210219p:plain

 

Templateに適応された状態です。

f:id:sgtech:20200126210224p:plain

 

ちょっとだけ余裕がある人は、イベントグラフタブに移動してください。ない人はこれで「BP_Explosion」での作業は終わりです。画像を2個飛ばして「爆発の起動」から読んでください。

f:id:sgtech:20200126210229p:plain

 

BeginPlayノードより、Delay(2秒を設定)、DestroyActor(self:自分自身)とノードを作成して接続します。これで2秒後に自分自身を破棄します。

f:id:sgtech:20200126210232p:plain

爆発の起動

「BP_Explosion」をSpawnActorするだけで起動します。例えばレベルブループリントのBeginPlayでSpawnしてみます。爆発させたい位置(Transform内のPosition)をステージ真ん中辺りに指定しました。

f:id:sgtech:20200126210236p:plain

 

実行するとすぐ爆発します。終わり。

f:id:sgtech:20200126210241g:plain




ジャム中の注意点など

巨大なアセットが本当に必要か検討する

UE4のMarketPlaceやラーニングコンテンツでは高品質なアセットが並び、中には無料で手に入るものがあります。

これらは使いやすいと思いきや、大きいリソースはジャム中のイテレーションを鈍化させる原因になります。

おまけの⑧では広大な3つのステージを同時に使用しました。

  1. シューティング ゲーム | Unreal Engine ドキュメント

  2. Infinity Blade: Fire Lands:Epic Games:Epic Content - UE4 マーケットプレイス

  3. Infinity Blade: Ice Lands:Epic Games:Epic Content - UE4 マーケットプレイス

ShooterGameのビル内に、Fire LandsとIceLandsを入れこむ贅沢な使い方をしました。入れこむための配置調整に時間がかかった上に、結果としてマップを開く時間がとてつもなく長くなり、アプリのパッケージング時間も膨大となりました。

結果として提出するための動画撮影時間が足らずに中途半端なコンテストのエントリーになってしまいました。

f:id:sgtech:20200126210412g:plain

ゲームの本質的に不要であれば、無理に入れない方が良いかもしれません。

ゲーム画面の発表時には電源を接続する

ノートPCがバッテリー動作の場合、充分な電力がグラフィックカードへ送られず3Dゲームの実行が不安定になることがあります。

発表場所近くで電源を使用できるよう運営に手配していただくようにしましょう。

f:id:sgtech:20200126210523j:plain

ゲームジャムでUE4チームを作るには

テンプレートの活用やBlueprint開発、エディタでの高速なイテレーションによって、UE4はジャムの強力な味方になります。

しかしUE4だけの制限をしていないジャムにおいて、UE4チームが生まれる機会は少ないです。Global Game Jam (毎年世界同時に開催される最も大規模なジャム)では、Unityに比べてUE4で制作されるゲームの数は10分の1程度です。世界中の比率と日本国内の比率は同じくらいです。

UE4を使いたいなと思っていても、チームではUnityを使用する場合が多いと思います。

ジャム運営の方へ

UE4チームが組まれるためには、ジャム運営側の協力が必要だと思っています。あらかじめ参加者に希望(リーダーや使用ツール)を募るケースが多いと思いますので、参加時にエンジンの希望を出してもらうようにしてみましょう。

次に参加者の希望を公開 (公開する旨は伝わるようにする)して、ジャムのwebページで見えるように並べます。UE4の希望者は他にUE4の希望者が居ると集まりやすいです。

または、ジャムの参加枠にUE4枠を作成してみてください。どこからともなく集まります。connpassなどのサービスで枠を作成できます。

ジャム当日のチーム決めの後に、選択肢として考えてみる

チーム内にUE4経験者が居る場合は、UE4チームになってみることを検討してみてください。UE4未経験者が経験者に教わりながら触り始めて、機能実装やレベルデザインを主体的に行っている様子を何度も見てきました。ここでの経験者は私以外であるパターンもいくつか知っています。

おわりに

今回は個人的な活動を書き起こしてみました。私が活用したことのないものは書いておりませんので、良さげなノウハウや苦労した話を持っているよ!という方は、ぜひブログやスライドにして公開していただけたらと思います。

セガではグループ内で定期的にゲームジャムを開催しており、私のように毎回UE4を使う人や、その時によってアナログゲーム制作や電子工作を絡める方など、やりたいことを試す機会に恵まれています。ご興味がありましたら、ぜひ採用情報をチェックしてみてください。

採用情報| 株式会社セガ・インタラクティブ

そして私とUE4のチームを組んでください。

 

おまけ:これまでの制作物

簡単な説明・期間・画像を載せてみました。

Sega Game Jamで制作したものは[SGJ]とつけました。

画像の下にジャム前のモチベーションを書きました。


①: [SGJ]超電磁的なコインを飛ばすVRゲーム:1日

f:id:sgtech:20200126210958g:plain

ジャム前は、VR元年ということもありVRゲームを作りたいモチベーションでした。

バーチャルリアリティのテンプレートを使用しています。


②: クレー射撃のようなVRゲーム:2日

f:id:sgtech:20200126205831g:plain

ジャム前はとにかくVRゲームを作りたいモチベーションと、オリンピック競技的なものを作りたいと思っていました。

バーチャルリアリティのテンプレートを使用しています。

 

③: [SGJ]巨大化して求婚するゲーム:2日

 ※Sega Game Jam内に限り、セハガールモデルの使用が認められていました

f:id:sgtech:20200126210107g:plain

ジャム前は特に何も考えずに挑みました。

サードパーソンのテンプレートを使用しています。

 

④:[SGJ]コントローラやLED連動システムごと作った宇宙探査ゲーム:2日

f:id:sgtech:20200126225439g:plain

ジャム前はアーケードゲーム筐体を作りたいと思っていました。

フライングのテンプレートを使用しています。


⑤: 爆弾の設置側と解除側のゲーム:1ヶ月程度

f:id:sgtech:20200126205856g:plain

ジャム前はUE4のリプレイ機能(DemoRec)を使いたいなと思っていました。

サードパーソンのテンプレートを使用しています。

 

⑥: 昼と夜を切り替え対応する足場を乗り継ぐゲーム:2日

f:id:sgtech:20200126205842g:plain

ジャム前はUE4のライトシナリオ機能を使いたいと思っていました。

ジャム専用のサイドスクロールテンプレートを使用しています。

 

⑦: [SGJ]おじさんが失った青春を取り戻すゲーム:2日

f:id:sgtech:20200126210112g:plain

ジャム前は特に何も考えずに挑みました。

サードパーソンのテンプレートを使用しています。

 

⑧: プリンがぷるぷるするゲーム:1ヶ月程度

f:id:sgtech:20200126205917g:plain f:id:sgtech:20200126210741g:plain

ジャム前は、ゲームにならなさそうなものを無理やりゲームにしたいと思っていました。

サードパーソンのテンプレートを使用しました。プリンの軟体シミュレーションにはNVIDIA FleXを使用しています。

 

⑨: つばめが綺麗な円を描くゲーム:2日

f:id:sgtech:20200126205932g:plain

ジャム前は特に何も考えずに挑みました。

テンプレートは使用していません。

 

⑩: 地形をリバースさせ、せり上がる衝撃でジャンプし続けるゲーム:5日

f:id:sgtech:20200126210004g:plain

ジャム前は、アプリケーション容量を小さく収めるチャレンジ枠に挑戦したいと思っていました。地形をランタイムで生成しています。(ProceduralMeshComponent)

テンプレートは使用していません。

 

⑪: [SGJ]大崎オフィスにグループ会社が集結するということで、各事業所を回ってグループシナジーを集めていくタイムリーネタだったゲーム:2日

f:id:sgtech:20200126210045g:plain

ジャム前は、メガドライブミニ要素をどこかしらに入れたいと思っていました。実際にプレイヤーの前方より発射されます。

テンプレートは使用せず、OSSのOceanProjectを使用しています。

 

⑫: [SGJ]ヒトデが魚や人を食べて大きくなって星になるゲーム:2日

f:id:sgtech:20200126210021g:plain

ジャム前は、チーム分けでUnityチームのプログラムリーダーになっていたのでUnityの復習をしていました。当日の話し合いでUE4を使うことになりました。

サードパーソンのテンプレートを使用しています。

 

以上です。ここまで見ていただき、ありがとうございました。

SEGA GAME JAM 再始動!テーマは☆!!

f:id:sgtech:20191207144708j:plain

セガゲームス、セガ・インタラクティブ含め、セガサミーグループが大崎に集約され、いよいよシナジー効果が期待される中、先月11月2日にSEGA GAME JAMが再始動しました。

皆さんこんにちは。SEGA GAME JAM運営の麓です。

SEGA GAME JAMの運営としてはデザイナー向けの対応や、ポスターデザイン、ロゴデザイン、Tシャツデザインの調整などを担当しつつ、当日は主にデザイナーとして参加しています。

普段私はテクニカルアーティストとしてツール環境整備周りを担当していて、アセットを作らなくなって久しいのですが(元々はデザイナーでした)、GAME JAM中はただひたすらデザインアセットを作り続けることになる刺激的な時間をいつも過ごしています。

f:id:sgtech:20191207145048j:plain
f:id:sgtech:20191207145029j:plain

SEGA GAME JAMって?

今さらですが、今回初めてこのブログから読み始める方のために簡単にSEGA GAME JAMについて説明します。

SEGA GAME JAMは2日間の限られた時間で、小規模グループに分かれて、それぞれのグループで一からゲームを作ってしまおう!というイベントで、2012年7月の初回から年2回程のペースで開催されているイベントです。

参加するのはセガサミーグループ全体を対象とし、ゲーム制作部門ではない人も過去には参加しています。

CEDEC2013で効果や詳細は公表していますので、ご興味をお持ちの方は以下にアクセスしていただけるとより詳しく知ることができます。(要ログイン)

SEGA Game Jamがもたらした組織活性化の効果

SEGA GAME JAMの変化について

さて、今まで十数回にわたって、羽田は大鳥居で開催されていましたが、グループ各社が大崎に集約されて取り巻く環境や事情が変化してきました。

あえて挙げるとすると3点。

  1. 参加者の裾野が広がった
  2. 会場がすごくイベントっぽくなった
  3. ゲーム制作の作業時間が短くなった
f:id:sgtech:20191207145439j:plain
f:id:sgtech:20191207145705j:plain

参加者の裾野が広がった

昨年まではセガゲームス、セガ・インタラクティブは羽田の大鳥居に社屋を構えていて、SEGA GANE JAMの会場も大鳥居でした。

そのためか、基本的に参加者は自然と大鳥居に近い場所に住んでいるセガゲームス、セガ・インタラクティブのメンバーに偏っていました。 

大崎に集約された後、その新社屋が会場となることで距離的な制約などは緩和され、セガサミーグループ内の様々な人が気軽に参加できるようになりました。

内定者の皆さんもより参加しやすくなったのではないでしょうか。

f:id:sgtech:20191207151552j:plain
f:id:sgtech:20191207151529j:plain

※写真左は会場の隣でやっていた『ぷよぷよ!!クエスト』のイベントから差し入れのカレーです。

会場がすごくイベントっぽくなった

新社屋内の多目的スペース「TUNNEL TOKYO」を活用できるようになり、イベント感が増しました。

※「TUNNEL TOKYO」についての詳細は以下を参照してください。

tunnel-tokyo.jp

会場がイベントらしくなることで、テンションも上がりますし、より楽しい雰囲気の中で時間が過ごせるようになります。

f:id:sgtech:20191207151139j:plain
f:id:sgtech:20191207151237j:plain

ゲーム制作作業時間が短くなった

一見ネガティブな印象を持たれがちですが、会場の事情や昨今の働き方改革に合わせる形でイベント自体も時間の効果的な使い方へのチャレンジが必要になりました。

改めて、当日のタイムスケジュールを振り返ってみましょう。

 

一日目 (11/2)

  • 8:30  受付開始
  • 9:00  開始
  • 9:05  テーマ決め
  • 9:20  チーム分け
  • 15:00 企画発表
  • 20:00 α 版発表
  • 20:30 写真撮影
  • 21:30 会場 Close

二日目 (11/3)

  • 07:30 会場 Open ~ 随時制作再開
  • 12:00 β 版発表
  • 18:00 制作終了
  • 18:15 発表会
  • 19:00 試遊会&順次撤収開始
  • 20:00 完全撤収
  • 20:30 打ち上げ 参加は任意

 

以上から、ゲーム制作に使える時間は22時間程度というのがわかるかと思います。

そんな中でもちゃんと一つのゲームを作り上げることができたのは、参加した皆さんの実力の高さを実感しました。

SEGA GAME JAMの効果について

効果の程は?というと、SEGA GAME JAMの根本の趣旨は変わらないのでそこは今までと変わりません。例えば、

  • グループ会社、事業部、世代を超えた絆が生まれる!
  • 失敗を恐れずチャレンジできる!
  • 変わるきっかけが生まれる!

グループ会社、事業部、世代を超えた絆が生まれる!

このイベントが終わるとまた日常の自分たちの仕事へと戻っていきます。

しかし、ここで一緒にゲーム制作できた経験と記憶は消えることがありません。

仕事の中での再会もありますし、連絡を取り合って新しいアイデアを元に何かが生まれたりすることもあります。

f:id:sgtech:20191207145830j:plain
f:id:sgtech:20191207145859j:plain

失敗を恐れずチャレンジできる!

普段ふと思いついたことも、やりたいなーって思っていることも何かきっかけと時間がないとなかなか手をつけられなくて悩むことも多いと思います。

せっかく2日間という時間と協力してくれるメンバーを得る機会なので、いろんなチャレンジができます。

例えば普段プログラマーの仕事をしている一参加者もこの二日間は延々写真とビデオを撮り続けて、最後にはSEGA GAME JAMのプロモーションビデオを完成させました。また、私も普段使うことのないデザインアセット作成用のツールをいくつも試してきました。

そして過去には、モバイル開発にいた人もボルダリングを体験できるVRゲームをチームの力で作り上げることができました。

f:id:sgtech:20191207152537j:plain
f:id:sgtech:20191207145452j:plain

変わるきっかけが生まれる!

実は過去に、総務などゲーム開発をしない部門にいた人もこのイベントをきっかけに開発へと転身したということもありました。

f:id:sgtech:20191207152338j:plain
f:id:sgtech:20191207152308j:plain

これからも・・・

手短ですが、今回のBlog記事ではSEGA GAME JAMの再始動を改めて宣言し、ここ大崎で起きた変化を少しでも紹介したかったので筆をとってみました。


ゲーム作りの本質は変わりません。遊んでくれる方が笑顔で感動体験をしてくれる事が何よりの喜びです。

 

そのための、チャレンジの場、交流の場として、そしてゲーム作りを楽しむためにも SEGA GAME JAM は引き続き開催していきたいと思っています。

f:id:sgtech:20191208195859j:plain
f:id:sgtech:20191208195841j:plain

※最後のプレイ会の一場面

最後に、そんなGAME JAMが開催できるような社内交流が盛んで、開かれた職場環境で働いてみたいという方は以下をチェックしてみてください。

 

sega-games.co.jp

おまけ 

ここまでTech blogなのに何のノウハウも公開していないことに気づきました。

イベント開催レポなのでそんなにお話しできることもないのですが、一つだけ、社内GAME JAMを開催していたり、これから開催しようと思っているゲーム業界の皆さんへ・・・。

参加者のモチベーションが上がる要素の一つとして「いろいろな業界関係者が見学してくれるとモチベーションが上がる」という意見が過去の開催アンケートにいくつか見られました。

「社内」ということで多少難しい面もあるかと思いますが、少し調整を頑張ってゲーム業界周辺の関係者を見学に誘ってみてはいかがでしょうか?

 

それでは、ここまで読んでいただきありがとうございました。

良いJAM生活を。

 

そして良いお年をお迎えください。

セガのモーションキャプチャースタジオ紹介

はじめに

はじめまして。セガゲームスのモーションキャプチャーチームに所属している北川と申します。

業務内容としてはモーションキャプチャーエンジニアとしてワークフローの構築や収録オペレーターといったことをしています。(簡単にいうとモーションキャプチャーの撮影周り全般です)

モーションキャプチャーチーム内では、以下の三つの班に分かれて業務を行っています。

・撮影班:撮影~収録したマーカーデータの処理や小道具作成など

・エディット班:収録データのキャラクターへの流し込みと修正作業

・サポート班:上記の班をサポート

私はその中でも撮影班として収録業務を行っているので、今回はなかなか話をする機会のないセガのモーションキャプチャースタジオについてお話をさせていただきます。

 

 

セガモーションキャプチャースタジオとは

セガモーションキャプチャースタジオの歴史

セガは『バーチャファイター』(1993年発売)の開発時からと業界でもかなり早くモーションキャプチャーをゲーム開発に導入しました。

導入当初はモーションキャプチャーの専門チームとしては存在せず、2000年頃よりモーションキャプチャーチームとして部をまたがってプロジェクトをサポートするようになりました。

写真は過去のスタジオ写真の一部になります。スタジオも数回引っ越しをしていますし、使用しているシステムも様々な変化があります。

f:id:sgtech:20191127214712j:plain
f:id:sgtech:20191127214716j:plain
f:id:sgtech:20191127214705j:plain
f:id:sgtech:20191127214708j:plain
f:id:sgtech:20191127214722j:plain
f:id:sgtech:20191127214728j:plain

現在の所属はセガゲームスになりますが、セガ・インタラクティブ、アトラス、サミー、マーザ・アニメーションプラネットなどセガサミーグループの様々なプロジェクトに関わっています。

直近のタイトルでは以下のモーション収録に携わりました。

『龍が如く7 光と闇の行方』『東京2020オリンピック The Official Video Game』『新サクラ大戦』
『ファンタシースターオンライン2』『WCCF FOOTISTA』『Wonderland Wars』『けものフレンズ3』
『Fate/Grand Order Arcade』『艦これアーケード』『ペルソナ5 ザ・ロイヤル』『キャサリン・フルボディ』

  

スタジオスペック
  • カメラ:Vicon社 反射光学式カメラ 約100台          

    f:id:sgtech:20191127214815j:plain

  • 収録エリア:18m x 10m x 4m(横幅 x 奥行き x 高さ)
  • 常設設備:壁面鏡・ワイヤーアクション用設備・チェック用大型モニター

過去のモーションキャプチャーを利用するタイトルがバーチャファイターシリーズをはじめとした格闘アクションだった事もあり、『シェンムー』(1999年発売)制作の頃から立体的なアクションの要求に応えるためワイヤーアクション用の設備を設置しました。
現在のスタジオではワイヤーアクションの為に天井からのH鋼を二本に増やすだけでなく、床内にワイヤー用の専用フックも設置してより複雑なアクションがとれるようになっています。 

f:id:sgtech:20191127214737j:plain
f:id:sgtech:20191127214741j:plain
f:id:sgtech:20191127214638j:plain
f:id:sgtech:20191127214732j:plain

 

収録環境の工夫

リファレンス用のビデオ収録

反射光学式のモーションキャプチャーは収録しただけだとただの点データ(座標データ)になってしまいます。そうするとマーカーを付けていない部分の動きや表情などは収録することができません。

そのため、後作業で参考にするためにキャプチャー収録と同期をしてビデオを録画することが非常に有用になってきます。

昔はSD画質でも問題なかったのですが、指の表現や表情も撮影時のものを参考にすることが増えてきたことによってHD画質での録画の要望が高まってきました。しかし、要望の増え始めた頃はVicon社のキャプチャーシステムと同期してHDで録画するシステムは存在していない状況でした。

その話をモーションキャプチャーチームをサポートしてくれているプログラマーに話したところ、プログラマー同士の雑談から動画の処理に詳しい者がシステム作成に手を挙げてくれました。

そこからモーションキャプチャーチームの要望をヒアリングしたうえで、ハードの選定や録画・エンコードソフト、キャプチャーシステムとのリンク部分などを作成してくれました。

これによって国内でも非常に早い段階でHD画質でのリファレンス映像の収録環境を構築することができました。このシステムは今でも欠かすことのできないものとして運用されています。

社内のふとした繋がりによって当初想定していたより素早く期待以上の環境構築をすることができたと同時に、セガ社内の人材の厚さを実感しました。

f:id:sgtech:20191127214651j:plain
f:id:sgtech:20191127214655j:plain
f:id:sgtech:20191127214701j:plain
 リアルタイムプレビューのクオリティアップ

ビデオ収録でも触れましたが、収録したデータは座標情報のみとなり点と線の表示となってしまいます。そのため、MotionBuilderというソフトを同時に使用して確認用にキャラクターを動かす事が一般的です。
ただアクター(演者)さんとキャラクターとの体型の差などから不自然に動いてしまう場合も多々あり、エディット班では後処理を行う際にセガ独自のリターゲット方法を利用しており、アクターさんとキャラクターの動きの誤差を少なくすることで作業の軽減を図っています。

そこでエディット班とサポート班に協力をしてもらい、リアルタイムプレビューにも同様のリターゲットが行えるように改良を行っていきました。これによって収録をしている段階で動きの誤差が少なくなり、アクターさん・プロジェクトスタッフ双方のイメージの共有の齟齬が少なくなり再収録などのリスクも非常に低くなりました。

f:id:sgtech:20191127214646j:plain



指の収録

最近では指の動きを収録する事例なども多く見かけるようになりましたが、セガでは2010年頃からボディと一緒に簡易的な指のモーションの収録も行うようになりました。

それ以前は必要に応じてグローブデバイスを使うなどしたこともありますが課題も多く、指は収録後にビデオやイメージを基にプロジェクトのモーションデザイナーが手作業で動かすことがほとんどでした。その手法だと数をこなしたり、自然な動きを再現するのに非常に時間がかかってします。そこで収録時のアクターさんの動きを体と一緒に収録できれば指の自然な表現ができるのではと実装に向けて検証を始めました。

検証当初は5本の指全てにマーカーを付けての収録など様々なテストをしました。しかし出来上がるクオリティとデータクリーンアップ作業の工数を鑑みて、親指・人差し指・小指の3か所のみにマーカーを付け、その動きを基に5本の指を動かすようにしました。これによって手の開閉タイミングや細かい動きのニュアンスも収録できるようになり、プロジェクトからも好評で今ではすべての撮影で欠かせないものとなっています。

導入当初はリアルタイムプレビューでは満足に動かすことができず、撮影後のデータ処理の段階で初めて動く状況でしたが、改良を重ね現在ではリアルタイムプレビュー上でも動かせるようになっています。

末端の動きではありますが開閉や指差しなどだけでも表情のように印象が大きく変わるので、特にダンスやイベントシーンの収録時にイメージ共有がしやすくなりました。

f:id:sgtech:20191127214750j:plain



 

 

その他

小道具やセット

モーションキャプチャーの収録はカメラやソフトなどを見るととても複雑なシステムを使用しているように見えますが、実際の収録現場はアナログな作業が非常に多く存在しています。

生の動きであるアクターさんの動きをデジタルデータに変換するのがモーションキャプチャーです。なので、可能な限り演じやすく・ロスなくデータ化することが非常に重要になってきます。もちろんそのまま使用することはほとんどありませんが、だからこそその素材になる収録データはできる限りアクターさんの動きをしっかりと撮ることが最終的なクオリティにも貢献できると思っています。

収録しやすくなるように小道具やセットも可能な限りリクエストに応えられるように様々な準備を行います。演技しやすいように発泡スチロールや塩ビパイプなどを組み合わせて大きくても軽い小道具を作成したり、イメージに近くデータ収録に問題がないセットにするなど様々な工夫をして収録をしています。この部分は実際に現場で動きながら作業をするので、テクニカルなだけでなくADや大道具的な作業も行っています。

以下の画像はごく一部ですが、すべてチーム内のスタッフが作成したものです。よく見るとわかりますが、マーカーがついており小道具の動きも収録を行っています。収録したオブジェクトの動きもリアルタイムプレビュー上でしっかりと反映し武器などを構えた状態も確認できるようにしています。

 

f:id:sgtech:20191127214755j:plain
f:id:sgtech:20191127214800j:plain
様々な収録システム

モーションキャプチャーといっても様々なメーカーのいろいろな収録システムが存在します。セガのモーションキャプチャースタジオも当初から現在のViconのシステムではありませんでした。古くは磁気式といわれるものやVicon社以外のシステムを運用していました。

それらの経験は現在の収録にも活かされており、メインで使用しているシステムだけでなく他のシステムに関しても情報を収集したり撮影によっては他のシステムを運用したりしています。

例えばスタジオの広さが室内ではとても足りない場合や、収録をしたい環境(セットなど)を再現するのが困難な場合は持ち出して収録をすることができる慣性センサー式のシステム(Xsens MVN)を使用して収録を行ったりもしています。

また、映画製作で行われているパフォーマンスキャプチャーについても要望が高まっていることからフェイシャルキャプチャーやバーチャルカメラも同時に撮れる環境づくりを順次進めています。市販のものを購入するだけでなく、使い勝手を考え顔の動き・表情を収録するためのHMC(ヘッドマウントカメラ)や3DCG上のカメラを操作することができるバーチャルカメラを独自に作成もしています。

社内のスタジオとしてできるだけ多くの要望に応え、より良いものをプロジェクトに届けるべく様々な検証やサービスの展開を行っています。

f:id:sgtech:20191127214810j:plain
f:id:sgtech:20191127214805j:plain

 

 

最後に

今回はモーションキャプチャースタジオでの収録に関連した部分にスポットを当てて書いてきました。収録現場はPCでの作業もありますが、実際に自分が動いて対応をすることが多くあります。ビデオの収録やキャラを見ながらの確認などをしっかりと整備したことによって、イメージを共有しやすくしたり現場での撮影補助に集中することができるようになりました。動き回ることの多い現場だからこそ周辺のツールなどのありがたみを感じます。

f:id:sgtech:20191127214746j:plain



写真:撮影班一同

 

モーションキャプチャーチームでは一緒にプロジェクトを支えるメンバーを募集しています。

興味のある方はぜひサイトにアクセスしてみてください。

sega-games.co.jp

©SEGA

 

【Unity】Unite Tokyo 2019 「大量のアセットも怖くない!~HTTP/2による高速な通信の実装例~」講演と壇上では語られなかった6つのこと。

皆さんこんにちは。セガゲームス、開発技術部の山田です。 以前は OpenGL の話を本ブログで紹介したのですが、今回は Unite Tokyo で講演してきたお話です。 本記事は講演の時と同じく、前半は山田、後半は竹原でお送りします。

目次

Unite Tokyo 2019

Unityユーザーのためのテクニカルな講演やブース出展が数多く行われる、国内最大のUnityカンファレンスイベント「Unite Tokyo 2019」が 2019年9月25日、26日に開催されました。そこで、私と竹原より、「大量のアセットも怖くない~HTTP/2による高速な通信の実装例」という講演を行いました。 お越しいただいた方々ありがとうございました。

講演の結論は「Unityで標準的な作り方をした場合において、 HTTP/2を使ってアセットバンドルをダウンロードすることは相性がよいです」 と話しました。

f:id:sgtech:20191028000857j:plain

資料など

資料や講演ムービーは既に公開されており、次のページでアクセスできます。

learning.unity3d.jp

質疑中の様子

予想していたよりも多くの方に質疑コーナーに来て頂けまして、色々と質問や情報交換ができました。 とても有意義な時間でした。ありがとうございました。

f:id:sgtech:20191028000853j:plain

講演中に語られなかったこと

講演では説明できなかった色々なことを本ブログで補足したいと思います。

Keep Alive の話

Keep Alive を使った HTTP/1.1 なら HTTP/2 との速度差はそれほどつかないのでは?と思う方もいるでしょう。自分もそう考えていた時期があったので、この点に悩む方は多いのではないかと考えています。

前提として、https での通信を考えます。 Keep Alive で削減できるのは TCP の再接続のコストです。実際にデータを送受信するまでの前準備の部分です。

f:id:sgtech:20191028000903p:plain

HTTP/1.1 では、複数のコネクションを張って並列にデータのダウンロードを行う実装とします。 このとき多くの場合で3~6が使われることと思います。しかし、それぞれのコネクションで輻輳制御が行われるために、帯域を有効活用することができません。 これを分かりやすく説明してくれているのが 「IIJ Technical WEEK 2015」においての「HTTP/2からQUICへ続く Webプロトコルの進化」という講演内容です。

www.iij.ad.jp

「HTTP/2からQUICへ続く Webプロトコルの進化」という講演資料の19ページから21ページにて解説をされています。 次の図は、この資料より引用させていただきました。

f:id:sgtech:20191028000900p:plain

HTTP/1.1 ではファイルごとに1つのコネクションを使います。Unity での標準的な作りをする場合においてファイルサイズは小さめであり、1コネクションにおいて輻輳ウィンドウサイズが十分に大きい状態で通信を行い続けることができません。 HTTP/2 ではストリームの機能を用いて複数ファイルのダウンロードを1つのコネクションに多重化するため、使用できる帯域を最大限使うことができます。

RTTの観点からも HTTP/2 ほうが有利です。 HTTP/1.1 の場合、Keep-Alive で再接続のコストを抑えていても、ファイルを取得するときに出すリクエストで RTT 分の時間が掛かります。 この間は、そのコネクションにおいてファイルのダウンロードは進行していません。仮に 100 ファイルあったとすると 100 *0.5RTT の時間分はファイルのデータダウンロードに使えていないことになります。HTTP/2 では多重化により他のデータやりとりの1部としてファイルのリクエストも紛れ込んでいるので、通信路としての無駄が少なくなっています。

f:id:sgtech:20191028000906p:plain

ただし、どのような条件下でも HTTP/2 のほうが速いかというとそうでもないので状況に応じて考える必要があります。

必要なファイルを結合してアーカイブファイルを作成し、それをダウンロードするというフローであれば HTTP/1.1 でも効率の良い通信が実現できます。 Unite Tokyo 2019 の KLab さんの講演「「禍つヴァールハイト」最大100人同時プレイ!モバイルオンラインゲームの実装テクニック」の中でも語られておりました。 tar 形式と Range パラメータを使ってというアイデアはとても面白いと思います。 KLab さんの方式は事前に必要なデータをガッツリダウンロードするような MO/MMO のようなものに向いているのではないかと考えております。

learning.unity3d.jp

同時ファイルオープン数について

講演中では印象優先で Windows ではファイル数 512 という表現をさせてもらいました。 しかし、その制限は実は Windows そのものによる制限ではなく、 Visual C++ が提供している C Runtime (CRT) による制限となっています。 Windows 自体はもっと多くのハンドルを同時に扱うことができます。

fopen/fclose といった C言語の世界の関数が CRT に属します。 Windows で生のファイルを操作する場合は Win32API に属する CreateFile 関数を使用します。 Windows 専用ということもあって、ファイルの共有Read/Write, 256文字を超えるファイルパスによるアクセスなど色々とできることが多いです。

(Windows API (Win32API) や、Windows カーネルの話も機会があったら本ブログで書けたらと思います。)


講演で語られなかったこと (竹原より)

それではここからは竹原が担当させて頂きます。

私のパートでは HTTP/2 に関する仕様や libcurl の実装面でのもう少しディープな解説をさせて頂こうと思います。

HPACK の圧縮率を確認する

HTTP/1.1 までの通信では、HTTP ヘッダはプレーンテキスト形式で記述され、クッキー等により時にはその合計サイズは 1 キロバイトを超えることもありました。 HTTP/2 ではこうしたヘッダのサイズ問題を解消するべく HPACK という専用の圧縮機構が採用されています。

講演を聞いてこの HPACK で実際どれくらいヘッダが圧縮されるのか、気になった方もいると思います。

f:id:sgtech:20191024153931p:plain

そこで、この項では HPACK の仕組みを、「どれくらいヘッダサイズが削減されるか」についても触れながら簡単に解説してみます。 かなり効果があるので、独自拡張等ヘッダに色々仕込んでいる場合は導入を検討してみても面白いと思います。

[HPACK]HTTP/2 のヘッダ管理

講演でも触れたように、 HTTP/2 のヘッダはバイナリとして扱われるようになりました。 更にパラメータは 全て小文字で表現されるようになった のに加え、従来のリクエストラインやヘッダの表現形式も若干変更されています。

例えば、 HTTP/1.1 の典型的なリクエストラインとヘッダの組み合わせである以下は

GET /resource HTTP/1.1
Host: sega.com
Accept: text/html

HTTP/2 では次のような集合として表現されます。

:method = GET
:scheme = https
:path = /resource
host = sega.com
accept = text/html

HPACK ではこれらの Header Name/Value の組み合わせをヘッダフィールドと呼び、文字列で表すか、独自のインデックス値でエンコードして表すか選択することが可能です。 更に、文字列で表す場合は Huffman Coding(ハフマン符号) で圧縮するかどうかも選択することができます。

[HPACK]Huffman Coding での圧縮

Huffman Coding は、出現頻度の高い文字には短いビット列を割り当て、低い文字には長いビット列を割り当てることにより圧縮を図る方式です。

例えば、文字 A が 1 回、B が 3 回、C が 5 回、D が 2 回、E が 1 回出現するような文字列「ABBBCCCCCDDE」に対して以下のように符号を割り当てます。

f:id:sgtech:20191024154846p:plain

この割り当てられた符号を使って前述の文字列「ABBBCCCCCDDE」を表現すると、

1110 10 10 10 0 0 0 0 0 110 110 1111

となり、全体を 25bit で表現することができるようになりました。

実際の符号の割り当てには、圧縮したいデータ内の文字の出現頻度をベースにして構築した Huffman Tree という二分木を利用します。 Huffman Tree の構造はベースにしたデータ内の文字の出現頻度により変化するので、適用したいデータのパターン毎に用意する必要があります。 そこで、 HPACK では過去に利用された HTTP のリクエスト・レスポンスのヘッダを解析した結果を基にして構築した専用の Huffman Tree が採用されています。

RFC 7541 - HPACK: Header Compression for HTTP/2

それでは、Huffman Coding でどの程度のデータの圧縮が可能なのか、先ほどのヘッダフィールドの内容を例に確認してみましょう。

まずは :method を Huffman Coding してみると

":method"  1011100 101001 00101 01001 100111 00111 100100
"GET"  1100010 1100000 1101111

となるので、これを合算して 61bit に圧縮できることがわかります。
※ヘッダフィールドは Name/Value でそれぞれ管理されるので "=" は不要となります

HPACK では Huffman Coding されたデータがオクテット単位に揃わない場合、余ったデータ部は 1 でパディングされるというルールがあるので実際には

":method"  1011100 101001 00101 01001 100111 00111 100100
"GET"  1100010 1100000 1101111 {111}

となり、 64bit(8byte) のデータ長となります。

元々の文字列は ":method" → 7byte, "GET" → 3byte で 10byte ですので、 20% 圧縮されたことが分かります。
※ HTTP/3 に使われている QPACK では、このパディングが不要となり、さらに圧縮率が上がっています!

このように、 Huffman Coding を用いると、頻出文字で構成されるデータであれば大幅にデータを圧縮可能です。 上記よりもう少し頻出文字が多い文字列だと 30% を超える圧縮率になることもあります。 反面、バックスラッシュ(19bit)やアンダースコア(15bit)といった出現頻度の低い文字については、元の8bitより遙かに大きくなってしまうので注意が必要です。 実装によっては、 Huffman Coding を掛けた前後のサイズを比較し小さい方を採用する、というような工夫もしているものもあるようです。

[HPACK]インデックス値を用いた圧縮 : Static Table

HPACK には Huffman Coding の他にも、Header Name と Header Value を対応させた辞書である Indexing Table という独自の圧縮機構が用意されています。 Indexing Table には Static Table と Dynamic Table の二種類が存在しています。

Static Table は Huffman Tree のように過去の利用頻度の高いヘッダが予め登録されているテーブルで、HTTP/2 の RFC に全 61 種類が定義されています。

RFC 7541 - HPACK: Header Compression for HTTP/2

先ほど例に挙げたヘッダを上記の RFC の Static Table で表現しようとすると

:method → 2
:scheme → 7
:path → 4
host → 38
accept → 19

と対応していますので、以下のように表現できるようになります。

 2
 7
 4 /resource
38 sega.com
19 text/html

※インデックスは 1byte で扱われます

結果、 63byte → 31byte となり、約 51% 削減という Huffman Coding を大幅に超えた値で圧縮することができました。

※実際には Literal Header Field という独自の形式でヘッダフィールドを表現する為に、圧縮率はこの値より少し小さくなります。詳細は RFC 7541 - HPACK: Header Compression for HTTP/2 を参照ください

更にテーブルを適用できなかった文字列部には Huffman Coding を掛けてさらにデータを圧縮することも可能です。

[HPACK]インデックス値を用いた圧縮 : Dynamic Table

Dynamic Table は、通信に使用したヘッダフィールドを動的にテーブルに登録していき、 Static Table のようにインデックス値で指定できるようにする圧縮機構です。 テーブルへの登録可能な上限サイズの初期値は 4096 オクテットで、上限を超えた場合はファー ストインファーストアウトのルールで登録が抹消されていきます。 Dynamic Table のインデックスは Static Table のインデックスの続きの 62 から始まり、追加する毎にインクリメントされていきます。

先ほどの Static Table で表現したヘッダフィールドをさらに Dynamic Table に登録してみましょう。

 2 → 2 のまま
 7 → 7 のまま
 4 /resource → 新規に 63 に登録
38 sega.com → 新規に 64 に登録
19 text/html → 新規に 65 に登録

すると、以下のようにかなりすっきりとした形で表現できるようになります。

 2
 7
62
63
64

結果、 63byte → 5byte となり、圧縮率は驚異の約 92% まで上がりました。

Dynamic Table のサイズは前述した通り 4096 オクテット(変更は可能です)なので、なんでもかんでも登録するわけにはいきません。 しかし、同じヘッダのリクエストを何度も送信する場合にはかなりの効果をあげますので、こうした事例では Dynamic Table を積極的に利用するのをお勧めします。

[HPACK]まとめ

若干長くなってしまいましたが、 HPACK を利用すると大幅にヘッダを圧縮することができることを理解して頂けたと思います。

最近のゲームは API リクエストをかなり頻繁に送信するものや独自にヘッダを拡張しているケースも多く、これらの積み重ねによって結構なデータ送信量になってしまうこともあります。 こうしたデータを削減するにも HTTP/2 はかなり効果的です。

アセットのダウンロードだけでなく API 通信にも HTTP/2 をお勧めします


HTTP/2 特有の設定を libcurl から行うには?

HPACK の高い圧縮率を見ると使ってみたくなるのはプログラマの性ですよね。

それでは libcurl から HPACK はどのように操作できるのでしょうか。……と期待を煽っておいて申し訳ありませんが、実は libcurl を用いた場合は HPACK についてのパラメータを変更することはできません

libcurl が依存している nghttp2 という OSS のレイヤーで「Huffman Coding」及び「Static/Dynamic Table」の利用については以下のようにそれぞれよろしくやってくれます。

  • Huffman Coding エンコード実施後、元の値より小さい場合のみ適用されます。
  • Static Table 自動的に適用されます。
  • Dynamic Table 特定の条件を満たすもののみ登録されます。

Dynamic Table への登録条件は以下の通りです。

/* Don't index authorization header field since it may contain low
     entropy secret data (e.g., id/password).  Also cookie header
     field with less than 20 bytes value is also never indexed.  This
     is the same criteria used in Firefox codebase. */

※ nghttp2 のソースコードコメントより

要約すると、

  • id や password, authorization 等のセキュリティ上問題になるようなヘッダーフィールドはインデックス化しない
  • 20 byte 未満の Cookie ヘッダーフィールドはインデックス化しない
  • これらは Firefox で使用されている基準と同じである

という内容です。

この基準以外で Dynamic Table を利用したい場合は、 nghttp2 に用意されている HPACK API を利用すると良いでしょう。

Tutorial: HPACK API — nghttp2 1.41.0-DEV documentation

※筆者も libcurl との併用が可能かどうか等については未検証です

また、 libcurl から制御できない HTTP/2 のパラメータは、実は HPACK だけではなく他にもいくつかあります。

例えば、

  • クライアントが指定する「最大ストリーム数の設定」 : SETTINGS_MAX_CONCURRENT_STREAMS
  • Dynamic Table の最大サイズ : SETTINGS_HEADER_TABLE_SIZE
  • ストリームの初期ウィンドウサイズ : SETTINGS_INITIAL_WINDOW_SIZE

等はすべて libcurl 内で隠蔽されています。

この辺りの HTTP/2 独自のパラメータを細かく制御したい人は nghttp2 をそのまま使うのをお勧めします。 ただし、 libcurl はクッキーの制御や HTTP/1 系への対応等、実装に手間のかかる所をケアしてくれています。 HTTP/2 のパラメータをどこまで制御したいか、プロジェクトの都合に合わせてどちらを使うか決めるのが良いと思います。


優先度制御の現在とこれから

講演中で HTTP/2 の優先度については仕様が見直し中、という話をさせて頂きました。

それでは、具体的にどのような仕様に見直し中なのか、少し補足しようと思います。

まず、三行でまとめると以下の通りです。

  • 優先度は現在 HTTP バージョンに紐づかない 仕様として現在審議中です
  • 従来の HTTP/2 の優先度に関しては 優先度制御しない 機能が追加予定です
  • 現在策定中の HTTP/3 では、優先度の機能を持たないことに決まりました

これだけではつまらないので、新しく提案されている優先度がどのようなものなのかについても軽く説明しようと思います。

※あくまで議論中の仕様なので今後変更される可能性があります

新しく提案された優先度はとてもシンプルです。

まず、Stream Weight は urgency level (緊急度) に置き換わり、全 8 段階へと縮小されました。

f:id:sgtech:20191024155737p:plain

※ここで言う「ファイルダウンロード」とはブラウザ経由での大きなサイズのファイルのダウンロードなどを指します

その他の変更点や特徴は以下の通りです。

  • 制御は HTTP ヘッダで行います
  • ヘッダで設定した値をさらに変更したい場合は HTTP/2,3 共に Priority フレームを利用する方向で話が進んでいるようです
  • クライアントからの urgency はあくまで hint であり、サーバ側の都合で urgency の値を上書き可能なようです
  • progressive jpeg 等のリソースの識別用のフラグも用意されます
  • HTTP/2 との優先度の互換性についてはこれから検討するようです

新しい優先度は基本的には web ページを基準に議論が進んでいる仕様のようですが、ゲームでも似たような区分でデータ分けは可能なので、割と使い易いのではないかと思います。 優先度についてより詳細が気になる方は、以下のページも参照してみてください


PKP と Expect-CT

講演の中で Public Key Pinning (PKP) について触れました。

f:id:sgtech:20191024160646p:plain

しかしこの PKP は、実は世の中的には古い仕様として非推奨となりつつあります。 理由は、講演でも触れたように、証明書の更新タイミングに運用側に負荷が掛かるからです。 例えば、 2019/1/29 にリリースされた Chrome 72 では PKP は既に廃止となっています。

それでは、中間者攻撃への対策はどうすれば良いのでしょうか?

そこで出番となるのが Expect-CT ヘッダです。

Expect-CT ヘッダーは、サーバが Certificate Transparency (CT) に対応していることをクライアントに伝える為に使用されます。

Certificate Transparency とは(ざっくり説明)

CT は証明書の発行のログと突き合わせることで、対象の証明書が不正なものであるかどうかを検知する機構です。 CT には Signed Certificate Timestamp (SCT) という、上記のログを管理するサーバに対象の証明書が登録された時刻を保証するタイムスタンプを利用します。 (利用の仕方は証明書に埋め込んだり、TLS Extension として送信したり、色々あります) この値からログ管理サーバに問い合わせを行うことで、自分たちの知らない所で証明書が発行されていないか(偽装されていないか)を確認します。

これ以上深堀りするととても長くなりますので、詳細が気になる方は RFC 6962 - Certificate Transparency を参照してください。

Expect-CT ヘッダの現状

リーグ・オブ・ワンダーランド導入時にもこの Expect-CT の検討は行ったのですが、まだ draft であった為に導入には早いとして最終的に PKP を選択しました。

それでは現在はどうなのか……というと現状 draft で止まっている状態なようです。

GitHub - httpwg/http-extensions: HTTP Extensions in progress

しかし、 Nginx や Apache では対応されているようですので、将来を見据えて PKP ではなく Expect-CT を採用してみるのも面白いかと思います。

最後に

私たちは、新しい技術でユーザの体験を変えていける、チャレンジ精神のある方を求めています。

当記事で弊社に興味を持った方は是非下のリンクをクリックしてください。

sega-games.co.jp

ゲーム開発に使われるプログラミング言語

 ゲーム=プログラム?

みなさんこんばんは。セガゲームス開発技術部の林です。

長年、技術と名のつく部門で技術者をやっています。このブログも TECH とついているためぜひ何か情報を発信してみたいと考えていましたが、やっと順番が回ってきました。

これまでやってきたことを控えめに表現するとゲームタイトルを開発しているチームのお手伝いです。遠慮せずに表現すると、技術的に難易度の高い部分を引き受けて成功に導くのが役割です。

そのため、家庭用ゲーム・アーケードゲーム・スマートフォンアプリなどいろいろなタイプや規模のゲーム開発に触れる機会が数多くありました。そこで、今回ブログのテーマとしてはその全てに関わる内容をご紹介したいと思います。

 

ゲーム開発に使用するプログラミング言語について取り上げます。

 

プログラム上のテクニックや技術の詳細ではなく、実際の開発現場でどのプログラミング言語が何に使われているのかをご紹介します。また、単に列挙するだけでなく、そのプログラミング言語の使われ方を通じて、ゲーム開発中にプログラミングが必要な場面としてどのようなことが行われているかの雰囲気もお伝えできればと思います。


プログラミング言語

ゲームはプログラムとデータでできています。最近プログラミングは特殊な技術者だけに必要なものではなく、その論理的な考え方は現代に生きる上で必要だとしてプログラミング教育が行われるようになりました。2020年からは小学校でのプログラミング教育が必修化されます。そういった流れから、ゲームはプログラムで動いており、プログラミングすることでゲームを動作させられるということを知っている人も多くなっているはずです。

そのプログラムを記述してゲーム機を含むコンピューターに命令するために使用するのがプログラミング言語です。プログラミング言語には非常に多くの種類が存在しており、ゲーム開発現場でもその中から選択された数多くのプログラミング言語が使用されています。

ゲーム業界と一般的なIT産業で全く違うプログラミング言語を使うということはなく、基本的には同じものを使いますが、全体に対する割合や重要度は業界によって異なる特徴が出ます。

この記事は、ゲーム業界を目指す方にとって、どのプログラミング言語を学習すればよいかの参考になるかもしれません。


よく使われるプログラミング言語

f:id:sgtech:20190916160513p:plain
C++

家庭用ゲームとアーケードゲームの多くは C++言語 で書かれています。ゲームは特に高速な動作が要求されるプログラムであり、高速な動作が期待できる C++ で実行速度を意識して書くことが重要です。

C++ やその元になった C言語 はハードウェア(コンピューター)に近い層の「原始的」な言語であり、ハードウェアの性能を100パーセント引き出すことに適しています。

C++ は十分に使いこなすには難易度が高めの言語ですが、その分機能が非常に多く、様々な目的に対して様々なやり方でプログラムを記述できる大きな自由度があります。そのため大規模なものを含む様々なプロジェクトで使用することができます。

 

また、ゲームそのもののプログラムだけでなく、特に速度の要求されるサーバープログラムやゲーム開発に必要なツール類の開発にも使用されます。

ゲーム開発において、ゲームプログラマーはゲーム本体のプログラムだけでなく、ゲームを作るのに必要なツールを作るためにもプログラミングします。一つのゲームを完成させるためには数多くのツールを作り、そのツールでゲームを組み立てていく作業が多くあります。

 

C++ の元になった C言語 は過去に広く使われていたため今でも一部に残っています。シンプルなため他言語との橋渡し部分に使われることもあります。C++ を学習する場合は必然的に C言語 も学ぶことになります。

 

f:id:sgtech:20190916155107p:plain
C#

スマートフォン向けゲームの多くは Unity というゲームエンジンを使って開発されています。この Unity では主に C#言語 を使ってプログラミングを行います。

 

また、C# は Windows PC 上で動くツールを作成するのにも向いており、ゲーム開発に使う社内ツールの多くは C# でプログラミングされています。 得意な処理を分担して、 C#C++ を併用しているツールもたくさんあります。

 

f:id:sgtech:20190916162024p:plain
Java

現代はすべてのゲーム機やスマートフォンがネットワークに接続しています。インターネットを経由した接続先にはサーバーが用意され、サーバーと通信することでネットワークゲームを実現しています。そういったネットワークゲームのサーバーや、ゲームと連動しているWEBサイトのサーバーなどゲーム会社は様々なサーバーを提供しており、それらのサーバー上でプログラムが動いています。サーバー上で動いているプログラムには様々な言語が使われていますが、 Java言語 が使われているケースが比較的多いです。

 

また、サーバーの場合は Java やその他の言語で直接プログラムを書くだけでなく、既存のソフトウェアをインストールして動かして使うことも多くあります。間接的にそれらのソフトウェアを作成するのに使われたプログラミング言語を使っているということができます。一部をカスタマイズして使うこともあります。

 

Java は他にも Android アプリ開発に使用することができ、一部のアプリで使用されています。

 

f:id:sgtech:20190916163211p:plain
Python

Python は様々な用途に使える人気の言語です。ゲーム業界や映像業界で広く使われているCGツールである Autodesk Maya の中でも実行できるため、面倒な繰り返し作業を自動処理させるなど、ツールを使いやすくするためにもよく使われています。

 

また、 Python は最近技術の進歩が目覚ましい人工知能(AI)の処理を記述するのに向いています。ゲーム開発現場においても人工知能を活用したツールを作るために使われる機会が増えてきました。

 

f:id:sgtech:20190916164031p:plain
JavaScript

JavaScript は、主にWEBページを作るために使われます。JavaScript を使うとWEBサイトで様々な機能や演出が実現できるようになります。このページにも使われていますね。

ゲームプレイヤー向けのWEBサイトだけでなく、ゲーム開発中に必要な情報を蓄積する社内向けWEBサイトも作成されます。チームではそれを参照しながら仕事を進めます。

 

また、JavaScript は Adobe Photoshop などのツールを自動化したり便利にするスクリプト処理にも使うことができます。

 

JavaScript のプログラムを直接書かず、TypeScript という JavaScript を強化した言語で記述し、それを JavaScript に変換してから使うこともあります。


その他の言語

その他にもシーンに応じて多くのプログラミング言語が業務に使われています。ここからはそれぞれ簡単に紹介していきます。

シェーダー言語

現代のゲーム機で画面表示を行うためには、専用のプログラミング言語を使って表示方法を細かく記述する必要があります。これをシェーダー言語といいます。キャラクターやメニューなどあらゆる画面表示はシェーダー言語の指示によって行われています。ゲームにとって表示の美しさや個性はとても大事なため、シェーダー言語によるプログラミングも重要です。

シェーダー言語としては、 HLSLGLSL などが使用されます。

アセンブリ言語

最も原始的でハードウェアに近い言語である アセンブリ言語 は、大きなプログラムを書くことには向いていませんが、特に高速に処理を行いたい部分にピンポイントに利用されています。

なお、最近メガドライブミニの登場で話題のメガドライブなど過去の16bitゲーム機時代のころまでは、ゲームプログラム全てが アセンブリ言語 で書かれていました。

スクリプト系言語

ゲームプログラム本体でもツールそのものでもなく、開発時に必要な様々な処理を行うためにも多くのプログラムが書かれます。 RubyPerl 、そしてすでに出てきた PythonJavaScript は作業を補助するためのスクリプト言語として使われます

Visual Basic もそういった処理の他、ゲーム開発でデータの管理によく使われる Microsoft Excel の制御にも使われます。

開発時ではなく、ゲーム実行時にゲームの動作を補助するスクリプト言語として、 LuaSquirrel が使われることもあります。

その他の言語

iOSアプリの開発には Objective-CSwift 、Androidアプリの開発には Kotlin といった目的に特に合ったプログラミング言語を使用することがあります。ゲームエンジン Unreal Engine 4 では専用ビジュアル言語である Blueprints が使われます。

bash 、 cmd.exe(コマンドプロンプト)、 PowerShell といった作業環境で使用する言語もプログラミング言語だと言えそうです。

既存のプログラミング言語ではできないことを実現するために、独自のプログラミング言語を新たに開発してそれを使うこともあります。


多様なプログラミング言語との付き合い方

ここまで多くのプログラミング言語を紹介してきましたが、ゲーム開発はチーム作業ですので、これら全てを一人で使いこなせるようになっている必要はありません。ここまで紹介してきたものの中で私が実際に業務で使ったことがある言語は半分ほどです。

使ったことがある言語でも、ほとんどが入社後に初めて触れています。セガに入社した時点では全く存在していなかった言語もあります。今後もゲーム機や開発に使う技術、プログラミング言語の進化に合わせて様々な局面に適した新しい言語がどんどん登場してくるでしょう。

 

プログラマーとして特に得意な言語はもちろんあったほうがよいですが、仕事で必要になった時に新しい言語をすぐに使いこなせるようになっておくと仕事の幅が広がります。まずは書きたい処理をすぐにスラスラと書ける得意な言語を軸として一つ二つ準備しつつ、それ以外の言語は新たに使いながら学んでいくことができれば問題ありません。

 

どのプログラミング言語を習得しておけばよいかという問いに対しては、どんなプログラミング言語でもすぐに習得できるようになっておけばよいというのが答えになります。

 

私たちは、常に新しい分野に好奇心を持ち、多くのプログラミング言語を使いこなしてゲーム開発に取り組める方を求めています。興味のある方は次にもアクセスしてみてください。

sega-games.co.jp

記載されている会社名、製品名は、各社の登録商標または商標です。

セガ・セガロゴとメガドライブは株式会社セガホールディングスまたはその関連会社の登録商標または商標です。

©SEGA

Powered by はてなブログ