SlideShare a Scribd company logo
1 of 79
Orange Cube
自社フレームワーク
++C++;
Orange Cube
岩永信之
自己紹介
• C#でぐぐれ
• C#でiOS/Androidゲームを作っています
本日の話
• 自社フレームワークの話
• 今、オープンなのは IteratorTasks だけ
• できれば随時オープン化していきたい
• 要求と解決策を中心に話す
• チームが作っているゲームの性質・要求
• 要求に対する技術的な課題
• Unityという縛りの中での課題
• どうフレームワークを整備したか
• 見せれる範囲で実際のコード
• 実物デモ
背景
どういうものを作っていて、どういう要求があった
チームが作っているもの
1. ストラテジー
2. RPG、リアルタイム バトルもの
3. ストラテジー
前提: 作っているゲームの性質
• サーバーとの通信だらけ
• 非同期処理を楽にしたい
• 差分更新、更新された部分の変更通知がほしい
• アクション性は低い/結構なページ数
• ゲーム系フレームワークよりも、UI系フレームワーク使いたい
こんなフレームワークができあがりました
• IteratorTasks
• TaskInteraction
• TaskNavigation
• TypeGen
• Inventories/MasterRepository
• Binding-CodeGen
ライブコーディングでデモあり
非同期処理
IteratorTasks
System.Threading.Tasks.Task もどき
非同期処理
• スマホゲームなんて非同期処理の塊
• いろんなロジックがサーバー上で動いてる
• サーバーからもらったデータを表示
• そうでなくても、ネイティブUIには非同期処理が必要
• 参考: フリーズしないアプリケーションの作り方
エンド・ユーザーは、
0.5秒のフリーズでストレスを感じ、
3秒のフリーズはバグだと思う
例: バイト列読み込み
• 同期
static byte[] ReadBytes(Stream s, int n)
{
var buffer = new byte[n];
s.Read(buffer, 0, n);
return buffer;
}
ここでフリーズ
の可能性あり
例: バイト列読み込み
• begin/end、コールバック式
static void ReadBytes(Stream s, int n, Action<byte[]> callback)
{
var buffer = new byte[n];
s.BeginRead(buffer, 0, n, r =>
{
var result = s.EndRead(r);
callback(buffer);
}, null);
}
2個のメソッドをペアで
呼ぶ必要あり
後ろにさらに処理がつづいたり、
分岐・ループさせるとかなり面倒
例: バイト列読み込み
• ContinueWith※、コールバック式
static Task<byte[]> ReadBytes(Stream s, int n)
{
var buffer = new byte[n];
return s.ReadAsync(buffer, 0, n).ContinueWith(t => buffer);
}
※ 他のプログラミング言語だと Then という名前が多い
いわゆる継続処理(continuation)
後ろにさらに処理がつづいたり、
分岐・ループさせるとかなり面倒
例: バイト列読み込み
• await(C# 5.0※)
• C#的には5.0(2012年に正式版)で解決した問題
• “Unityでなければ”、3年前に解消されているはずの問題
static async Task<byte[]> ReadBytes(Stream s, int n)
{
var buffer = new byte[n];
await s.ReadAsync(buffer, 0, n);
return buffer;
}
同期の場合とほぼ同じ
書き方で、フリーズしない
※ UnityはC# 3.0。つらい。本気でつらい。日々ソウルジェム濁る
IteratorTasks
• しょうがないんで「もどき」を使って運用してる
• UnityがCoroutine(yield return)ベースの非同期処理なんで、同じ方針の、
Task互換ライブラリを作って使ってる
• yield return+コールバック式のメソッドを、Task互換のクラスに変換
• Coroutineと比べた利点
• MonoBehaviourに依存しない、UnityEngine.dllに依存しない
• 戻り値を返せる
IteratorTasks
https://github.com/OrangeCube/IteratorTasks
例: バイト列読み込み
• iterator → Task
• C#的には5.0(2012年に正式版)で解決した問題
• “Unityでなければ”、3年前に解消されているはずの問題
static Task<byte[]> ReadBytes(Stream s, int n)
{
return Task.Run<byte[]>(c => ReadBytesIterator(s, n, c));
}
static IEnumerator ReadBytesIterator(Stream s, int n, Action<byte[]> callback)
{
var buffer = new byte[n];
var t = s.ReadAsync(buffer, 0, n);
if (!t.IsCompleted) yield return t;
callback(t.Result);
}
await の代わりに
yield return
1段ラップ
return result の代わりに
callback(result) 作る側は相変わらず面倒だけども、
使う側は幾分かマシに
互換
• 標準TaskとIteratorTasksでコード共有
• 結構 #if 分岐でいける
• 実際、後述のTaskInteraction, TaskNavigation, 通信コード生成 は
#if で両対応してる
#if UseIteratorTasks
yield return Task.Delay(_pollingIntervalMilliseconds);
#else
await Task.Delay(_pollingIntervalMilliseconds).ConfigureAwait(false);
#endif
await のところを
yield return に
反省: Rx使わないの?
• 値1つ取るだけ(ラウンドトリップ1回)の非同期処理にRxはいまいち
• (awaitと比べるとの話。begin/endとか同期よりはだいぶいい)
• (Coroutineそのまま使うくらいならRx推奨)
• 同期の時と同じフローで書けなきゃ嫌
• if → where、var → let になるのすら嫌
• if-else で困る
• イベント ストリーム的な非同期処理には、うちでもRx的なもの使ってる
• こっちはほんとにRxの本領
参考:Reactive Extensions(Rx)入門
UniRx
反省: バッド ノウハウすぎる
• 標準ライブラリの互換ライブラリなんてものは超バッド ノウハウ
• 要らなくなるべきもの
• UnityがMono 3系になるだけで無用の長物
• 「すぐに要らなくなるはずだろう」が全然すぐじゃなかった…
• おかげ様でものすごく安定したけども、それは恥だと思ってる
• 所詮は劣化コピー
• awaitと比べると不便
• スタック トレースとか追えない
反省: 両対応は大変
• IteraterTasks(IT)/System.Threading.Tasks(TT)両対応
#if 分岐
共通コード
IT版
ライブラリA
TT版
ライブラリA
IteratorTasks 標準ライブラリライブラリA
共通コード
ライブラリA
Unity
ゲーム
編集ツール(Desktop)や
サーバー
4つ1セット
反省: 両対応は大変
• ライブラリAに依存するライブラリBがあったとして
IteratorTasks
A
A.ForIterator
A.ForThreading
A.Shared
B
B.ForIterator
B.ForThreading
B.Shared
ライブラリ1個増やすだけでも
参照設定がかなり面倒
ビューとの相互アクション
TaskInteraction
チャネルを介したゲーム ロジックとビューとの非同期やり取り
やり取りの記録、再現
ビューとの通信
• よくあるシーケンス図
ビュー ゲーム ロジック サーバー
ボタンAをタップ
アニメーション表示
アニメーション表示
ボタンBをタップ
よくあるミス:
こいつが処理の起点
本来:
こいつが処理の主体
よくあるダメな実装
• ビューのイベントが起点で、そこに多くのコードが入る
class View : MonoBehaviour, IPointerClickHandler
{
public void OnPointerClick(PointerEventData eventData)
{
// ここにゲーム ロジック書く
}
} ダメ!絶対!
ビューとの通信
• ロジックが主体
ビュー ゲーム ロジック
結果のアニメーション表示
ボタンAをタップ
コマンド選択して
コマンドAが選ばれた
実行結果
アニメーション再生終わった
この辺り結構複雑な処理
• コマンド再入力が必要なことも
• アニメーションないときも
ここが起点
ベタなロジック実装
public void Start()
{
// 開始処理
var d = CommandSelecting;
if (d != null) d(candidates);
}
public event Action<CommandCandidate[]> CommandSelecting;
public void SelectCommand(CommandCandidate selected)
{
// 選ばれたコマンドを実行
var d = CommandExecuted;
if (d != null) d(commandResult);
}
public event Action<CommandCandidate[]> CommandExecuted;
public void EndCommand(CommandCandidate selected)
{
// ...
}
ビュー側に「コマンド選択して」
メッセージを投げる
ビュー側から「コマンド選択結果」
を呼んでもらう
Startの続きの処理
ここでいったん処理中断
ビュー側に「コマンド実行結果」
メッセージを投げる
ビュー側から「結果アニメーション再生終わった」
を呼んでもらう
SelectCommandの続きの処理
ベタなロジック実装の問題
public void Start()
{
// 開始処理
var d = CommandSelecting;
if (d != null) d(candidates);
}
public event Action<CommandCandidate[]> CommandSelecting;
public void SelectCommand(CommandCandidate selected)
{
// 選ばれたコマンドを実行
var d = CommandExecuted;
if (d != null) d(commandResult);
}
public event Action<CommandCandidate[]> CommandExecuted;
public void EndCommand(CommandCandidate selected)
{
// ...
}
処理がとびとび
• フロー図と合わせて見ない
と何してるのかわからない
呼んでほしいタイミングでだけ呼ばれる保証が
ない
• ダメなタイミングで呼ばれた時のエラー処理
が必要
• ビューを作る人がわかるドキュメントが必須
フレームワークによっては
• イベントの送り方、結果の戻し方が違ったりはする
using GalaSoft.MvvmLight.Messaging;
using System.Windows.Input;
class BattleEngine
{
private Messenger _messenger;
public void Start()
{
// 開始処理
_messenger.Send<CommandCandidate[]>(candidates);
}
public ICommand CommandSelecting { get; private set; }
}
※ WPF, MVVM Lightの例
• ビューにメッセージを送る用のライブラリがあったり
• ビューからの応答はメソッドじゃなくて、1段階クラスを挟んだり
• フレームワークに適したクラスを挟んでるだけで、
やっぱりメッセージ送信と応答の受信がわかれてしんどい
「メッセンジャー パターン」
とか言ったりする
解決の手がかり: ビューはTask
• ロジックから見て、ビュー上の動きは非同期処理(Task)
• (コマンド選択など)ユーザーのタップを1つ待つ
• (アニメーションなど)時間経過を待つ
public static Task AwaitTap(this Button button)
public static Task PlayAsync(this Animation anim)
public static Task Delay(TimeSpan delay)
Task使ったメッセンジャー パターンで解決
Rx使えば、
button.Tap.FirstAsync().ToTask()
イベントを1つ待つ
Taskを使ったメッセンジャー
• Channelクラス
Channel _channel;
public async Task RunAsync()
{
// 開始処理
var selected = await _channel.Send<Command[], Command>(candidates);
// 選ばれたコマンドを実行
await _channel.Send<CommandResult>(commandResult);
// ...
}
CommandSelectingメッセージと
SelectCommandメソッドをペアに
CommandExecutedメッセージと
EndCommandメソッドをペアに
ビューの処理を
非同期にawait
※ IteratrTasks版だと、awaitのところがyield return
Channelの追加の役割
Channelビュー ロジック
コマンド選択して
コマンドAが選ばれた
選ばれた
結果の記録
Channel ロジック
コマンド選択して
記録した
結果の再現
Channel ロジック
コマンド選択して
サーバーと
通信
記録 再現 記録・再現ができることで
• アプリ再起動時に、続きから再開
• サーバー上でのチート検証
• 対戦履歴の再生
• オンライン対戦・協力プレイ
同じ乱数シードと、
同じユーザー入力を与えれば
実行結果は一緒
反省
• 他のフレームワークとのつなぎこみをフレームワーク化したい
• つなぎ先
• ビュー(データ バインディング)とのやり取り
• サーバーとの通信
• 今は、結構手作業
• Channelにメッセージ ハンドラーを登録して、ビューを表示して、ユーザーの選択を入れ
て返して…
• サーバーAPIたたいて、タイムアウト管理して、通信エラー時の復帰処理して…
• アプリのサスペンド時にChannelの途中記録を読みだして、ストレージに保存して、再起
動時に復元して…
ここでいったんデモ
Task, TaskInteractionの利用例
デモ内容
• ゲームのログイン時の流れ
ゲーム
ロジック
ゲーム
ロジック
ビュー
• 確認ダイアログ表示
• ユーザー名入力
• 登録状況確認
• 新規登録
• ユーザー データ取得
デモ内容
ゲーム開始
登録状況確認
サーバーと通信
登録済み
利用規約表示 同意します
いいえ
名前入力
ビュー表示、ユーザー応答待ち
登録状況確認 有効な名前
NG
はい
データ取得
まだ
済み
プレイ開始
OK
デモ
ページ遷移
TaskNavigation
ページ遷移をステート マシンとして管理
遷移トリガーをTaskで表現
• 例: 装備画面
ページ遷移
ユニット
装備
装備一覧
(空欄)
装備詳細
(装備中)
装備一覧
(変更)
装備詳細
(空欄)
比較
(変更)
装備一覧
(装備中)
比較
(装備中)
空欄選択
詳細
変更
戻る
戻る
戻る
選択
変更
選択
戻る
戻る
戻る
装備
選択
戻る
装備
装備
ユニット
グループ
装備
グループ
装備強化
グループ
ステート マシンとTask
• ページ遷移はステート マシン
• ステート
• どのページにいる
• トリガー
• どのボタンをタップした
• リストのどの要素をタップした
• タイムアウトした
ステート
A
ステート
B
トリガー1
トリガー2
Rx使えば、
button.Tap.FirstAsync().ToTask()
Rx使えば、
list.Items.FirstAsync().ToTask()
いずれにしろTaskが使える
これら複数のうちの最初の1つを待つ
Task.Any(
button.AwaitTap(),
Task.Delay(timeout));
Task.Delay(timeout)
Taskナビゲーションをフレームワーク化
• ステート マシンの設定例
AddState(S.EquipmentInventory,
new Transition
{
T.Item(ct => Cancel.AwaitTap, () => {}, TransitionKey.PageBack),
T.Item(ct => Detail.AwaitTap(ct), x => SelectedItem = x, S.EquipmentDetail),
});
AddState(S.EquipmentDetail,
…
どのステートのときに
(一覧画面にいる)
どういうトリガーで
(戻るボタンを押した)
どう遷移する
(戻る)
(詳細ボタンを押した) (詳細画面に遷移)
遷移前の処理
(選択したアイテムを記憶)
CancellationTokenを受け取って
Taskを返すメソッド
(1つ終わったら残りはキャンセルする)
※ こいつも、WPFとUnityの両方で稼働
フレームワーク化したことで
• 「戻る」(AndroidのBackボタン)対応
• ビュー内のデータ(ViewModel※をスタックで保存、pop)
• グループ
• グループ内遷移: 1つのグループViewModelを共有
• グループ間遷移: 一気に数ページ戻れる
• ページのビューはページ内のことに専念
• トリガーを起こすところまでがページの債務
• ページ遷移やViewModelの記録はナビゲーターの債務
※ ビュー内でだけ必要なデータを記録しておくモデル
独自のUnityシーン管理
• UnityのApplication.LoadLevel使ってない
• LoadLevelの問題
• 全オブジェクトの一斉破棄かけてるみたいでとにかく重たい
• リソース リーク防止の一番手っ取り早い方法ではあるけど、いくらなんでも遅い
• Application.LoadLevelAdditiveAsyncで読み込んで、自前でシーン管理
• 前のシーンを自前でDestroy
• 読み込んだシーンをルート要素につなぎなおし
というような処理を、ページ遷移管理のついでにフレームワーク化
反省: まだ結構定型コードが多い
• ステート マシンの設定コードが結構煩雑
• コード生成で対応(Unityエディター拡張)
• 結構、黒魔術的
グループ単位で設定
グループ内のページ一覧
反省: テキストで書くものじゃない
• ステート マシン設定なんて、テキスト ベースのプログラミング言語で
書くものじゃない
• ↓こういう絵で描けるVisualなDSL (と、編集用エディター拡張)が必要
• 実装も大変だし、カスタマイズ性と両立難しそう
• (Visualなエディター拡張ありのナビゲーション フレームワーク自体はUnity用のものもあ
るにはある)
装備一覧
(空欄)
装備詳細
(空欄)戻る
選択
戻る
装備
反省: ダイアログ
• 今の実装はページのみ
• ダイアログは別系統フレームワーク
• 実際の要件的には…
• UIデザイナーから上がってくるページ遷移フローはページとダイアログが同
列・混在
• ダイアログの遷移も同じナビゲーション フレームワークで動かしたいことが
多々ある
通信コード生成
TypeGen
API定義・型定義をC#で(C#→C#コード生成)
オンライン ゲーム
• サーバーとの通信は定型文が多い
• 手書きすると大量に似たようなコードを書く必要がある
• シリアライズ、デシリアライズ
• HTTP通信、エラー処理
• 多くの通信フレームワークはリフレクションで実現していて…
• iOSで死ぬ
• 性能的に、携帯端末であまり動的な処理をしたくない
コード生成
C# → C# コード生成
• 型定義、メソッド定義はstrongly-typedな言語使うのが楽
• (初代)XML、(2代目)RubyでDSL、(3代目)JSONとかで書いてた
• だんだんやりたいことが複雑に
• 配列に対応、nullableに対応、ジェネリック、型の派生に対応…
• 要するに、型に厳しい言語で書けることと要件変わらなくなった
• なら、最初からC#で書けばいい
型定義例
[Comment("装備品")]
class Equipment
{
[Comment("アイテムID")]
int Id;
[MasterForeignKey(typeof(EquipmentMaster))]
[Comment("アイテムマスターID")]
int MasterId;
[InventoryForeignKey("Enhancers")]
[Comment("装備強化アイテムのID")]
int?[] EnhancerIds;
[Required(false, true)]
[Comment("インスタンスごとの追加能力")]
AbilityIndexedValue[] InstanceAbilities;
}
[Comment("装備する")]
void AddEquipment(
[Comment("誰の(ユニットのID)")]
int unitId
,
[Comment("何番目の装備スロットに")]
int slot
,
[Comment("何を(装備品のID)")]
int equipmentId
,
[Required]
[Comment("変更結果")]
out SyncDifference<Unit>[] Units
);
型定義(C#でクラスを書く) API定義(インターフェイスのメソッドを書く)
プレーンなクラス、フィールドを書く
いくつか、属性を付けて生成結果を制御
定義C#の読み込み
• ビルドしたDLLからリフレクションで読み込み
• 普通に System.Type を読んでる
• 他の選択肢(作り始めた当時はなかったもの)
• System.Reflection.Metadata
• 依存先の解決できなくてもDLL単体で読める
• Roslyn C# Scripting API (Microsoft.CodeAnalysis.Scripting.CSharp)
• 今まだ簡単に使える段階にない
• ほんとはこれでやりたかったけども、Roslynのリリース自体が思った以上に遅く
生成物: 基本
• 型に厳しい言語で面倒なのは、シリアライズとUIバインディング
• この辺りを生成
• JSONシリアライズ/デシリアライズ
• データバインディング用(INotifyPropertyChanged)実装
• 通信処理
• メソッドと対応するURL作って
• 送りたいデータをJSON化してPOST
• 返ってきたデータをJSONデシリアライズ
生成物: 普通のクラス
public partial class Equipment
{
/// <Summary>
/// アイテムID
/// </Summary>
public int Id { get; set; }
…
public Equipment(int id, …)
{
…
Id = id;
…
}
public Equipment(Equipment x) { … }
public static Equipment Clone(Equipment x) { … }
プロパティ
コンストラクター引数
コピー コンストラクター
ディープ クローン
生成物: JSON化・JSON parse
partial class Serializer
{
private string Key(int index, Equipment _)
{
switch (index)
{
case 0: { return "id"; }
…
default: return null;
}
}
private void Serialize(int index, Equipment x)
{
switch (index)
{
case 0: { Serialize(x.Id); break; }
…
}
}
…
partial class Deserializer
{
private Equipment Deserialize(string key, Equipment x)
{
x = x ?? new Equipment();
switch (key)
{
case "id": { x.Id = Deserialize(default(int)); break; }
…
}
return x;
}
…
コード生成で静的に(ビルド時に)作ってしまえば
リフレクション要らない
生成物: データ バインディング用クラス
[Serializable]
[DataContract]
[FileExtensionsAttribute("Equipment")]
[Description("装備品")]
public partial class Equipment : BindableBase, IIdentifiable, IChild, IValidatable
{
/// <Summary>
/// アイテムID
/// </Summary>
[DataMember]
[JsonProperty(PropertyName = "id")]
public int Id { get { return _id; } set { SetProperty(ref _id, value); } }
private int _id;
…
主に編集ツール(Windowsデスクトップ、WPF)用
INotifyPropertyChanged実装
生成物: 通信コード
namespace DataModels
{
public partial class Api : IUnitApi
{
public Task<AddEquipmentResponse> AddEquipmentAsync(AddEquipmentRequest arg, …)
{
OnRequest(arg);
var t = _client.Post("AddEquipment", "/Hero/addEquipment", arg, …
t.ContinueWith(_ => OnResponse(_.Result));
return t;
}
…
HTTP Post
JSON Serialize/Deserialize 呼び出し
全API共通のイベント発火
引数・戻り値をそれぞれ1つのクラスにラップ
(モック作成でその方が都合がよかった※)
※ JSONでAPIの応答モック データを作れる
引数の追加・削除後のモック コード修正が楽だった
生成物: その他
• 型定義JSONも出力
• C#で型定義しだす前の旧型式
• (内部的には「contract JSON」と呼んでる)
• サーバー側は外注、かつ、PHP
• サーバー側のコード生成は発注先に任せてたので、C#を前提にできなかった
• プロジェクトの途中でC#定義に切り替えた
• 急に形式を変えるわけにもいかなかった
• インベントリ/マスター リポジトリ
• (次節で説明)
補足: サーバー側C#
• 複雑なロジックだけサーバーもC#
• 理由
• 2重開発がさすがに無理
• C#で書く方が楽
• 動かし方
• MonoでPHPと同一サーバー内稼働
• 合成・レベルアップ
• ダンジョン、対人バトルのチート検証
• 一部(性能を求める)機能だけWindowsサーバー/IIS
• リアルタイム バトル
反省: .NETの型システム引きずりすぎた
• 非null参照型
• void
null非許容 null許容
値型 int int?
参照型 string ない※
こいつがつらい
• nullを認めたくない場合、[Requred]属性を付けてる
• コード生成の分岐が増えて大変
• .NET経験のない人への説明が大変
※ .NET最大の後悔(million dollar mistake って言われてる)
後からの修正でフレームワークに組み込むのはものすごく大変
Task A()
Task B(T arg)
Task<U> C()
Task<U> D(T arg)
Task<void> A(void arg)
Task<void> B(T arg)
Task<U> C(void arg)
Task<U> D(T arg)
引数・戻り値の有無で4パターンの分岐
こう書けると楽だった
† どちらも今、C#チームが新機能として検討中だけど、入るとしてC# 7.0(2年くらい先?)
反省: 高機能化しすぎた
• 黒魔術度合いが半端ない
• コード生成で、ジェネリックや派生クラスに対応するの結構大変
• リポジトリ(次節で説明)対応がやりすぎ感ある
• 結構ぎりぎりのバランスで成り立ってて
• 修正入れるのそこそこ大変に
• ドキュメント整備できてないので公開してもきっと他人に使えない
反省: コード増えすぎる
• JSON化、すべて静的コード生成
• ソースコード量のうちの結構な割合がJSONがらみ
• アプリのバイナリ サイズ肥大
• 一方、利点もあって
• ソースコードが目に見えるんで、問題を見つけやすい
• JSON読み書きに問題あった時にブレイク ポイント仕掛けられる
リポジトリ
Inventories/MasterRepository
サーバーとのデータ同期、差分更新
ローカル ストレージにデータをキャッシュ
データは全部サーバー上にある
• 必要な分だけ通信でもらってる
• クライアント上でも正規化した状態で管理
• 差分更新
Unit
Id: 1
MasterId: 1
EquipmentId: 120
Equipment
Id: 120
MasterId: 39
EnhancerIds: [ 11, 15, 21 ]
Enhancer
Id: 11
MasterId: 93
Grade: 4
{
{ "action": "update", "item": { "id": 1, "master_id": 1, "equipment_id": 82 } },
{ "action": "remove", "id": 2 }
}
変化したところだけもらう
問題: インスタンスが変わる
• サーバーとの同期でインスタンスが変わる
• 漏れなく追従するの、手動では無理
UI インベントリ
Unit
Id: 1
MasterId: 1
EquipmentId: 120
参照
同期前
UI インベントリ
Unit
Id: 1
MasterId: 1
EquipmentId: 120
参照
同期後
Unit
Id: 1
MasterId: 1
EquipmentId: 82
差分更新の粒度的に
プロパティ1つだけの更新でも
インスタンス丸ごと新しくなる
古い方参照しっぱなし
UI側が更新されない
...
インベントリ内でも同様
参照先が変わる
装備
変更
2系統のデータ
• マスター
• ユニットや装備の名前、パラメーターなど、ユーザーによらないデータ
• ほとんど更新されない
• かなりデータ量が多い
• インベントリ
• ユーザーの手持ちの品
• ことあるごとに更新がかかる
デバイスのローカル ストレージに
キャッシュを保存しておきたい
マスター リポジトリ
• ライブラリを整備
• バージョンとデータをローカルに保存
• バージョンが一致していたらローカルから読む
• 不一致ならサーバーから取り直す
• ID をキーにした Dictionary 化
• コード生成を整備
• [Master]属性がついている型を束ねて MasterRepository 型を生成
• LoadAsyncメソッドで、上記ライブラリを呼ぶ
インベントリ リポジトリ
• ライブラリを整備
• Inventoriesライブラリ
• 現在のインスタンスをID検索できる
• インスタンスの更新イベントを公開
• コード生成を整備
• 通信APIをフックして、リポジトリを自動更新
• 他のインベントリ、マスターが必要なクラスに
それぞれのリポジトリを渡す
• ユニット→装備 とかのID検索プロパティを生成
インベントリ リポジトリ
• ライブラリを整備
• Inventoriesライブラリ
• 現在のインスタンスをID検索できる
• インスタンスの更新イベントを公開
• コード生成を整備
• 通信APIをフックして、リポジトリを自動更新
• 他のインベントリ、マスターが必要なクラスに
それぞれのリポジトリを渡す
• ユニット→装備 とかのID検索プロパティを生成
class DictionaryInventory<T>
{
IEnumerable<T> Items { get; }
IEvent<ChangedArg<T>> Changed { get; }
}
• IEventはIObservableと似たような機能
• つまり、IEnumerableかつIObservableな型
• 現在の値を取る → IEnumerable
• 値の変化をもらう → IObservable
• LINQ+Rx で、Where とか Select を定義可能
インベントリ リポジトリ
• ライブラリを整備
• Inventoriesライブラリ
• 現在のインスタンスをID検索できる
• インスタンスの更新イベントを公開
• コード生成を整備
• 通信APIをフックして、リポジトリを自動更新
• 他のインベントリ、マスターが必要なクラスに
それぞれのリポジトリを渡す
• ユニット→装備 とかのID検索プロパティを生成
internal IEnumerable<IDisposable> Change(SyncDifferenceItem diff)
{
switch(diff.PropertyName)
{
case "Unit": return Units.Change(diff.Difference);
case "Equipments": return Equipments.Change(diff.Difference);
case "Enhancers": return Enhancers.Change(diff.Difference);
...
インベントリ リポジトリ
• ライブラリを整備
• Inventoriesライブラリ
• 現在のインスタンスをID検索できる
• インスタンスの更新イベントを公開
• コード生成を整備
• 通信APIをフックして、リポジトリを自動更新
• 他のインベントリ、マスターが必要なクラスに
それぞれのリポジトリを渡す
• ユニット→装備 とかのID検索プロパティを生成
public partial class Equipment : IDependent<MasterRepository>
{
protected MasterRepository _masters;
void SetRepository(MasterRepository repository)
{
_masters = repository;
if (InstanceAbilities != null) InstanceAbilities.SetRepository(reposito
}
public EquipmentMaster EquipmentMaster { get { return _masters.GetEquipment(
}
通信APIをフックして、このインターフェイス
を持ったクラスにリポジトリを渡す
ID検索して所望のインスタンスを得る
反省: IObservable
• IObservableとほぼ同機能な型を作ってしまっている※
• IEvent<T> ≒ IObservable<EventPettern<T>>
• Unityがシングル スレッド動作なので、同時実行制御だけさぼってる
• IObservable<T>との差は:
• senderを取れる
• OnError/OnCompleteがない
• でも結局、senderはほとんど使ってない
• IObservableでよかった
• Rxに移行しようか悩み中
• IEventに対して、Rxと同じような、Subject, Where, Select, Subscribe実装してる
※ 時期の問題もあった。今から作るならUniRx使うと思う
データ バインディング
Binding-CodeGen
ビューには「UI上のどこにどのデータを出したい」だけを記述
データが更新されたらUIを自動更新
UIが多いゲーム
• 作ってるゲームの性質的にはUIフレームワーク中心
• 3Dとか物理エンジンとか要らない
• むしろ、XAML※的機能がほしい
• Data Binding (CommonView, DialogBase)
• ConentControl, ItemsControl
• UI仮想化
• ゲームだからって常にゲーム フレームワークが最適じゃない
• UIが得意なのは一般OS
• 一般OSのUIフレームワークの上にゲーム描写を重ねたい
• 実際、Win8アプリはXAML UIの上にDirect Xサーフェスを
重ねれる
※ WPF(Windowsデスクトップ)、Silverlight(Webプラグイン)、WinRT(Windowsストア アプリ)の系譜
データ バインディング
• データ バインディング
• UI系フレームワークの要件:
• UI上のどこにどのデータを出したい
• データが更新されたらそこだけ更新したい
<StackPanel
<TextBox Text="{Binding X}" />
<TextBox Text="{Binding Y}" />
</StackPanel>
new Point
{
X = 10,
Y = 20,
};
オブザーバー パターンで実現
※ この辺りはこれだけで1時間セッション コースになるので今回は割愛
検索すればWPF/WinRTとか、JavaScript系フレームワークの記事が出てくるはず
データ バインディング コード生成
• 自社フレームワークでは、コード生成で実現
• リフレクションが使えないので
• モデルのプロパティと、ビューのプロパティをつなぐだけの簡易なもの
[DataContextType(typeof(EquipmentContentModel))]
partial class EquipmentContent : MonoBehaviour
{
[BindingProperty("Equipment")]
public Equipment Equipment
{
set
{
SetThumbnail(value);
}
}
ビューのコード
partial class EquipmentContent
{
public EquipmentContentModel ViewModel { get …
void SourcePropertyChanged(object sender, …
{
base.SourcePropertyChanged(sender, e);
var data = DataContext as EquipmentContentModel;
if(data == null) return;
if (e.PropertyName == "Equipment")
Equipment = data.Equipment;
…
コード生成結果
コード生成
(Unityエディター拡張)
型に応じたプレハブの選択
• ContentControl, ItemsControlクラス
• たいていのUIは、
• 「このデータ型に対して、このプレハブを作りたい」みたいな要件ばっかり
• Unityインスペクターでプレハブを刺しとく
• 1要素版がContentControl、リスト版がItemsControl
UI仮想化
• VirtualizingListViewクラス
• 仮想化
• リストのうちの、画面に見えてる範囲だけ、プレハブをInstantiate
• 残りは作らない、隠れたら消す
• これがないと
• 「アイテムは100個までしか持てません」みたいなゲームになる
• 数が多いと一覧画面に入った瞬間に数秒フリーズ
• スクロールもきつい
反省: 同一プロジェクト内コード生成
• Unityエディター拡張は、コンパイル エラーがある状態で動かせない
• コード生成結果でエラーになると、コード生成し直しがままならない
• エラーがなくなるまでコードを元に戻してから生成しなおし
まとめ
まとめ (1/2)
• IteratorTasks
• System.Threading.Tasks.Task もどき
• TaskInteraction
• チャネルを介したゲーム ロジックとビューとの非同期やり取り
• やり取りの記録、再現
• TaskNavigation
• ページ遷移をステート マシンとして管理
• 遷移トリガーをTaskで表現
まとめ (2/2)
• TypeGen
• API定義・型定義をC#で(C#→C#コード生成)
• Inventories/MasterRepository
• サーバーとのデータ同期、差分更新
• ローカル ストレージにデータをキャッシュ
• Binding-CodeGen
• ビューには「UI上のどこにどのデータを出したい」だけを記述
• データが更新されたらUIを自動更新

More Related Content

What's hot

【Unite 2018 Tokyo】そろそろ楽がしたい!新アセットバンドルワークフロー&リソースマネージャー詳細解説
【Unite 2018 Tokyo】そろそろ楽がしたい!新アセットバンドルワークフロー&リソースマネージャー詳細解説【Unite 2018 Tokyo】そろそろ楽がしたい!新アセットバンドルワークフロー&リソースマネージャー詳細解説
【Unite 2018 Tokyo】そろそろ楽がしたい!新アセットバンドルワークフロー&リソースマネージャー詳細解説Unity Technologies Japan K.K.
 
Unityネットワーク通信の基盤である「RPC」について、意外と知られていないボトルネックと、その対策法
Unityネットワーク通信の基盤である「RPC」について、意外と知られていないボトルネックと、その対策法Unityネットワーク通信の基盤である「RPC」について、意外と知られていないボトルネックと、その対策法
Unityネットワーク通信の基盤である「RPC」について、意外と知られていないボトルネックと、その対策法モノビット エンジン
 
【Unite Tokyo 2019】Understanding C# Struct All Things
【Unite Tokyo 2019】Understanding C# Struct All Things【Unite Tokyo 2019】Understanding C# Struct All Things
【Unite Tokyo 2019】Understanding C# Struct All ThingsUnityTechnologiesJapan002
 
Building the Game Server both API and Realtime via c#
Building the Game Server both API and Realtime via c#Building the Game Server both API and Realtime via c#
Building the Game Server both API and Realtime via c#Yoshifumi Kawai
 
History & Practices for UniRx UniRxの歴史、或いは開発(中)タイトルの用例と落とし穴の回避法
History & Practices for UniRx UniRxの歴史、或いは開発(中)タイトルの用例と落とし穴の回避法History & Practices for UniRx UniRxの歴史、或いは開発(中)タイトルの用例と落とし穴の回避法
History & Practices for UniRx UniRxの歴史、或いは開発(中)タイトルの用例と落とし穴の回避法Yoshifumi Kawai
 
【Unity道場スペシャル 2017京都】スマホゲーム開発者なら知っておくべきチートのリスク&対策
【Unity道場スペシャル 2017京都】スマホゲーム開発者なら知っておくべきチートのリスク&対策【Unity道場スペシャル 2017京都】スマホゲーム開発者なら知っておくべきチートのリスク&対策
【Unity道場スペシャル 2017京都】スマホゲーム開発者なら知っておくべきチートのリスク&対策Unity Technologies Japan K.K.
 
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
Observable Everywhere  - Rxの原則とUniRxにみるデータソースの見つけ方Observable Everywhere  - Rxの原則とUniRxにみるデータソースの見つけ方
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方Yoshifumi Kawai
 
それはYAGNIか? それとも思考停止か?
それはYAGNIか? それとも思考停止か?それはYAGNIか? それとも思考停止か?
それはYAGNIか? それとも思考停止か?Yoshitaka Kawashima
 
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践Yoshifumi Kawai
 
C# 8.0 非同期ストリーム
C# 8.0 非同期ストリームC# 8.0 非同期ストリーム
C# 8.0 非同期ストリーム信之 岩永
 
イミュータブルデータモデル(世代編)
イミュータブルデータモデル(世代編)イミュータブルデータモデル(世代編)
イミュータブルデータモデル(世代編)Yoshitaka Kawashima
 
目grep入門 +解説
目grep入門 +解説目grep入門 +解説
目grep入門 +解説murachue
 
マルチコアを用いた画像処理
マルチコアを用いた画像処理マルチコアを用いた画像処理
マルチコアを用いた画像処理Norishige Fukushima
 
テスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるなテスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるなKentaro Matsui
 
すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!Genya Murakami
 
Doozy UI 使おうぜ! #unity_lt
Doozy UI 使おうぜ! #unity_ltDoozy UI 使おうぜ! #unity_lt
Doozy UI 使おうぜ! #unity_lttorisoup
 
徳丸本に載っていないWebアプリケーションセキュリティ
徳丸本に載っていないWebアプリケーションセキュリティ徳丸本に載っていないWebアプリケーションセキュリティ
徳丸本に載っていないWebアプリケーションセキュリティHiroshi Tokumaru
 
MagicOnion入門
MagicOnion入門MagicOnion入門
MagicOnion入門torisoup
 
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するCEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するYoshifumi Kawai
 

What's hot (20)

【Unite 2018 Tokyo】そろそろ楽がしたい!新アセットバンドルワークフロー&リソースマネージャー詳細解説
【Unite 2018 Tokyo】そろそろ楽がしたい!新アセットバンドルワークフロー&リソースマネージャー詳細解説【Unite 2018 Tokyo】そろそろ楽がしたい!新アセットバンドルワークフロー&リソースマネージャー詳細解説
【Unite 2018 Tokyo】そろそろ楽がしたい!新アセットバンドルワークフロー&リソースマネージャー詳細解説
 
Unityネットワーク通信の基盤である「RPC」について、意外と知られていないボトルネックと、その対策法
Unityネットワーク通信の基盤である「RPC」について、意外と知られていないボトルネックと、その対策法Unityネットワーク通信の基盤である「RPC」について、意外と知られていないボトルネックと、その対策法
Unityネットワーク通信の基盤である「RPC」について、意外と知られていないボトルネックと、その対策法
 
【Unite Tokyo 2019】Understanding C# Struct All Things
【Unite Tokyo 2019】Understanding C# Struct All Things【Unite Tokyo 2019】Understanding C# Struct All Things
【Unite Tokyo 2019】Understanding C# Struct All Things
 
Building the Game Server both API and Realtime via c#
Building the Game Server both API and Realtime via c#Building the Game Server both API and Realtime via c#
Building the Game Server both API and Realtime via c#
 
History & Practices for UniRx UniRxの歴史、或いは開発(中)タイトルの用例と落とし穴の回避法
History & Practices for UniRx UniRxの歴史、或いは開発(中)タイトルの用例と落とし穴の回避法History & Practices for UniRx UniRxの歴史、或いは開発(中)タイトルの用例と落とし穴の回避法
History & Practices for UniRx UniRxの歴史、或いは開発(中)タイトルの用例と落とし穴の回避法
 
【Unity道場スペシャル 2017京都】スマホゲーム開発者なら知っておくべきチートのリスク&対策
【Unity道場スペシャル 2017京都】スマホゲーム開発者なら知っておくべきチートのリスク&対策【Unity道場スペシャル 2017京都】スマホゲーム開発者なら知っておくべきチートのリスク&対策
【Unity道場スペシャル 2017京都】スマホゲーム開発者なら知っておくべきチートのリスク&対策
 
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
Observable Everywhere  - Rxの原則とUniRxにみるデータソースの見つけ方Observable Everywhere  - Rxの原則とUniRxにみるデータソースの見つけ方
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
 
UIElements+UI BuilderでEditor拡張を作ろう
UIElements+UI BuilderでEditor拡張を作ろうUIElements+UI BuilderでEditor拡張を作ろう
UIElements+UI BuilderでEditor拡張を作ろう
 
それはYAGNIか? それとも思考停止か?
それはYAGNIか? それとも思考停止か?それはYAGNIか? それとも思考停止か?
それはYAGNIか? それとも思考停止か?
 
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
 
C# 8.0 非同期ストリーム
C# 8.0 非同期ストリームC# 8.0 非同期ストリーム
C# 8.0 非同期ストリーム
 
イミュータブルデータモデル(世代編)
イミュータブルデータモデル(世代編)イミュータブルデータモデル(世代編)
イミュータブルデータモデル(世代編)
 
目grep入門 +解説
目grep入門 +解説目grep入門 +解説
目grep入門 +解説
 
マルチコアを用いた画像処理
マルチコアを用いた画像処理マルチコアを用いた画像処理
マルチコアを用いた画像処理
 
テスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるなテスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるな
 
すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!
 
Doozy UI 使おうぜ! #unity_lt
Doozy UI 使おうぜ! #unity_ltDoozy UI 使おうぜ! #unity_lt
Doozy UI 使おうぜ! #unity_lt
 
徳丸本に載っていないWebアプリケーションセキュリティ
徳丸本に載っていないWebアプリケーションセキュリティ徳丸本に載っていないWebアプリケーションセキュリティ
徳丸本に載っていないWebアプリケーションセキュリティ
 
MagicOnion入門
MagicOnion入門MagicOnion入門
MagicOnion入門
 
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するCEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
 

Similar to Orange Cube 自社フレームワーク 2015/3

iOS の動画アプリ開発に Xamarin を使ってみた @JXUG #2 East
iOS の動画アプリ開発に Xamarin を使ってみた @JXUG #2 EastiOS の動画アプリ開発に Xamarin を使ってみた @JXUG #2 East
iOS の動画アプリ開発に Xamarin を使ってみた @JXUG #2 Eastirgaly
 
Androidプログラミング初心者のためのゲームアプリ開発入門
Androidプログラミング初心者のためのゲームアプリ開発入門Androidプログラミング初心者のためのゲームアプリ開発入門
Androidプログラミング初心者のためのゲームアプリ開発入門Masahiko Mizuta
 
デジタルアートセミナー#2 openFrameworksで学ぶ、 クリエイティブ・コーディング Session 1: openFrameworks入門
デジタルアートセミナー#2 openFrameworksで学ぶ、 クリエイティブ・コーディング Session 1: openFrameworks入門デジタルアートセミナー#2 openFrameworksで学ぶ、 クリエイティブ・コーディング Session 1: openFrameworks入門
デジタルアートセミナー#2 openFrameworksで学ぶ、 クリエイティブ・コーディング Session 1: openFrameworks入門Atsushi Tadokoro
 
C++11とゲーム製作
C++11とゲーム製作C++11とゲーム製作
C++11とゲーム製作uchan_nos
 
“debug.gem”の 利用体験・開発効率の向上
“debug.gem”の 利用体験・開発効率の向上“debug.gem”の 利用体験・開発効率の向上
“debug.gem”の 利用体験・開発効率の向上Naoto Ono
 
“debug.gem”の 利用体験・開発効率の向上.pdf
“debug.gem”の 利用体験・開発効率の向上.pdf“debug.gem”の 利用体験・開発効率の向上.pdf
“debug.gem”の 利用体験・開発効率の向上.pdfNaoto Ono
 
Chrome DevTools.next
Chrome DevTools.nextChrome DevTools.next
Chrome DevTools.nextyoshikawa_t
 
わんくま名古屋#33(20141115) TDD道場#21
わんくま名古屋#33(20141115) TDD道場#21わんくま名古屋#33(20141115) TDD道場#21
わんくま名古屋#33(20141115) TDD道場#21Yasuhiko Yamamoto
 
BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 1
BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 1BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 1
BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 1Atsushi Tadokoro
 
Multipeer connectivityを使った 動画のリアルタイム端末間共有
Multipeer connectivityを使った 動画のリアルタイム端末間共有Multipeer connectivityを使った 動画のリアルタイム端末間共有
Multipeer connectivityを使った 動画のリアルタイム端末間共有Imajin Kawabe
 
メディア・アート II 第1回: ガイダンス openFrameworks入門
メディア・アート II 第1回: ガイダンス openFrameworks入門メディア・アート II 第1回: ガイダンス openFrameworks入門
メディア・アート II 第1回: ガイダンス openFrameworks入門Atsushi Tadokoro
 
Firefoxの開発プロセス
Firefoxの開発プロセスFirefoxの開発プロセス
Firefoxの開発プロセスMakoto Kato
 
Unityで本格戦国シュミレーションRPG 開発
Unityで本格戦国シュミレーションRPG 開発Unityで本格戦国シュミレーションRPG 開発
Unityで本格戦国シュミレーションRPG 開発dena_study
 
【SQiP2014】システム操作インターフェイス最適化によるテスト自動化ROI向上
【SQiP2014】システム操作インターフェイス最適化によるテスト自動化ROI向上【SQiP2014】システム操作インターフェイス最適化によるテスト自動化ROI向上
【SQiP2014】システム操作インターフェイス最適化によるテスト自動化ROI向上Tatsuya Ishikawa
 
.NET Compiler Platform
.NET Compiler Platform.NET Compiler Platform
.NET Compiler Platform信之 岩永
 
Circle ci and docker+serverspec
Circle ci and docker+serverspecCircle ci and docker+serverspec
Circle ci and docker+serverspecTsuyoshi Yamada
 
Fabric + Amazon EC2で快適サポート生活 #PyFes
Fabric + Amazon EC2で快適サポート生活 #PyFesFabric + Amazon EC2で快適サポート生活 #PyFes
Fabric + Amazon EC2で快適サポート生活 #PyFesSho Shimauchi
 

Similar to Orange Cube 自社フレームワーク 2015/3 (20)

Android gameprogramming
Android gameprogrammingAndroid gameprogramming
Android gameprogramming
 
iOS の動画アプリ開発に Xamarin を使ってみた @JXUG #2 East
iOS の動画アプリ開発に Xamarin を使ってみた @JXUG #2 EastiOS の動画アプリ開発に Xamarin を使ってみた @JXUG #2 East
iOS の動画アプリ開発に Xamarin を使ってみた @JXUG #2 East
 
Androidプログラミング初心者のためのゲームアプリ開発入門
Androidプログラミング初心者のためのゲームアプリ開発入門Androidプログラミング初心者のためのゲームアプリ開発入門
Androidプログラミング初心者のためのゲームアプリ開発入門
 
デジタルアートセミナー#2 openFrameworksで学ぶ、 クリエイティブ・コーディング Session 1: openFrameworks入門
デジタルアートセミナー#2 openFrameworksで学ぶ、 クリエイティブ・コーディング Session 1: openFrameworks入門デジタルアートセミナー#2 openFrameworksで学ぶ、 クリエイティブ・コーディング Session 1: openFrameworks入門
デジタルアートセミナー#2 openFrameworksで学ぶ、 クリエイティブ・コーディング Session 1: openFrameworks入門
 
C++11とゲーム製作
C++11とゲーム製作C++11とゲーム製作
C++11とゲーム製作
 
“debug.gem”の 利用体験・開発効率の向上
“debug.gem”の 利用体験・開発効率の向上“debug.gem”の 利用体験・開発効率の向上
“debug.gem”の 利用体験・開発効率の向上
 
“debug.gem”の 利用体験・開発効率の向上.pdf
“debug.gem”の 利用体験・開発効率の向上.pdf“debug.gem”の 利用体験・開発効率の向上.pdf
“debug.gem”の 利用体験・開発効率の向上.pdf
 
Chrome DevTools.next
Chrome DevTools.nextChrome DevTools.next
Chrome DevTools.next
 
わんくま名古屋#33(20141115) TDD道場#21
わんくま名古屋#33(20141115) TDD道場#21わんくま名古屋#33(20141115) TDD道場#21
わんくま名古屋#33(20141115) TDD道場#21
 
つぶLT20121215
つぶLT20121215つぶLT20121215
つぶLT20121215
 
BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 1
BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 1BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 1
BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 1
 
Multipeer connectivityを使った 動画のリアルタイム端末間共有
Multipeer connectivityを使った 動画のリアルタイム端末間共有Multipeer connectivityを使った 動画のリアルタイム端末間共有
Multipeer connectivityを使った 動画のリアルタイム端末間共有
 
メディア・アート II 第1回: ガイダンス openFrameworks入門
メディア・アート II 第1回: ガイダンス openFrameworks入門メディア・アート II 第1回: ガイダンス openFrameworks入門
メディア・アート II 第1回: ガイダンス openFrameworks入門
 
Firefoxの開発プロセス
Firefoxの開発プロセスFirefoxの開発プロセス
Firefoxの開発プロセス
 
Unityで本格戦国シュミレーションRPG 開発
Unityで本格戦国シュミレーションRPG 開発Unityで本格戦国シュミレーションRPG 開発
Unityで本格戦国シュミレーションRPG 開発
 
【SQiP2014】システム操作インターフェイス最適化によるテスト自動化ROI向上
【SQiP2014】システム操作インターフェイス最適化によるテスト自動化ROI向上【SQiP2014】システム操作インターフェイス最適化によるテスト自動化ROI向上
【SQiP2014】システム操作インターフェイス最適化によるテスト自動化ROI向上
 
.NET Compiler Platform
.NET Compiler Platform.NET Compiler Platform
.NET Compiler Platform
 
0621 ndk game
0621 ndk game0621 ndk game
0621 ndk game
 
Circle ci and docker+serverspec
Circle ci and docker+serverspecCircle ci and docker+serverspec
Circle ci and docker+serverspec
 
Fabric + Amazon EC2で快適サポート生活 #PyFes
Fabric + Amazon EC2で快適サポート生活 #PyFesFabric + Amazon EC2で快適サポート生活 #PyFes
Fabric + Amazon EC2で快適サポート生活 #PyFes
 

More from 信之 岩永

YouTube ライブ配信するようになった話
YouTube ライブ配信するようになった話YouTube ライブ配信するようになった話
YouTube ライブ配信するようになった話信之 岩永
 
C# コンパイラーの書き換え作業の話
C# コンパイラーの書き換え作業の話C# コンパイラーの書き換え作業の話
C# コンパイラーの書き換え作業の話信之 岩永
 
Unicode文字列処理
Unicode文字列処理Unicode文字列処理
Unicode文字列処理信之 岩永
 
C# 8.0 null許容参照型
C# 8.0 null許容参照型C# 8.0 null許容参照型
C# 8.0 null許容参照型信之 岩永
 
C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)信之 岩永
 
.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#信之 岩永
 
C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1信之 岩永
 
C#言語機能の作り方
C#言語機能の作り方C#言語機能の作り方
C#言語機能の作り方信之 岩永
 
Unityで使える C# 6.0~と .NET 4.6
Unityで使える C# 6.0~と .NET 4.6Unityで使える C# 6.0~と .NET 4.6
Unityで使える C# 6.0~と .NET 4.6信之 岩永
 
それっぽく、適当に
それっぽく、適当にそれっぽく、適当に
それっぽく、適当に信之 岩永
 
Code Contracts in .NET 4
Code Contracts in .NET 4Code Contracts in .NET 4
Code Contracts in .NET 4信之 岩永
 
今から始める、Windows 10&新.NETへの移行戦略
今から始める、Windows 10&新.NETへの移行戦略今から始める、Windows 10&新.NETへの移行戦略
今から始める、Windows 10&新.NETへの移行戦略信之 岩永
 
今から始める、Windows 10&新.NETへの移行戦略
今から始める、Windows 10&新.NETへの移行戦略今から始める、Windows 10&新.NETへの移行戦略
今から始める、Windows 10&新.NETへの移行戦略信之 岩永
 
C# design note sep 2014
C# design note sep 2014C# design note sep 2014
C# design note sep 2014信之 岩永
 
C#/.NETがやっていること 第二版
C#/.NETがやっていること 第二版C#/.NETがやっていること 第二版
C#/.NETがやっていること 第二版信之 岩永
 

More from 信之 岩永 (20)

YouTube ライブ配信するようになった話
YouTube ライブ配信するようになった話YouTube ライブ配信するようになった話
YouTube ライブ配信するようになった話
 
C# 9.0 / .NET 5.0
C# 9.0 / .NET 5.0C# 9.0 / .NET 5.0
C# 9.0 / .NET 5.0
 
C# コンパイラーの書き換え作業の話
C# コンパイラーの書き換え作業の話C# コンパイラーの書き換え作業の話
C# コンパイラーの書き換え作業の話
 
Unicode文字列処理
Unicode文字列処理Unicode文字列処理
Unicode文字列処理
 
C# 8.0 null許容参照型
C# 8.0 null許容参照型C# 8.0 null許容参照型
C# 8.0 null許容参照型
 
C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)
 
.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#
 
C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1
 
C#言語機能の作り方
C#言語機能の作り方C#言語機能の作り方
C#言語機能の作り方
 
Unityで使える C# 6.0~と .NET 4.6
Unityで使える C# 6.0~と .NET 4.6Unityで使える C# 6.0~と .NET 4.6
Unityで使える C# 6.0~と .NET 4.6
 
それっぽく、適当に
それっぽく、適当にそれっぽく、適当に
それっぽく、適当に
 
Modern .NET
Modern .NETModern .NET
Modern .NET
 
Deep Dive C# 6.0
Deep Dive C# 6.0Deep Dive C# 6.0
Deep Dive C# 6.0
 
Code Contracts in .NET 4
Code Contracts in .NET 4Code Contracts in .NET 4
Code Contracts in .NET 4
 
今から始める、Windows 10&新.NETへの移行戦略
今から始める、Windows 10&新.NETへの移行戦略今から始める、Windows 10&新.NETへの移行戦略
今から始める、Windows 10&新.NETへの移行戦略
 
今から始める、Windows 10&新.NETへの移行戦略
今から始める、Windows 10&新.NETへの移行戦略今から始める、Windows 10&新.NETへの移行戦略
今から始める、Windows 10&新.NETへの移行戦略
 
C# design note sep 2014
C# design note sep 2014C# design note sep 2014
C# design note sep 2014
 
.NET vNext
.NET vNext.NET vNext
.NET vNext
 
C#/.NETがやっていること 第二版
C#/.NETがやっていること 第二版C#/.NETがやっていること 第二版
C#/.NETがやっていること 第二版
 
Coding Interview
Coding InterviewCoding Interview
Coding Interview
 

Recently uploaded

スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムsugiuralab
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略Ryo Sasaki
 
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...Toru Tamaki
 
論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNetToru Tamaki
 
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Yuma Ohgami
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A surveyToru Tamaki
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)Hiroki Ichikura
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdftaisei2219
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものですiPride Co., Ltd.
 

Recently uploaded (9)

スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
 
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
 
論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet
 
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdf
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものです
 

Orange Cube 自社フレームワーク 2015/3

Editor's Notes

  1. 要するに、「データの更新に画面遷移(リロード)が必要とか、画面遷移するたびにロード長いとかそんなクソゲー作るな」という話
  2. MonoBehaviour は1人で債務を持ちすぎ。債務分割まったくできてないど素人設計
  3. ちなみに、C# 5.0のawaitはこれと似たようなコードに展開されてる。要は、C# 5.0と同じことを自前でやってる。
  4. つまり、UnityとっととMonoのバージョン上げろよ
  5. 命名規約的には、いまのところ await + イベント名でメソッド作ってる。いまいちかなぁと思いつつ定着。 FirstAsync 無双。
  6. Begin/End系の非同期処理と同様、行きと帰りが違う口なのが問題。ラウンドトリップをTaskで一本化してしまえば案外楽。 逆に言うと、メッセンジャー/コマンドのペアに分解する補助関数かけば、既存MVVMフレームワークにもつなげる。 この辺りは後でデモでライブコーディングします
  7. ページ遷移をステート マシンで管理しようって言うのは割かしよくある発想。 https://msdn.microsoft.com/ja-jp/magazine/dn818499.aspx
  8. インベントリは紆余曲折あった ・ 昔、要るデータだけ取ってたら更新が保守しきれなくて心折れる ・全同期やり始める ・重たすぎてサーバー側に怒られる ・差分更新をフレームワーク化、コード生成(今ここ)
  9. IteratorTasksでも言った通り、劣化コピーの実装は嫌
  10. つまるところ、「C#でクロスプラットフォーム」ってこと以外にUnity使ってる利点もない。 マップ表示だけかなぁ、ゲーム的な描画最適化頑張らないといけないの
  11. このパターン守れないとだいたいスパゲッティ コード化して大変