はじめに
こんにちは、ソーシャルゲーム事業部 Unityエンジニアの佐藤です。
今年は体重が9kg増加するという成長ぶりでした( ・`ω・´)
もうちょっとで桁が一つ増えるところまで来てしまいました...(´・ω・`)
この記事はカヤックUnityアドベントカレンダー2016 20日目の記事となります。
今回は、社内で使っているIDLについてご説明したいと思います。
Baalとは
BaalはKAYACで用いているIDL(インターフェース定義言語)です。
Unityで作ったクライアントアプリと、サーバーが通信する際のデータ形式の定義をしたものです。
ドキュメントの生成や、データ定義に基づいたC#ファイルの生成などを行います。
Baalを導入した経緯
Baal導入以前は、サーバーサイド担当のエンジニアとクライアント担当のエンジニアでAPIの設計を話して作るというフローでしたが、
- 設計の認識にズレが生じることがある
- エンドポイント毎に、APIを実行するクラスやレスポンスのデータ型、パーサーを書くのが大変
といった問題が度々発生しました。
それらの問題を解決するためにBaalが導入されました。
Baalは、APIやデータの型の定義する書式から、APIの実装やデータの型クラスファイル、パーサーを自動で生成することができます。
Baalの利用例
- データ型の定義(ステージの構成・敵の配置・アイテムの効果など)
- APIの定義(リクエスト・レスポンス)
Baalの使い方
Baalの定義例です。 ユーザーがログインするAPIのサンプルで紹介したいと思います。
定義を元に、C#のソースコードを生成したいと思います。
ランタイムはat.pkgs.baalを使用します。
生成されたファイルは下記となります。
// UserAPI_generated.cs /* * This file is auto-generated by program. * Changes to this file may lost. */ using System.Collections.Generic; using Kayac; using Kayac.Net.Http; using Models; using Models.Data; using Models.Data.Response; namespace Models.Service { /// <summary> /// ユーザーに関するAPI /// </summary> public sealed partial class UserAPI : APIBase<UserAPI.Api> { public enum Api { Login } /// <summary> /// ログイン /// このメソッドはリクエストをキャンセルできません /// </summary> public Operation<LoginResponse> Login( System.String email, System.String password ) { return Login( email, password, CancellationToken.None ); } /// <summary> /// ログイン /// </summary> public Operation<LoginResponse> Login( System.String email, System.String password, CancellationToken cancellationToken ) { var context = GetContext(HttpMethod.Post, "api/login", Api.Login); context.AddParameter("email", email); context.AddParameter("password", password); return context.GetResponseAsync<JsonResponse<LoginResponse>>(cancellationToken). Select(resp => resp.Result.resultObject); } } }
// LoginResponse_generated.cs namespace Data.Response { public class LoginResponse { public System.Boolean result { get; private set; } } }
このようにBaalを用いてデータ定義をクラスにしたり、API定義を自動で実装したり...ということをKAYACではやっています。
また、データ型の継承もBaal定義で行うことが出来ます。
namespace Data.Request { abstract entity WithDeviceId { DeviceId: !string } entity LoginRequest += WithDeviceId // ←←DeviceIdがLoginRequestクラスに追加される { Email: !string; Password: !string; } }
生成するファイルのテンプレートをカスタムできるので、プロジェクト毎に必要な形式を用意できます。
実務での利用
- GitHubを用いている場合は、Baal定義のプルリクエストを作り、サーバー/クライアントエンジニアでレビューする
- Git Subtreeを用いて、サーバーとクライアント、それぞれのリポジトリに定義を反映する
- Baal定義に問題がないか、自動テストをまわす
- Baal定義からのソースコード生成をJenkinsのジョブにする
といったようにプロジェクト毎にBaalのワークフローを拡張して開発速度や精度をあげる取り組みを行っています。
おわりに
明日はアファトのパフォーマンスチューニングについての記事です。
サクサク動くゲームってそれだけで楽しくなりますよね! ヒントは明日の記事にあるかと思いますので、ぜひ御覧ください!!