Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

河合 宜文 / Kawai Yoshifumi / @neuecc Cysharp, Inc. Cygames C#大統一理論 C#

Slide 3

Slide 3 text

MagicOnion MasterMemory UniTask https://github.com/Cysharp SlnMerge RuntimeUnitTestToolkit RandomFixtureKit

Slide 4

Slide 4 text

ConsoleAppFramework ValueTaskSupplement https://github.com/Cysharp LitJWT Ulid Difference

Slide 5

Slide 5 text

UniRx MessagePack-CSharp ZeroFormatter Utf8Json https://github.com/neuecc LINQ to GameObject SerializableDictionary CloudStructures Open on GitHub

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

Unified Realtime/API Engine https://github.com/Cysharp/MagicOnion 特徴

Slide 8

Slide 8 text

全てのロジックをC#サーバー上で実行 AI・演算・結果処理など全てサーバー側で処理

Slide 9

Slide 9 text

Realtime Network

Slide 10

Slide 10 text

Microser vices Realtime Server Unity Native App Browser API Server P2P

Slide 11

Slide 11 text

Microser vices Realtime Server Unity Native App Browser API Server P2P

Slide 12

Slide 12 text

P2P Dedicated Server

Slide 13

Slide 13 text

P2P Dedicated Server

Slide 14

Slide 14 text

Microser vices Realtime Server Unity Native App Browser API Server

Slide 15

Slide 15 text

⚫ Unity Connected Games ⚫ Photon Engine ⚫ Monobit Engine ⚫ DIY - WebSocket + Server App ⚫ DIY - WebSocket + mBaaS ⚫ DIY - TCP(UDP) + Server App ⚫ DIY - TCP(UDP) + Unity Headless

Slide 16

Slide 16 text

Unity Connected Games

Slide 17

Slide 17 text

Photon Engine Monobit Engine

Slide 18

Slide 18 text

WebSocket + ServerApp WebSocket(TCP/UDP) + mBaaS(mobile backend as a Service)

Slide 19

Slide 19 text

TCP(UDP) + ServerApp TCP(UDP) + Unity HeadlessApp

Slide 20

Slide 20 text

TCP(UDP) + ServerApp TCP(UDP) + Unity HeadlessApp

Slide 21

Slide 21 text

About MagicOnion

Slide 22

Slide 22 text

C#の型が通信定義となる単方向/双方向RPC // 自然な書き味で、タイプセーフにRPC(Remote Procedure Call)を実現 // C#のasync/await構文により、非同期通信も自然に見える var client = MagicOnionClient.Create(channel); var result = await client.Sum(100, 200); public class TestService : ITestService { public async UnaryResult Sum(int x, int y) { return x + y; } }

Slide 23

Slide 23 text

C#の型が通信定義となる単方向/双方向RPC // 自然な書き味で、タイプセーフにRPC(Remote Procedure Call)を実現 // C#のasync/await構文により、非同期通信も自然に見える var client = MagicOnionClient.Create(channel); var result = await client.Sum(100, 200); public class TestService : ITestService { public async UnaryResult Sum(int x, int y) { return x + y; } } クライアントもサーバーも自 然に繋がっているように見え る(デバッガもサーバー/クラ イアント共有でステップ実行 で繋がって動いていく)

Slide 24

Slide 24 text

リアルタイム通信のための双方向の型付きRPC public interface IGamingHub : IStreamingHub JoinAsync(string roomName, string userName, Vec Task LeaveAsync(); Task MoveAsync(Vector3 position, Quaternion rotation); } public interface IGamingHubReceiver { void OnJoin(Player player); void OnLeave(Player player); void OnMove(Player player); }

Slide 25

Slide 25 text

No content

Slide 26

Slide 26 text

il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Call, typeof(AsyncDuplexStreamingCall).GetProperty("RequestStream").GetMethod); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, serializerOptionsField); il.Emit(OpCodes.Newobj, (typeof(MarshallingClientStreamWriter<>).MakeGenericType(def.RequestType).GetConstructors().Singl il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Call, typeof(AsyncDuplexStreamingCall).GetProperty("ResponseStream").GetMethod); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, serializerOptionsField); il.Emit(OpCodes.Newobj, (typeof(MarshallingAsyncStreamReader<>).MakeGenericType(def.ResponseType).GetConstructors().Singl il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, serializerOptionsField); resultType2 = typeof(DuplexStreamingResult<,>).MakeGenericType(def.RequestType, def.ResponseType); il.Emit(OpCodes.Newobj, resultType2.GetConstructors()[0]); MethodType t; string requestType; string responseType; ITypeSymbol unwrappedOriginalResponseType; ExtractRequestResponseType(y, out t, out requestType, ou var id = FNV1A32.GetHashCode(y.Name); return new MethodDefinition { Name = y.Name, MethodType = t, RequestType = requestType, ResponseType = responseType, UnwrappedOriginalResposneTypeSymbol = unwrappedOrigi OriginalResponseTypeSymbol = y.ReturnType, IsIfDebug = y.GetAttributes().FindAttributeShortName HubId = id, Parameters = y.Parameters.Select(p => {

Slide 27

Slide 27 text

C#で自然にサーバーとクライアントを繋げる 機能として提供するものはシンプルなRPCのみ あとはアプリケーションの作り込みで何でも作れる Unityにも依存しないことであらゆる使い方ができる(サーバーtoサーバーなど) 一つのシンプルなやり方で応用が効く(土管にもなるし土管以外もOK) サーバープログラムを透明にしない どちらにも平等に配置できることを意識したフレームワーク サーバーもクライアントもどちらも大事 適切な場所に適切なコードを書くことで、サーバー/クライアント全体を通し たアーキテクチャの最適化を支援する

Slide 28

Slide 28 text

エコシステムには全部乗る 未来で償却する

Slide 29

Slide 29 text

エコシステムには全部乗る 未来で償却する

Slide 30

Slide 30 text

All in Oneではない RPCしかない

Slide 31

Slide 31 text

API Services

Slide 32

Slide 32 text

Microser vices Realtime Server Unity Native App Browser API Server

Slide 33

Slide 33 text

Microser vices Realtime Server Unity Native App Browser API Server

Slide 34

Slide 34 text

PROS CONS

Slide 35

Slide 35 text

中間言語からコード生成する IDL(JSON/XML/proto/etc...) サーバーコード (PHP/Ruby/Go/C#/etc...) クライアントコード (C#/Swift/JavaScript/etc...)

Slide 36

Slide 36 text

PROS CONS

Slide 37

Slide 37 text

protoはC#/* 任意の言語 */ではない

Slide 38

Slide 38 text

C# as a Schema C#に固定することで 通信定義そのものをC#で表現する

Slide 39

Slide 39 text

言語の違うREST Response型を別々 に書く APIクライアント を手書きする (ザ・マイクロ サービスみたいな 構成) 中間IDLを書く そこからクライア ント・レスポンス 型自動生成 (←を嫌う時によ くある構成、一番 メジャー) サービスを普通に 書く、そこからク ライアントを自動 生成、リクエス ト・レスポンス型 はC#のDLLとして 共有 サービスを普通に 書く、クライアン トはそのプロジェ クト参照から実行 時動的生成

Slide 40

Slide 40 text

認証、課金、クエスト、ミッション、etc...

Slide 41

Slide 41 text

https://logmi.jp/tech/articles/322333

Slide 42

Slide 42 text

適切なコードを適切なところに書く 作り込みを現実のものにする

Slide 43

Slide 43 text

適切なコードを適切なところに書く 作り込みを現実のものにする

Slide 44

Slide 44 text

MagicOnion is Unified Realtime/API Engine

Slide 45

Slide 45 text

Microser vices Realtime Server Unity Native App Browser API Server

Slide 46

Slide 46 text

サーバーとクライアントの距離が限りなく近い

Slide 47

Slide 47 text

ConsoleAppFramework https://github.com/Cysharp/ConsoleAppFramework 引数の自動割当 複数コマンドのルーティング コンフィグ処理 ロギング処理 ライフサイクル管理(Daemon) などCLIの面倒ごとに対応 class Program : ConsoleAppBas { static async Task Main(string[] args) { await Host.CreateDefaultBuilder() .RunConsoleAppFrameworkAsync(args); } public void Run(string name, int repeat = 3) { for (int i = 0; i < repeat; i++) { Console.WriteLine($"Hello from {name}"); } } }

Slide 48

Slide 48 text

Realtime Unity API Service

Slide 49

Slide 49 text

Realtime Unity API Service

Slide 50

Slide 50 text

Conclusion

Slide 51

Slide 51 text

時代の変わり目を超える リアルタイム通信がほぼ必須だったり、5Gが迫っていたり 旧来のフレームワークから変わっていくタイミング 一歩先の理想形へ クライアントとサーバーを、APIとリアルタイムを 全てをC#で統合するという夢想を具現化するのがMagicOnion ただの旧来のXXの置き換えなどではなく、 誰も見たことのない究極的な理想の形に近づけていく 銀の弾丸はないので、相応の困難は発生するかもしれないけれど ぜひ一緒に乗り越えていきましょう! →お、コンタクトフォームが https://cysharp.co.jp/contact/

Slide 52

Slide 52 text

No content