Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

いろいろ見せますLord of Knightsのクライアント開発事例紹介

61,085 views

Published on

パソナテックエンジニアカフェで話すスライドです。
http://atnd.org/events/26591

Unityで作ったオンラインゲームの開発事例とC#を使った通信設計周りの話です。

Published in: Technology
  • Be the first to comment

いろいろ見せますLord of Knightsのクライアント開発事例紹介

  1. 1. いろいろ見せます❤Lord of Knights のクライアント開発事例紹介 株式会社 Aiming リードソフトウェアエンジニア 細田幸治 2012/04/10
  2. 2. こんばんは
  3. 3. ゲーム開発超楽しいで す。
  4. 4. そのなかでも
  5. 5. オンラインゲーム開発 めっちゃ楽しい❤
  6. 6. 私は
  7. 7. 細田幸治といいます。http://www.facebook.com/kouji.hosodaLord of Knights のクライアント開発のチーフをしています。以後お見知りおきを。
  8. 8. というわけで
  9. 9. Lord of Knights 開発事例紹介
  10. 10. 話すこと● ゲーム紹介● 開発あるあると改善の話● Unity+HTML で作るハイブリッドアプリ● C#を活用した非同期通信アプリ
  11. 11. 時間があれば● AppleStoreの審査あれこれ
  12. 12. この発表のターゲット● ゲーム開発ってどうやってるのか興味がある人● ある程度 Unity & C# を触ってる人● これからオンラインゲーム作りたい人
  13. 13. はじめに
  14. 14. ゲーム紹介
  15. 15. どんなゲーム?カードを強化して戦うストラテジー RPG メインプレイは内政、カード強化、バトルのサイ● クル● 多人数で1つのマップを共有する戦略ゲーム ○同盟を組んで協力プレイ ○他の同盟と競争して目標となる拠点を奪い合 う
  16. 16. どんなゲーム?おかげさまでApp Storeの→トップ25→トップ無料で5位になりました※2012/04/07現在
  17. 17. どんなゲーム?詳しくは Web へhttp://lordofknights.jp
  18. 18. 開発あるあると改善の話
  19. 19. まず
  20. 20. 開発の前提
  21. 21. 大事なことは● チームみんなで楽しく開発すること● そのための工夫や改善をひたすら頑張る ○言いだしっぺが主導して頑張る● 何があっても楽しく、あわてない
  22. 22. 具体的事例紹介
  23. 23. 開発規模● クライアント開発 3-8人● サーバー開発約 5人● 企画 3人● デザイン 3人の約 20人でリリースまで 8ヶ月半現在はリリースされたので運営とマーケティングも加わりもっと増えてる
  24. 24. 問題1● 企画とエンジニアのすれ違いが多くて仲が悪い● 部署ごとに部屋を区切られていてコミュニケー ションが取りづらい
  25. 25. あるある
  26. 26. これは最初から対策
  27. 27. チームの席は一緒● 企画、エンジニア、デザイン、運営など必要なメ ンバー全員で1チーム● メンバーの席は近くする
  28. 28. チームの席は一緒● すごいリーダー(総責任者、仕様判断、運営判 断、なんでも判断)が中心 すごい リーダー
  29. 29. チームの席は一緒● 企画リーダーとエンジニアリーダーがその近く すごい リーダー エンジニ 企画リー ア ダー リーダー
  30. 30. チームの席は一緒● UIデザイナーが企画リーダーの近く すごい リーダー エンジニ 企画リー ア ダー リーダー UIデザ イナー
  31. 31. チームの席は一緒● テクニカルアーティストはUIデザイナーとエンジ ニアの近く すごい リーダー エンジニ 企画リー ア ダー リーダー UIデザ TA イナー
  32. 32. チームの席は一緒● 運営が企画とリーダーの近く 運営 すごい リーダー エンジニ 企画リー ア ダー リーダー UIデザ TA イナー
  33. 33. チームの席は一緒● エンジニアや企画のメンバーは各リーダーの近 く 運営 すごい 企画 リーダー エンジニ エンジ 企画リー ニア ア ダー リーダー 企画 エンジ UIデザ TA ニア イナー
  34. 34. チームの席は一緒● 新人は各リーダーの近く 運営 すごい 新人 企画 リーダー エンジニ エンジ 企画リー ニア ア ダー 新人 リーダー 企画 エンジ UIデザ TA ニア イナー
  35. 35. チームの席は一緒結果結果● 必要な人にすぐ判断を仰げる● 関連する会話が自然と耳に入る● 新人が放置されにくい
  36. 36.
  37. 37. 問題2● 他のメンバーが何をやっているか分からない● 問題があったときに誰に相談したらいいか分か らない ?
  38. 38. あるある
  39. 39. ありました
  40. 40. 朝会
  41. 41. 朝会● チーム全員で朝一で集まって立ったまま10-15 分で● 当日やること、分かってる懸念点を報告● 難しい話はしない ○長くなるなら後で個別に話し合う
  42. 42. 朝会結果結果● 全員の動きが把握できた● 問題はチームで共有● 短時間に出来れば特にデメリットは無い
  43. 43.
  44. 44. 問題3● 朝会の時に昨日やったことを忘れている● 問題報告が遅れる● 残業が多い
  45. 45. あるある
  46. 46. ありました
  47. 47. 夕会
  48. 48. 夕会● チーム全員で終業時間前に集まって立ったまま 10-15分で● 忘れないうちに報告 ○当日達成できたこと ○出た問題点● 残業の必要性を報告 ○その日のうちにやらなくていいと判断したら帰る
  49. 49. 夕会結果結果● 夕会で報告が済むので次の日から朝会が短く なった● 問題共有の漏れが減り、共有も早くなった● 残業が減った!
  50. 50.
  51. 51. 問題4リモート会社との仕事をしている時● チャットやメールだけだとお互い仕事の進みが 見えず足並みがそろわない● 問題発見が遅れる ??
  52. 52. ある(ry
  53. 53. 週例ビデオチャット会議● お互い顔を見ながら30分以内で簡潔に● 進捗報告と問題共有、改善共有● 雑談も交えつつ
  54. 54. 週例ビデオチャット会議結果結果● 合意が作りやすい ○すれ違いが減る● 見えていなかった問題がぽろっとでてくる● 仲良くなれる
  55. 55.
  56. 56. 問題5● どの実装を優先すべきか分からない● 実装中に仕様抜け(必要なのに決まってない仕 様があること)がぽろぽろでる ?
  57. 57. ある(ry
  58. 58. ユーザー体験をリスト化
  59. 59. ユーザー体験をリスト化● ユーザーの体験(ストーリー)ベースで出来るこ とをリストアップ● 上記をマイルストーンごとにまとめ、いつどんな 体験が出来るかが一覧できる● すごいリーダーが優先順位をつけてどれが大事 か決定する
  60. 60. ユーザー体験をリスト化結果結果● 次にやることが明確になった● ストーリーを書く段階で仕様抜けにあるていど 気づける● これをマスターストーリーリストって言うらしい
  61. 61. マスターストーリーリストこんなの (ユーザーが)何をどうできる というように具体的に書く
  62. 62. マスターストーリーリストこんなの フローを工夫しないと 管理が大変
  63. 63.
  64. 64. 問題6● スケジュール通りに終わらない● デスマーチになる
  65. 65. ある(ry
  66. 66. タスクの増加・消化を可視化
  67. 67. タスクの増加・消化を可視化● マイルストーン終了までに必要な総タスク数をカ ウント● 毎週タスク数をカウントしてグラフ化 ○総タスクの増減 ○消化タスク数 ○週当たりの平均値● 総タスクが増えたら、その理由を記録
  68. 68. タスクの増加・消化を可視化結果結果● 遅れはじめたらすぐ分かるようになった● いつごろ終わるか予測が立つようになった● 何で遅れたか把握でき、不安が減った● リリースバーンダウンチャートって言うらしい
  69. 69. リリースバーンダウンチャートこんなの(OBTリリースまでの実際のチャート)
  70. 70. リリースバーンダウンチャートこんなの(OBTリリースまでの実際のチャート) スケジュールが 延びた実例
  71. 71. リリースバーンダウンチャートこんなの(OBTリリースまでの実際のチャート)タスク25個からスタート
  72. 72. リリースバーンダウンチャートこんなの(OBTリリースまでの実際のチャート) 線形的に増えて
  73. 73. リリースバーンダウンチャートこんなの(OBTリリースまでの実際のチャート) 最終的に約70個に
  74. 74. リリースバーンダウンチャートこんなの(OBTリリースまでの実際のチャート) 約3倍のずれ ヒャッハー!!
  75. 75. リリースバーンダウンチャートこんなの(OBTリリースまでの実際のチャート) でも週の消化数は 平均して7出てる
  76. 76. リリースバーンダウンチャートこんなの(OBTリリースまでの実際のチャート) 平均速度から リリースを予測可能
  77. 77. ここまでのまとめ
  78. 78. 結果アジャイル開発に なりました
  79. 79. 現在の問題いまはリリース直後で作業の割り込みが多く、優先度がころころ変わってる↓中長期のスケジュールが立っていない↓どうしたらいいか試行錯誤中
  80. 80. 大事なことは?● リスクの早期発見と改善が基本セット● チームみんなで作るという意識(自発的である)● 何があっても楽しく、あわてない● 何でも言えるチームの空気上記が実現できれば細かい手法は問わない
  81. 81. 開発プロセスの話はここ まで
  82. 82. 続いて技術の話
  83. 83. Unity! Unity!
  84. 84. Unity + HTMLで作る ハイブリッドアプリ
  85. 85. Unity×HTMLな理由● Unity で UI 作るの大変!● 内政、マップ、レポート、メール、ショップ、合成、 カード・・・・・・など 40画面以上!● リスト系など動きが少ない画面はHTMLの方が 作りやすい!
  86. 86. HTMLを使うメリットぱっと見区別できないぐらい自然 Unity画面 HTML画面
  87. 87. HTMLを使うメリットその2リリース後のアップデートがしやすい● 審査なしでアップデート可能 ○ キャンペーンページなどの自由が利きやすい HTML画面
  88. 88. HTMLを使うメリットその3自由文字入力ができる● iPhone 上でフォントに使えるテクスチャサイズ に制限がある(EZ GUI) ○ 1つのフォントごとに 2048*2048 ピクセルのテクスチャに 収める必要がある(iPhone4以降)● HTML だと上記のような制限がない ○ チャットなど自由入力出来る画面は HTML で作成
  89. 89. HTMLを使うデメリット● ローディングが長い● 反応が遅い ○ どうしてもユーザー体験が落ちる● メモリーを喰う ○ ゲーム内メールなどのリストを追加読み込みし続けると 突然落ちたりする● エディターで確認できないところがある ○ 後で説明する Unity と HTML との連携部分
  90. 90. HTMLとUnityの連携仕様● 連携とは ○ HTML 側から Unity の関数を呼び出す仕組みの事● なにに使うか? ○ クエストの達成判定 ○ サーバーと Unity 内モデルのデータ同期 ○ Unity の画面遷移やUIの操作
  91. 91. HTML×Unity 実装● 実装方法 ○ Native Plugin として実装 ○ Objective-C の UIWebView を利用UIWindow *window =[[UIApplication sharedApplication] keyWindow];// 基本クラスのインスタンス作るだけでOKUIWebView *webView = [[UIWebView alloc]initWithFrame:CGRectMake(0,0,width,height)];[window addSubview:webView];
  92. 92. HTML×Unity 実装shouldStartLoadWithRequest を使ってクエリストリングをパースクエリストリングとは URL の後ろにつく ?aho=foo&hoge=bar みたいなやつUIWebViewNavigationType が以下の場合に処理 UIWebViewNavigationTypeFormSubmitted UIWebViewNavigationTypeLinkClicked UIWebViewNavigationTypeOther
  93. 93. HTML×Unity 実装shouldStartLoadWithRequest を使ってクエリストリングをパースパース処理部分NSString *query = [[request URL] query];if(query == nil) return YES;NSArray *parsedStrings = [query componentsSeparatedByString:@"&"];for (NSString *q in parsedStrings){ char* key = [[[q componentsSeparatedByString:@"="]objectAtIndex:0]}
  94. 94. HTML×Unity 実装UnitySendMessage でパースしたデータを送信Objective-C側でメッセージ送信 if(strcmp(key,"change_scene") == 0) { UnitySendMessage(gameObjectName, "ChangeScene", value); }Unity側でメッセージ受信 void ChangeScene(string targetScneneName) { Appllication.LoadLevel(targetScneneName); }
  95. 95. HTML×Unity 実装● フォルダ構成 ○ Plugins/iOS 以下に Objective-C のコードを配置 ○ ビルド時に Unity が自動的に Xcode のプロジェクトにコ ピーしてくれる
  96. 96. HTML×Unity 実装● ブラウザが操作不能になる問題が出た ○ Unity 側が自動生成する AppCotroller.mm の描画フラ グを変更(@Unity3.4) ○ #define USE_DISPLAY_LINK_IF_AVAILABLE 0
  97. 97. C# を活用した非同期通信アプリ
  98. 98. 非同期通信って何?サーバーと通信する時に結果を待っている間フリーズしてプログラムが止まっているのが同期通信。サーバーと通信する時に、結果を待たずにプログラムは続行し、結果が返ってきたら通信処理の続きが実行されるようにするのが非同期通信。ゲームなどではフリーズを防ぐために通信処理は非同期通信で実装する必要がある。
  99. 99. 非同期通信って何?ようするにめんどくさい
  100. 100. 非同期通信アプリの設計指針● 通信の実装を気にしたくない● 処理を直感的に書きたい● エラーもあまり気にしたくない● サーバー実装に依存したくない● 簡単に View に反映させたい
  101. 101. なぜそうするか
  102. 102. 1つ1つ解説します
  103. 103. 通信の実装を気にしたくない良くあることよくあること● 仕様が変わる● 仕様変わったら通信実装も色々変わる ○ APIのインターフェイスの修正 ○ データのシリアライズ ○ バリデーション
  104. 104. 通信の実装を気にしたくない結果結果● 表示部分の実装、確認がなかなかできない● バグりやすい↓仕様変更、追加コストが高いってなってしまう。
  105. 105. 通信の実装を気にしたくない そこで
  106. 106. 通信の実装を気にしたくない通信実装コードの自動生成
  107. 107. 通信の実装を気にしたくない通信実装コードの自動生成● https://github.com/ppcuni/rpcoder ※ 動かすには LitJSON の微修正必要なので参考程度に● 定義ファイルから実装コードを自動生成する ツール● アプリケーション層で通信実装を気にする必要 はないようになってる
  108. 108. 通信の実装を気にしたくない定義ファイル# ユーザ登録しログインするRPCoder.function "registerUser" do |f| f.path = "/startup/regist.php" # エンドポイント URL f.method = "POST" # 通信メソッド f.add_param :invitation_code, "String",{:require => false} #招待コード f.add_param :user_name, "String" # 登録ユーザ名 f.add_param :card_number, "int" # 初期カード番号 f.add_param :direction_id, "int" # 方角ID f.add_return_type :login_user_info, "LoginUserInfo" # ユーザーの全情報 f.description = "ユーザ登録する"end
  109. 109. 通信の実装を気にしたくない定義ファイル# ユーザ登録しログインするRPCoder.function "registerUser" do |f| APIを定義 f.path = "/startup/regist.php" # エンドポイント URL f.method = "POST" # 通信メソッド f.add_param :invitation_code, "String",{:require => false} #招待コード f.add_param :user_name, "String" # 登録ユーザ名 f.add_param :card_number, "int" # 初期カード番号 f.add_param :direction_id, "int" # 方角ID f.add_return_type :login_user_info, "LoginUserInfo" # ユーザーの全情報 f.description = "ユーザ登録する"end
  110. 110. 通信の実装を気にしたくない定義ファイル# ユーザ登録しログインするRPCoder.function "registerUser" do |f| f.path = "/startup/regist.php" # エンドポイント URL f.method = "POST" # 通信メソッド エンドポイントURL f.add_param :invitation_code, "String",{:require => false} #招待コード f.add_param :user_name, "String" # 登録ユーザ名 f.add_param :card_number, "int" # 初期カード番号 f.add_param :direction_id, "int" # 方角ID f.add_return_type :login_user_info, "LoginUserInfo" # ユーザーの全情報 f.description = "ユーザ登録する"end
  111. 111. 通信の実装を気にしたくない定義ファイル# ユーザ登録しログインするRPCoder.function "registerUser" do |f| f.path = "/startup/regist.php" # エンドポイント URL f.method = "POST" # 通信メソッド Method f.add_param :invitation_code, "String",{:require => false} #招待コード f.add_param :user_name, "String" # 登録ユーザ名 f.add_param :card_number, "int" # 初期カード番号 f.add_param :direction_id, "int" # 方角ID f.add_return_type :login_user_info, "LoginUserInfo" # ユーザーの全情報 f.description = "ユーザ登録する"end
  112. 112. 通信の実装を気にしたくない定義ファイル# ユーザ登録しログインするRPCoder.function "registerUser" do |f| f.path = "/startup/regist.php" # エンドポイント URL f.method = "POST" # 通信メソッド f.add_param :invitation_code, "String",{:require => false} #招待コード f.add_param :user_name, "String" # 登録ユーザ名 f.add_param :card_number, "int" # 初期カード番号 f.add_param :direction_id, "int" # 方角ID 引数いろいろ f.add_return_type :login_user_info, "LoginUserInfo" # ユーザーの全情報 f.description = "ユーザ登録する"end
  113. 113. 通信の実装を気にしたくない定義ファイル# ユーザ登録しログインするRPCoder.function "registerUser" do |f| f.path = "/startup/regist.php" # エンドポイント URL f.method = "POST" # 通信メソッド f.add_param :invitation_code, "String",{:require => false} #招待コード f.add_param :user_name, "String" # 登録ユーザ名 f.add_param :card_number, "int" # 初期カード番号 戻り値 f.add_param :direction_id, "int" # 方角ID f.add_return_type :login_user_info, "LoginUserInfo" # ユーザーの全情報 f.description = "ユーザ登録する"end
  114. 114. 通信の実装を気にしたくない自動生成されるもの● API のインターフェイスクラス● API の実装クラス● API の Mock クラス● 型の実装クラス C#● 型のシリアライザ、デシリアライザ
  115. 115. 通信の実装を気にしたくない 色々めんどくさいところ作ってくれるバグがあってもテンプレート直せばOK
  116. 116.
  117. 117. 処理を直感的に書きたい良くあることよくあること● リクエストとレスポンスの処理が分離している● 非同期処理を連続して行うときにカオスになる
  118. 118. 処理を直感的に書きたい結果結果● コードの見通しが悪い● 通信時に何処で何が起きてるか分からない● バグりやすい↓仕様変更、追加コストが高いってなってしまう。
  119. 119. 処理を直感的に書きたい そこで
  120. 120. 処理を直感的に書きたいメソッドチェインで書けるように
  121. 121. 処理を直感的に書きたい記述例var task = IncrementAsync(1) // タスク完了時に呼ばれる完了処理(2を出力) .OnComplete(t => UnityEngine.Debug.Log(t.Result)) // ↑のタスク成功時に別のタスクを繋げる .ContinueWithTask<int>(IncrementAsync) // ↑のタスク完了時に呼ばれる完了処理(3を出力) .OnComplete(t => UnityEngine.Debug.Log(t.Result));
  122. 122. 処理を直感的に書きたい記述例var task = IncrementAsync(1) // タスク完了時に呼ばれる完了処理(2を出力) 非同期呼び出し .OnComplete(t => UnityEngine.Debug.Log(t.Result)) // ↑のタスク成功時に別のタスクを繋げる .ContinueWithTask<int>(IncrementAsync) // ↑のタスク完了時に呼ばれる完了処理(3を出力) .OnComplete(t => UnityEngine.Debug.Log(t.Result));
  123. 123. 処理を直感的に書きたい記述例var task = IncrementAsync(1) // タスク完了時に呼ばれる完了処理(2を出力) .OnComplete(t => UnityEngine.Debug.Log(t.Result)) // ↑のタスク成功時に別のタスクを繋げる非同期結果受け取り .ContinueWithTask<int>(IncrementAsync) // ↑のタスク完了時に呼ばれる完了処理(3を出力) .OnComplete(t => UnityEngine.Debug.Log(t.Result));
  124. 124. 処理を直感的に書きたい記述例var task = IncrementAsync(1) // タスク完了時に呼ばれる完了処理(2を出力) .OnComplete(t => UnityEngine.Debug.Log(t.Result)) // ↑のタスク成功時に別のタスクを繋げる 続けて行う非同期処理 .ContinueWithTask<int>(IncrementAsync) // ↑のタスク完了時に呼ばれる完了処理(3を出力) .OnComplete(t => UnityEngine.Debug.Log(t.Result));
  125. 125. 処理を直感的に書きたい記述例var task = IncrementAsync(1) // タスク完了時に呼ばれる完了処理(2を出力) .OnComplete(t => UnityEngine.Debug.Log(t.Result)) // ↑のタスク成功時に別のタスクを繋げる 非同期結果受け取り .ContinueWithTask<int>(IncrementAsync) // ↑のタスク完了時に呼ばれる完了処理(3を出力) .OnComplete(t => UnityEngine.Debug.Log(t.Result));
  126. 126. 処理を直感的に書きたい すっきり
  127. 127. 処理を直感的に書きたい実装的には非同期処理用のクラスを作成● 内部処理は yield を利用したコルーチン● コルーチンの完了をメソッドチェインで書ける● 次のコルーチンをメソッドチェインで繋げる
  128. 128.
  129. 129. エラーもあまり気にしたくない良くあることよくある● API ごとにエラー処理が分散している● 連続してエラーが起きたときに最後のエラーし か分からない
  130. 130. エラーもあまり気にしたくない結果結果● エラー実装がめんどくさい● バグ調べにくい↓仕様変更、追加コストが高いってなってしまう。
  131. 131. エラーもあまり気にしたくない そこで
  132. 132. エラーもあまり気にしたくない● すべての非同期処理を共通化 ○ 根っこ部分で try/catch してエラーハンドリング ○ エラーダイアログを出したりする処理も共通化● 個別エラー処理も可能に ○ エラーが複数発生したらキューにして全エラーを保持 ○ エラーはタスクをまたいで次のタスクに伝播、後でチェッ クできる
  133. 133. エラーもあまり気にしたくない View はだいたい正常系だけ書けば OK
  134. 134.
  135. 135. サーバー実装に依存したくない良くあることよくあること● サーバーの実装が完了しないと画面確認できな い● 通信エラーが起きたときの再現が取れない
  136. 136. サーバー実装に依存したくない結果結果● 実装のFixが延び延びになる● バグ調べにくい↓仕様変更、追加コストが高いってなってしまう。
  137. 137. サーバー実装に依存したくない そこで
  138. 138. サーバー実装に依存したくない Mock
  139. 139. サーバー実装に依存したくないMock とは クライアント● 擬似サーバー Mock● クライアントだけで完結● ソースの変更無しで サーバーと切り替えられ Server る
  140. 140. サーバー実装に依存したくないMock を使うと● サーバー実装スケジュールとの依存が少ない● 異常系の確認も手軽にできる
  141. 141. サーバー実装に依存したくないMock 実装の例
  142. 142. サーバー実装に依存したくない しばらくサーバーいらず
  143. 143.
  144. 144. 簡単に View に反映させたい良くあることよくあること● View で Polling してデータをチェック→反映 ○ GameObject の Update の中でチェックする感じ ○ Unity3.5 のプッシュ通知の初期化周りとかがそんな感じ
  145. 145. 簡単に View に反映させたい結果結果● チェック頻度が高いと負荷が高い● チェック頻度が低いと画面反映が遅れる● チェックコード自体書きたくない↓余計な負荷、ユーザー・エンジニア体験の悪化ってなってしまう。
  146. 146. 簡単に View に反映させたい そこで
  147. 147. 簡単に View に反映させたいイベントドリブンで View を更新
  148. 148. 簡単に View に反映させたい 実装例public class CityModel{ // 資源の増減通知 public event Action<ResourceStatus> Updated;}public class CityView : Aiming.TSS.Infrastructure.EventDrivenBehavior{ void Start() { // 資源の増減通知を購読、解除設定 _cityModel.Updated += OnResourceUpdated; base.AddDisposable(_cityModel, x => x.Updated -= OnResourceUpdated); }}
  149. 149. 簡単に View に反映させたい 実装例public class CityModel{ // 資源の増減通知 public event Action<ResourceStatus> Updated;} イベントを定義public class CityView : Aiming.TSS.Infrastructure.EventDrivenBehavior{ void Start() { // 資源の増減通知を購読、解除設定 _cityModel.Updated += OnResourceUpdated; base.AddDisposable(_cityModel, x => x.Updated -= OnResourceUpdated); }}
  150. 150. 簡単に View に反映させたい 実装例public class CityModel{ // 資源の増減通知 public event Action<ResourceStatus> Updated;}public class CityView : Aiming.TSS.Infrastructure.EventDrivenBehavior{ += でイベント void Start() { 購読開始 // 資源の増減通知を購読、解除設定 _cityModel.Updated += OnResourceUpdated; base.AddDisposable(_cityModel, x => x.Updated -= OnResourceUpdated); }}
  151. 151. 簡単に View に反映させたい 実装例public class CityModel{ // 資源の増減通知 public event Action<ResourceStatus> Updated;}public class CityView : Aiming.TSS.Infrastructure.EventDrivenBehavior{ イベント購読 void Start() { 解除を予約 // 資源の増減通知を購読、解除設定 _cityModel.Updated += OnResourceUpdated; base.AddDisposable(_cityModel, x => x.Updated -= OnResourceUpdated); }}
  152. 152. 簡単に View に反映させたいイベントを受け取った時の処理public class CityView : Aiming.TSS.Infrastructure.EventDrivenBehavior{ void OnResourceUpdated(ResourceStatus resource) { // テキストフィールド更新 _currentManaText.Text = resource.CurrentMana.ToString(); }}
  153. 153. 簡単に View に反映させたいイベントを受け取った時の処理public class CityView : Aiming.TSS.Infrastructure.EventDrivenBehavior{ void OnResourceUpdated(ResourceStatus resource) { // テキストフィールド更新 _currentManaText.Text = resource.CurrentMana.ToString(); }} 表示処理だけ書けばOK
  154. 154. 簡単に View に反映させたい● View の作成時に Model の変更イベントを購読● View の破棄、非表示時にイベント購読を解除● 購読と解除は近くに記述できるようにする
  155. 155. 簡単に View に反映させたい すっきり
  156. 156. ちなみに通信実装は
  157. 157. 通信実装で使ったもの● 通信処理は Unity の WWW クラスを利用● データフォーマットは JSON● JSON のパースに LitJSON を改良して利用 ○ http://sourceforge.jp/projects/sfnet_litjson/ ○ ライセンスがゆるい ○ ソースコードがフルオープン
  158. 158. まとめると
  159. 159. まとめ● 自動生成いいね● 直感的に書けるのいいね● エラーは簡単に処理できるのいいね● Mock いいね● イベントいいね
  160. 160. 以上技術の話でした
  161. 161. 最後にとにかく楽しむどんなトラブルも懸念事項も前向きに取り組めば楽しいクエストになります
  162. 162. ゲーム開発超楽しい❤
  163. 163. ご清聴ありがとうございました
  164. 164. あそびにきてね!株式会社 Aiming はオフィス見学をいつでも受け付けています。興味がある方はお気軽にご連絡ください。
  165. 165. おまけ
  166. 166. AppleStoreの審査あれこれ初めての iPhone アプリリリースだったノウハウがなかったので試行錯誤
  167. 167. 審査についてリリースまでにリジェクト3回されましたリジェクト理由その1● キャッシュファイルの保存場所が悪くてアウト! ○永続化用と一時用があるので気をつける 保存場所を直して解決 ○
  168. 168. 審査についてリジェクト理由その2● レビュアーが想定通りに行動しなくてアウト! ○審査専用アカウントかどうかで、審査用サーバーか本番 サーバーかをスイッチしていたが、レビュアーが専用アカ ウントを使ってくれなかった クライアントのバージョンでサーバーをスイッチするように ○ して解決
  169. 169. 審査についてリジェクト理由その3● 審査中にメンテをしたらレビュアーがログインで きなくなってアウト ○In Reviewになったらメンテを予定していたとしてもリスケ ジュールする ○次からワークフローに落とし込んで解決
  170. 170. 審査についてどのくらいで通るの?● だいたい審査出してから約5営業日で審査開始 (In Review)、だいたいその数時間後に結果出る● 場合によってはIn Reviewのまま1日過ぎることも あるので油断しない
  171. 171. 審査についてどういう判断基準?● 審査のたびに判断基準がまちまち● 深く見られる時もあれば一瞬でOKでる時も
  172. 172. 審査についてとにかく地雷が多いので● なるべく早く最初の審査をだす● 早くたくさん地雷を踏む● 審査提出時は2人以上でダブルチェック
  173. 173. おわり

×