【CEDEC2015】いまどきのゲーム制作環境:エディター群とそのバックエンド、開発スタッフ間のコミュニケーションの具体的な方法解説(前半)

7.3K Views

January 17, 24

スライド概要

CEDEC2015 (Computer Entertainment Developers Conference 2015)で行われた講演、
『いまどきのゲーム制作環境:エディター群とそのバックエンド、開発スタッフ間のコミュニケーションの具体的な方法解説』
で使用されたスライドの前半パートです。
※本スライドには動画が含まれております。pptxファイルをダウンロードすることで動画込みでご覧いただけます

後半パートのスライドはこちらです。
https://www.docswell.com/s/CAPCOM_RandD/K2436G-cedec2015

講演概要は以下のサイトをご覧ください。
https://cedec.cesa.or.jp/2015/session/ENG/3250.html

※CEDECの資料公開サイトCEDiLでも本資料が公開されています。
https://cedil.cesa.or.jp/

profile-image

株式会社カプコンが誇るゲームエンジン「RE ENGINE」を開発している技術研究統括によるカプコン公式アカウントです。 これまでの技術カンファレンスなどで行った講演資料を公開しています。 【CAPCOM オープンカンファレンス プロフェッショナル RE:2023】  https://www.capcom-games.com/coc/2023/ 【CAPCOM オープンカンファレンス RE:2022】  https://www.capcom.co.jp/RE2022/ 【CAPCOM オープンカンファレンス RE:2019】  http://www.capcom.co.jp/RE2019/

シェア

埋め込む »CMSなどでJSが使えない場合

関連スライド

各ページのテキスト
1.

いまどきのゲーム制作環境 エディター群とそのバックエンド、 開発スタッフ間のコミュニケーションの具体的な方法解説 前半パート 株式会社カプコン 技術開発室 市山裕介 株式会社カプコン 技術開発室 是松匡亮

2.

なぜ新しい制作環境なのか? • 開発のさらなる大規模化 – 第8世代への移行 – メモリ、演算リソースも増えた – MT FRAMEWORK の制作環境では効率化にも限界が見 えてきた • 制作環境を大きく見直す必要に迫られた

3.

アジェンダ • エディターの紹介と内部設計 • 共同編集前提のアセット設計 市山 裕介 Yusuke Ichiyama • テレメトリ • 安定した環境の配布 • C#スクリプトとC++リフレクション 是松 匡亮 Masaaki Korematsu

4.

紹介と簡単なデモンストレーション エディターの基本構成

5.

エンジンのエディター群 • Studio – エディター群の総称 • 約40種類のエディターから構成する統合ゲーム開発環境 – 1人では作れない – シンプルなルールとフレームワークが必要 • Runtime – ゲームランタイム • エンジンコードはC++、ゲームコードはC# で記述する

6.

Studio の使用言語と外部ライブラリ • WPF(.NET4.5) + C# – リッチなユーザーインターフェイス – Binding による表示と機能の分離 • Livet – MVVMインフラストラクチャ、更新通知、イベントリスナーの活用 • https://visualstudiogallery.msdn.microsoft.com/ee198b62-fa45-496c-9c1c-e8f63b43f677 • AvalonDock – WPF ドッキングウィンドウライブラリ • https://avalondock.codeplex.com/

7.

シーンエディター(デモ) • 簡単なステージ作成 • プレハブ化 • マルチシーン構造

8.

シーンエディター(デモ) シーンエディターでステージの作成

9.

シーンエディター(デモ) プレハブとマルチシーン

10.

シーンエディター(デモ) コミット履歴と差分の確認

11.

シーンエディター • GameObject と Component で階層構造を作成 • プレハブによるバリエーション – 継承、プレハブ内プレハブの利用 • マルチシーン – 複数のシーンで1つのシーンを構成 – シーン単位でのロード、アンロード

12.

アセットブラウザー • アセット操作のフロントエンド – アセット管理 • ファイルの更新検出(FileSystemWatcherでの監視) – バージョン管理 • 更新、コミット、履歴等 • Perforce機能の利用 – 依存関係の把握 • アセット参照、非参照 – 関係性はメタデータに保存

13.

一蓮托生はまっぴら ゲームランタイムとの関係

14.

Studio と Runtime の関係 • 別プロセスで動作 – Studio は Runtime のクラッシュの影響を受けない – Studio と Runtime は1対1 • ランタイムは複数ビューを作成可能 • リソースの共有が可能 – Studio は Runtime から型情報の提供を受ける Studio TCP/IP Runtime

15.

ランタイム表示をホストする Windowハンドル をホスティング ハメコミ合成 Studio WPFアプリケーション ドッキング枠 Runtime ネイティブアプリ AvalonDockのドッキング枠に別プロセスのプログラムをはめ込む

16.

ランタイム表示をホストする • WindowsFormsHost(HwndHost) を利用 – 親子付け用の WindowHandle作成 • Studio は複数の Runtime 描画結果を扱うことが可能 • クリックイベント等はランタイム側で処理 – TCP/IP経由でエディターにフィードバックする

17.

Studio のエディターが常にマスター • 主従関係を明確に – ランタイムはエディターのスレーブ • 描画結果を表示する存在 – エディターが、全てのデータと編集権を持つ • ランタイム側でデータが決定する構造は作らない

18.

クラッシュリカバリー(デモ) クラッシュリカバリー

19.

クラッシュリカバリー • クラッシュしてもデータは保護される – MT FRAMEWORK では、エディターとデータも 一緒に吹き飛んでいた – ランタイムの別プロセス化 – 全てのデータと編集権をエディターが持つ

20.

アセットを中心にした連携 エディター間の連携

21.

Studio 内でエディターが共存する • 40種類ほど – 統率のとれた作成方針と手段が必要 • 拡張性、保守性に大きく影響する – エディター同士は連携する • 編集対象のみの画面とシーン全体を表示した画面 • ゲーム画面を見ながら

22.

アセットを中心に連携する • エディターはアセットを編集する – アセット変更に連動してエディターの表示が変わる – アセットを中心としたイベントドリブン アセット エディター アセット エディター アセット アセット 1対1 標準的な形 エディター 1対多 複数のアセットを一緒 に扱うエディター エディター 多対1 複数のエディターから アセットを編集する

23.

アセットに要求する機能 ファイルとして • データファイル – JSON, FBX, DDS 等のデータ • メタデータファイル – – – – 依存関係(参照、被参照) 検索用公開情報 データバージョン情報 等の付加情報 • バージョン管理対象 インスタンスとして • データ操作メソッドの公開 • 変更通知の発行 • リファレンスカウント型の Open, Close • ネイティブデータへの変換

24.

エディター連携は2種類 • メモリ上での連携 – アセットの変更が行われたら表示更新 • 通常の編集操作 • ファイルのセーブはまだ行われていない • ファイルを介した連携 – ファイルが上書き保存されたら再読み込み • 外部ツールからのファイル上書き

25.

メモリ上での連携(名前の変更) メモリ上での連携(名前の変更)

26.

メモリ上での連携 • シーンエディター – 名前変更が連動する例 • なんでもない簡単な連携 • Inspector と Hierarchy 表示の連携 – Inspector 上で名前変更 – Hierarchy 上で名前変更。 – Python スクリプトで名前変更 – どの場合もUndoが効く

27.

ファイルを介した連携デモ ファイルを介した連携(テクスチャ変更)

28.

ファイルを介した連携 • シーンとマテリアルエディター – テクスチャ適用が連動する例 – アセットを保存した段階で連携する – シェーダーアセットの更新もファイルで連動する

29.

エディターが表示に責任を持つ • アセットの変更内容はエディターが検出 – 詳細な通知を期待しない エディター よっしゃ、表示更新任せとき アセット 何かが変わったよ

30.

エディターがなんでもやらない • アセットの内部のデータに手を出す エディター GameObjectを追加してやろう アセット 好きに変えて良いよ

31.

アセット内部に干渉しない • エディター – アセットが公開するデータ操作メソッドを使う • アセット – データ操作メソッドを外部に提供する • データ側でのUndoサポート

32.

データ側でのUndo Undoサポート

33.

Undo は必須 • ユーザー視点 – どこにでもあり、当然使える機能のはず • プログラマー視点 – 実装は面倒 – 機能実装を優先したい 実装負荷を下げたい 統一的な実装方法にしたい • スケジュールがそうさせる • でも後からの Undo 実装は作り直しレベル

34.

Undo の基本的な方針 • アセット側で Undo を実装する – データを操作したメソッドと値を記録する • アセットからの変更通知で表示更新する – Undo によって、古い値でデータを変更する • 通常フローと同じイベントドリブン

35.

アセット側でのUndo(基本操作) • 5種類の基本操作をやり直し可能にする • • • アセットがデータの操作メソッドを提供する 基本操作の時点で、順操作と逆操作を確実に実装する 組み合わせて使う 順操作 逆操作 オブジェクトの作成 オブジェクトの削除 オブジェクトの削除 オブジェクトの作成 値の変更 値の変更 コレクションへ要素を追加 コレクションから要素を削除 コレクションから要素の削除 コレクションへ要素を追加

36.

アセット側でのUndo(基本操作) • プログラマー向け表記 順操作 逆操作 CreateObject( #id ) DeleteObject( #id ) DeleteObject( #id ) CreateObject( #id ) SetValue( #obj, newValue ) SetValue(#obj, oldValue ) Add( #collection, item ) or Insert ( index, #collection, item ) Remove( #collection, item ) or RemoveAt( index, #collection ) Remove( #collection, item ) or RemoveAt( index, #collection ) Add( #collection, item ) or Insert ( index, #collection, item )

37.

メソッドを記録する 拡張メソッドを利用している

38.

メソッドを記録する 初回の Do 操作 Undo, Redoに必要なパラメーター はここで全て決まる Redo 操作 Undo 操作 拡張メソッドを利用している

39.

アセット側での Undo (応用操作) • 基本操作のトランザクションを作成 – 連続した基本操作をグループ化して 1回のUndoで戻す – ツリー操作 ドラッグドロップで まとめて移動 • 複数選択して、移動、削除等 – カラーピッカー • 編集開始時の値と終了時の値が必要 – 全部記録して後でシュリンク カラーパレットを なぞって色を選ぶ

40.

アセット側でのUndo(メリット) • Undo 可能なエディターを作りやすい – アセットを操作する層がはっきりとする – エディター毎に Undo 実装が異なる事がない • トランザクションの開始、終了に関しての考慮程度 • Python からの操作が作りやすい – 他の C# のエディターと同じ条件 – 容易にUndo可能に出来る

41.

Undo サポートまとめ • アセット側でサポートする – データを操作するメソッドをUndo可能にする – エディターは、Undo可能メソッドを利用するだけ – データが戻れば表示も戻るように • Undoに必要な情報は初回に全て決まる – Undo 中は、状態を見ることは無い • 相変わらず面倒だが1度実装すれば応用が利く

42.

それぞれの責任範囲 各レイヤーについて整理

43.

各レイヤーの責任範囲 表示情報への 変換に責任 快適操作と 表示に責任 データ操作と更 新通知に責任 入力からデータ 操作に責任 アセットを編集するエディター • • 人間向けの表示 UI との入出力 • • View へのデータ公開 Model へのデータ入力 アセット • • • データと操作 Undo の担保 更新通知の発行

44.

MVVM の形になった View Model ViewModel DataBinding Presentation and Presentation Logic • • 人間向けの表示 UI との入出力 • • View へのデータ公開 Model へのデータ入力 BusinessLogic and Data • • • データと操作 Undo の担保 更新通知の発行

45.

MVVM について • MVVM – Model – View – ViewModel えむ ぶい ぶいえむ – WPF をうまく利用する上で必須の考え方 • https://msdn.microsoft.com/ja-jp/library/windows/apps/JJ883732.aspx • MVVM はうまく適合する – やりたい事と役割毎にレイヤー分けしていく • 強固な Model 機能と ViewModel が責任範囲を守ることが重要 – ViewModel 劇太りに陥りやすい • この観点からのパターンは目新しいものではない – https://ja.wikipedia.org/wiki/データモデル

46.

アプローチ方法を考える 共同作業前提のアセット設計

47.

昨今の開発現場 大規模 • イメージ 中規模 • イメージ – プログラマー 30人~ – アーティスト 70人~ – プログラマー 10人~ – アーティスト 30人~ • +外部協力会社 • +外部協力会社 – プランナー 10人~ – プランナー 5人~ 共同作業、作業分担のインパクトは大きい

48.

シーン編集は共同作業 • 色々な役割の人が、同じシーンを 調整していく共同作業 VFX サウンド ライティング調整 イベント 置き物、壊れ物

49.

シーン編集は共同作業 シーンファイルには みんなの夢がつまっている VFX サウンド ライティング調整 イベント 置き物、壊れ物

50.

シーンの編集でよくある事 ゲームシーンの編集作業

51.

ゲームシーンの編集 • シーンに各担当がデータを追加していく – バージョン管理下 – 複数人が編集する VFX ライティング調整 イベント シーンファイル サウンド 置き物、壊れ物

52.

ファイルをロックしない場合 Aさんは、Bさんのコミットが 理由でコミットできない。 A Aさんも編集開始 rev 001+ rev 001 Bさんが編集開始 rev 002 B rev 003 Bさんがアセットをコミット rev 001+

53.

ファイルをロックしない場合 Aさんは、Bさんのコミットが 理由でコミットできない。 A Aさんも編集開始 rev 001+ rev 001 Bさんが編集開始 rev 002 B rev 003 Bさんがアセットをコミット rev 001+

54.

ファイルをロックする場合 ♪~ A A ロックが取れない ロックを取得 Rev 001 ロックを取得 Rev 002+ Rev 002 B Rev 001+ アセット編集をして rev003としてコミット Rev 003 アセットを編集して rev002をコミット

55.

ファイルをロックする場合 ♪~ A A ロックが取れない ロックを取得 Rev 001 ロックを取得 Rev 002+ Rev 002 B Rev 001+ アセット編集をして rev003としてコミット Rev 003 アセットを編集して rev002をコミット

56.

作業上の問題点 • 待ち時間が無駄 – AさんはBさんを待つ必要がある(直列作業) • Bさんの変更が終わるまで編集出来ない。 • Aさんイライラ • 待ちたくない故に・・・ – ローカルで作業を進めておく(並列作業) • 紙にメモして本番データに反映

57.

ファイルを分割する場合 編集開始 コミット A Rev 001+ B Rev 001+ 編集開始 コミット AさんとBさん は並列作業可能

58.

ファイルを分割する場合 エフェクト 付けたい !? C A CさんがAさんと同じファイルを 編集する必要が出てきたら? Rev 001+ 根本的な問題は 解決していない B Rev 001+

59.

曖昧な基準のファイル分割 • どこまでファイルを分ければ良いか? – 作業者基準はゲームの都合に合わない – ゲームの都合基準は作業者に優しくない – 細切れファイルはデータを複雑にする

60.

共同作業の問題点まとめ • 排他チェックアウトは待ち時間が発生する – 誰かが編集中なら作業出来ない • 本来の用途以外でのファイル分割をしたくない – それは、編集の為?ゲーム実行の為? • どこまで分割すれば良いのか、判断が難しい – 分割の目的があいまいになりがち – ちょうど良い妥協点探しはもう疲れた

61.

解決策を考える • ソースコードのようにマージ前提の運用 に出来ないか? – プログラマーは並列作業前提でしょう? • 特に、ブランチ開発は優秀な自動マージありき アセットもマージ前提で運用可能か?

62.

事実と仮説 • ソフトウェアの並列開発は差分パッチから始ま りブランチの活用が発展に大きな影響を与えた • ブランチ開発を支えているのはマージツールの 存在が大きい • アセットも同じような並列開発が出来ないのは マージツールが無いからである

63.

マージについて考えてみる シーンアセットのマージ

64.

シーンアセットの特性 • JSON,XMLフォーマット • シーンアセット – 記述が構造化されている • 最後の要素はカンマ無し • 閉じタグの表記揺れ

65.

一般的なマージツール • WinMerge,TortoiseMerge 等 テキストのプログラム コード向けに作られた マージツール 1行毎にマージを行う

66.

アセットはマージ出来ない JSON 最後の行にカンマが無い 行単位でマージすると壊れる 可能性がある。 XML 閉じタグの表記揺れ

67.

JSON をマージ出来ない例 base theirs mine TortoiseMergeでマージすると どうなるか?

68.

JSON をマージ出来ない例 行の途中なのに カンマが無い “ImageQuality” : “1” “DistortionType “ : “None” どちらの行を採用しても JSON は壊れる

69.

XMLも似たようなもの 意味は変わらないのに、閉じタグ の変更がコンフリクト原因となる

70.

一般的なマージツールでは駄目 • 1行毎のマージは構造を壊す – 壊れた場合の復旧は困難 • 編集作業のやり直し • プログラマーが呼び出される 構造を理解する 専用マージツールが必要

71.

作る前にアルゴリズムの確認 3Way Merge 利用するマージアルゴリズム

72.

利用するマージアルゴリズム • 3Way Merge – 編集の元になったファイルから、どのような変更操作が行われ たかをAとBのファイルから抽出し、その抽出した2つの変更 操作リスト同士を組み合わせ、改めて編集の元になったファイ ルに変更操作を適用して新しいファイルを作り出す – バージョン管理システムの利用が前提 • 「編集の元」をはっきりさせる必要がある為 – SVN, Git, Perforce 等、多くのソフトウェアで採用されている

73.

3Way Merge 用語 • base – 編集の元になったファイル • theirs – – base より新しいサーバー上にコミットされたファイル base- theirs • base と theirs の変更差分 • mine – 自分のローカルで編集しているファイル – base- mine • base と mine の変更差分 • result – base, theirs, mine のマージ結果 A 自分(mine) B 他の人(theirs)

74.

3Way Merge(概要) 3WayMerge 編集する base 編集開始 A mine mine マージする base (002) base (001) B 編集してコミット theirs 編集開始 theirs マージ結果をコミット result base (003)

75.

3Way Merge(手順の図解) base base からの差分を 「操作」として抽出 「変更操作リスト」 同士をマージ マージした 「変更操作リスト」を base に適用 Add Collider Set Color Red B A theirs mine Add Collider Add Mesh Set Color Red Set Pos (10,0,20) base result result が出来る Add Mesh Set Pos (10,0,20)

76.

3Way Merge(手順の図解) base base からの差分を 「操作」として抽出 「操作リスト」 同士をマージ マージした 「操作リスト」を base に適用 Add Collider Set Color Red theirs mine Add Collider Add Mesh Set Color Red Set Pos (10,0,20) base result Add Mesh Set Pos (10,0,20)

77.

3Way Merge 要点 • 3Way Merge – base - mineの間で発生した操作を抽出する • 操作リストAを作る – base - theirs の間で発生した操作を抽出する • 操作リストB を作る – 操作リストAと操作リストBをマージする – マージしたリストの操作を base に適用する

78.

シーンアセットを 3WayMerge する シーンアセットのマージ

79.

シーンマージ(デモ) シーンマージ

80.

1日100回程度発生 3月28日1900年 3月25日1900年 3月22日1900年 3月19日1900年 3月16日1900年 3月13日1900年 3月10日1900年 3月7日1900年 3月4日1900年 3月1日1900年 2月27日1900年 2月24日1900年 600 2月21日1900年 300 2月18日1900年 400 2月15日1900年 500 2月12日1900年 2月9日1900年 2月6日1900年 2月3日1900年 1月31日1900年 1月28日1900年 1月25日1900年 1月22日1900年 1月19日1900年 1月16日1900年 1月13日1900年 1月10日1900年 1月7日1900年 6731回のマージ 実質50人程度 1月4日1900年 集計期間 4月1日~8月1日ま での4か月間 1月1日1900年 シーンマージ回数集計 シーンのマージ発生回数 700 654回のマージ 大きなROMの アセット締切直前 200 100 0

81.

シーンアセット • シーンアセットの仕様 – プレハブアセットも同じ仕様 – JSON フォーマット – 階層構造 • GameObject, Component と そのプロパティが書き出されている • オブジェクトは移動可能 – シーン独自ルール有り • Id (Guid) でオブジェクトは一意に識別可能 • GameObject 内に同一型の Component は複数存在できない • プロパティの並び順に一部制約あり

82.

正確なマージに必要な条件 • オブジェクトを一意に識別できること – Id をつける(Guid) • GameObject, Component, Object 等保存対象クラス – オブジェクトの移動が正しく検知できる • 「mine で移動+theirs で値変更」への対応 • mine と theirs 両方で移動しても正確に検出可能

83.

クラス構造とデータの例 C# JSON • Id を持つことで、オブジェクトのユニーク性を担保する

84.

構造の分解と再構築 • マージ中、Id をキーにフラットな構造を作る – 親子関係を潰して独立させる • 親からは子の情報を外す • 子は親の情報を保持 – マージ後にシーンを再構築できるように 本来のデータ マージ中の表現 1e4d2908-6ff3-4beb-a23e-d6febe6a036d 0b98b6eb-2f9d-4110-b955-3d1bf39506dc

85.

オブジェクト毎の差分抽出 • Id オブジェクト毎に比較処理 – Id が両方にある場合、 JSON としての比較を行う – Id が片方にしかない場合は追加又は削除 1e4d2908-6ff3-4beb-a23e-d6febe6a036d 0b98b6eb-2f9d-4110-b955-3d1bf39506dc

86.

3WayMerge を行う 1. base – mine の差分をリスト化する – Id フィールドを特別扱いする • base との中に Id が存在するかどうか – 片方にしか無ければ、AddNode, RemoveNode どちらか – Id 付きオブジェクト毎に、行われた変更操作を抽出する • • • • 2. 3. 4. プロパティに差異があれば、AddProperty か RemoveProperty プロパティの値に差異があれば、ChangeValue 配列の要素数変更があれば、AddElement か RemoveElement 配列の要素の値変更があれば、ChangeArrayValue 1の手順を base - theirs に対しても行う base-mine, base-theirs の変更操作リスト同士をマージする マージした変更操作リストを base に適用する

87.

異常系の考慮 コンフリクトの扱い

88.

コンフリクトの扱い(その1) • 操作リストのコンフリクトはどう扱うか? • 例: – theirs でオブジェクト削除 – mine でそのプロパティを編集している • 削除を最高優先度にする – どの場合でも削除は最高優先度 » 操作リストをソートし、削除操作は最後に適用する – ゾンビのように復活するオブジェクトの発生防止

89.

コンフリクトの扱い(その2) • 同じプロパティに違う値書き込み • mine を優先する – ユーザーに選択させる運用は難しい » ルールにしてしまって自動解決の道を – バージョン履歴から「後出し優先」が理解できる » 「自分の編集が反映しない」よりわかりやすい

90.

シーン独自ルールへの対応 • 同一型コンポーネントはゲームオブジェクトに 複数存在できない – mine, theirs 共に同じコンポーネントを追加した場合 – コンフリクトとして検出し、 mine 優先 • それ以前に、運用がおかしいのでチームで話し合うように提案する • プロパティの並びに一部制約あり – JsonWriter 側でソートして対処

91.

運用する • バージョン管理ツールの設定 – シーンアセットにはシーン用のマージツール を使うように設定する • 拡張子ごとに指定可能 (*.scn.json, *.pfb.json) • ソースコードを自動マージする感覚で使う

92.

その他のメリット • 専用 Diff ツールが作れた • コミット前の変更確認の習慣化 • データの不具合を見つけやすい • コミットウィンドウや履歴ウィンドウ からダブルクリックで起動可能

93.

参考情報 開発お役立ち情報

94.

JSON 用マージツール • JsonDiffPatch – http://benjamine.github.io/jsondiffpatch/demo/index.html JSON 同士の比較が出来る 作成中のマージツールの答え 合わせに使った

95.

GDC2013 のセッション • GDCVault – Working Together: Solutions for Collaborative Asset Creation – Niklas Frykholm(Bitsquid AB) – http://www.gdcvault.com/play/1017738/Working-Together-Solutions-for-Collaborative – アイデアはこのセッションから

96.

失敗ノウハウ マージツール運用上の注意

97.

運用上の注意 • データをバグらせると大変なことに! – かなりやばい – 全パターンのユニットテストを作っておく Visual Studio の Professional 以上なら ユニットテスト支援機能が付いています。

98.

運用上の注意 • データがおかしくなった? – ユーザーは真っ先にマージを疑う • 迅速に潔白を証明する • 本当の原因調査に移れるように準備する – マージ発生時、base, theirs, mine ファイルを自動的に サーバーに保存する • 迅速なバグ修正と潔白の証明に役立つ • ログになければマージは発生していない

99.

誤解 • JSON ならマージ対応が可能なんでしょ? – マージ可能なデータフォーマットが大切 • JSON をマージするだけではアセットとしての整合性は取れない • マージに優しいフォーマットを JSON で実現しただけ • とりあえずマージ可能にしておこう – やめておけ – 何かメリットがあるのか? • 1人でしか触らないアートリソース等 • レアなバグが入る隙になる 編集の衝突発生回数

100.

うまく運用する為に • 意識改革 – 自分の編集は他人にも影響を及ぼす • 適度なファイル分割 • ゲームの為の分割を第一に考える • 作業上衝突する部分はマージで吸収する • 全てをマージで解決しようとしない