この記事は
【その1】ドリコム Advent Calendar 2015の20日目です。
前日はおーはらさんの
Elixirを使ってSidekiqを操作するでした。
なお弊社今年は募集盛況で
【その2】ドリコム Advent Calendar 2015も出来ました。よろしくお願いいたします。
ついでに個人的に
伺か Advent Calendar 2015とか
Linux Desktop Advent Calendar 2015とか
Electron Advent Calendar 2015とか
Node.js その2 Advent Calendar 2015とか
ももんが Advent Calendar 2015とかも参加しているのでよろしくです。
自己紹介
ドリコムの新卒エンジニア、奈良阪と申します。ネットで奈良阪|Narazakaっぽいアカウントを見つけたらたぶん私です。

こんなアイコン物理学専攻として生まれPerlで育ちJavaScriptでゲテモノを作る仕事Ruby使いでErlang勉強中のインターネットラクガキマンであり、メインWindows(10)でArch Linux好きなMacアンチでオープニングアニメーション愛好家なぬるめの時刻表鉄でもあります。
業務ではRailsをいじりつつ、Electronでプランナー向けツールを作ってみたり、管理画面にJavaScriptを仕込もうと狙ったりしています。
まあ変な人です。
新規ゲームアプリをモデルとビューに分けて作ったり色々したら捗った話
新卒エンジニアなので新卒研修というものがありました。
プランナー、デザイナー、プログラマーを含んだ6人のチームでゲーム1本作るといったものです。
そこでUnity3Dでスマホゲームを作ることになり、エンジニア3人のうち僕を含む2人でクライアントを作ることになりました。
作業分担としては、UnityでUIを作るあたりをもとからクライアントエンジニアである
chu-hiくんにやってもらい、もともとサーバーエンジニアである僕はUIがあまり関わらないロジックの部分を担当することになりました。
ロジックの部分を請け負ったのでそこの全体的な設計は僕がやることになりました。
そこで色々なことを個人的な趣味で仕込んでみて捗ったりしたという話です。
1.モデル(的な部分)とビュー(的な部分)に分けて単体テストを書いた
かねてから個人的にゲームのクライアントにもサーバーでやるような自動テストを導入したいなあという思いを持っていました。
今メインでいるプロダクトもそうですが、基本的に弊社ゲームのクライアントには自動テスト的なものがないのが現状です。
無論十分手動でテストが入れられているから回っているんですが、プログラマーたるもの怠惰にゆきたい。テストとか面倒なルーチンは機械にやらせたい……。
一般的に見た目に関わる部分の自動テストが面倒なのはあるんですが、見た目に反映する前の、例えばダメージ計算とかそのへんの部分まではある程度現実的に自動テストが入れられるんじゃないかと思いました。
そこにきて本ゲーム、前述のような分担をすることによって、作業者によってロジック(モデル的なところ)とUI(ビュー+コントローラ的なところ)を分離することに成功しました。
というわけで自動テストを書きました。
xUnit.NETつかってだいたいこんな感じです。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xunit;
using NewGame.Word;
using NewGame.Status;
namespace NewGameTest{
using ExecutableString = String;
public class WordFrequencyElementTest{
[Theory]
[InlineData("return 1")]
[InlineData("return 0.1")]
[InlineData("return 'a'")]
[InlineData("return true")]
public void condition_enabled(ExecutableString condition) {
var status = prepare_status();
var fe = new WordFrequencyElement(condition, "");
Assert.True(fe.IsEnabled(status));
}
...
ロジックがUnityに依存しないPure C#でできているのでxUnit.NETとかそういう汎用のツールでかけて実に清々しいです。サーバーの人間にもスルッとかけます。
UIのテストはできていないんですが、その中で動いている複雑な部分のテストがあるというのは品質に対して実に安心感があるものです。個人の感想ですが。
これによってゲーム開発によくある(らしい)仕様変更にともなうコード修正に戦々恐々とすることはなくなりました。
2.データエディタを作った
かねてから個人的にExcelを撲滅したいなあという思いを持っていました。
基本的に弊社ゲームのデータはExcelで作られています。
・エンジニアにとって:
Excelはマージができませんし、差分もgitネイティブでは見られませんし、バイナリだからひたすらリポジトリが重くなりますし、ゲームに落とし込めるようテキストに変換するのに数分かかります。
・またプランナーにとっても:
RDBまんまなのでいちいち色々なところに数値のIDを関連づけのために入れなければならないし、複数人作業するときに手動ロックしなければいけない(自動マージできない)です。
つらいです。
というわけでこのゲームではExcelを生まれる前に消し去るために、すべてyamlやjsonをマスターにしたいなと思いました!……と、言うは易し行うは難し。
実際データを作るプランナーの人とかにyaml直接いじれというのは酷というもの。
エンジニアが楽した分プランナーが闇を背負ってはいけません。
「データをいじるためのUI」=「データエディタ」は必須なわけです。
普段はExcelがその役を負っているわけですが、Excelが嫌なら他のツールを使うしかない……。
というわけで今回は自分で作りました。
こんな見た目のやつです。

いわゆるゲーム中のシナリオみたいなやつのエディタで、yamlファイルを吐くものです。
ツリー状の構造になるゆえにExcelでは管理しにくかったので専用のを作ってみました。
Electronを使うことでWebアプリと同じような制作ができつつWin/Mac両対応が行え、UIライブラリとして
webixを使うことでデスクトップアプリに遜色ない操作性を確保できました。
こちらはプランナーデザイナー陣にも好評で、「ならツール」などと呼ばれ親しまれました。
が、プロト提出の締め切りギリギリの中で結局デザイナー少しとあとほぼプログラマしか入力しなかったなど、課題は残りました。
3.データエディタにゲームのモデル部分を接続した
かねてから個人的にゲームのデータ調整やチェックを実際のゲームの処理に突っ込んでやりたいなあと思っていました。
ゲームにバグを出さないためにデータチェックツールというのが往々にして作られるわけですが、なにぶん仕様追加変更の多いゲームのこと、本体の変更に追従してゆくコストがかかります。
なのでゲームのデータを簡単に「本物」のゲームの処理に突っ込んでテストできれば、そういった外部ツールの辛みもなくなるのではないかと思いました。
というわけで先ほどのゲームのモデル部分処理だけを切り出してコンソールアプリケーションにし、先ほどのエディタがその入出力に対応することで、「本物の処理」を使って「プレビュー」を行えるようにしました。

右側がその「プレビュー」で、「実行」ボタンなどを押すと現在編集中の部分のシナリオが実際のゲームでどういった動きをするのか、選択肢などの挙動も含めて再現できるというものになっています。
この機能もやはり好評でして、プレビュー機能の成果か突貫工事なデータ入力作業でもレビューでバグっぽい動きはしませんでした。
実装としては単純にパイプで入出力しました。C# CLIなexeとnode.jsのchild_process.spawn()との通信です。
Edge.js、そのElectron対応版の
electron-edgeを使えば、node.jsからDLLのごとくC#内部の関数を呼べたのですが、やったかぎりだとあいにくそれができるのがWindowsのみだったので、Win/Mac両対応を崩さないためにパイプにしました。
ゲーム本体は本来ならシナリオを最初から再生する機能(上記ボタンの「戦闘開始」のみの機能)しか持たなくて良いので、本番では使わないテスト用の機能の追加は避けた方がデバッグコストなどもかからないでよさそうです。
本質的な処理をするモデルをゲーム全体から切り離せるようにしておくと、UIの必要性が薄いテストツールを気軽に外部アプリケーションとして作り込めると思います。
ただしこの手法の反省点としては、簡易プロトコルを作ったり、初期化処理だけですが本体に追従したり、Electronとの結合だったり、工数的にはちょっとお高くついてしまった感があるあたりでしょうか。
やっぱりゲーム自体にテスト機能を組み込んでしまう方法をとって、Unity3DのWebGLビルドを使ってブラウザ内完結させるとかのほうがもしかしたら簡単だったかもしれません。
まとめ
研修で新規ゲームの設計をやるに当たって、かねてから周りのゲーム制作を見つつ個人的に抱いていたゲームクライアント制作手法への提案を試してみました。
・モデル的な箇所とビュー的な箇所を分離することでテストをかきやすくし、実際書いて品質を担保しました(まだリリースしてないので主観になってしまいますが)。
・Excelには向かないデータ編集に対して独自ツールを作り、企画工数を減らしました。
・さらにデータ編集ツールにゲームの本物の処理が動くプレビュー機能をつけることによって、ミスを減らしたり調整を楽にしたりしました。
やってみた所感としては、
・モデルビュー分離はコードの質を保つのに貢献し、一方で爆速感の不足や、やや仕様変更に手間がかかる感がありました。ただテストなしで仕様変更後などにバグチェックするコストを考えると、実際には仕様変更の手間というのはこちらの方が軽いのかもしれません。
・データ編集のための独自ツールはプレビューもあって非常に便利でした。調整も楽だし、Gitフレンドリーでエンジニアも楽です。ただし初期投資はその分かかるので、短期間で運用を終了するゲームの場合はもしかしたらExcelに任せた方が良いのかもしれません。
基本的には目論見通り、テストや調整のコスト削減につながって良かったと言える感覚です。が、弊社ゲームの既存手法と比べると別のところでコストが新たに発生しており、なかなか八方うまくは収まらないなあと思いました。
ただこれはあくまで最初の試行であり、この方向でうまくやればなにか新境地があったりするかもしれません。
新しく1本ゲームを作るという研修、こういった試行錯誤も含めて多くの学びがあります。
現状まだ道半ばでいろいろあって修羅っていますが、なんとかいいゲームができるように頑張ってゆきたいです。
またここで得た経験を生かしたりして次なる手法の改善を考え、よりゲームの本質的な品質アップを目指して運動してゆきたいです。
そんなわけでまた変な実験を始めたら生暖かく応援よろしくお願いいたしますm(_ _)m>社内
次回の
【その1】ドリコム Advent Calendar 2015は、僕の教育担当でもある@shinya_131さんの
エンジニアからデータ分析になって3ヶ月が経ったです。