1

それはおそらく初心者の質問ですが、私にとって重要です。また、興味深いトピックだと思います。

新しい Unity Multiplayer で C# を使用しています。ここでチュートリアルを見つけることができます: https://unity3d.com/learn/tutorials/topics/multiplayer-networking - 私はまさにそのベースに取り組んでいます。プレイヤーが参加またはホストするときに、「プレイヤーの統計」を「PlayerStats」クラスのインスタンスとして静的リストに追加するようにコードを作成しました。すべてのプレイヤーに対してこのように動作するはずです - 誰かが参加するたびに、彼の統計のインスタンスがリストに追加されます。

さて、このリストは 1 つのグローバルである必要があるので、サーバーによって同期される必要があると思いました。多分ある種のSyncVar、おそらくある種のSyncList。ここに問題があります。クラス インスタンスのリストを同期する方法はありますか?

Unity のドキュメントを確認しましたが、残念なようです。あるいは、私の理解が間違っているのかもしれません。SyncList は整数などの基本的な型しかないようで、構造体もありますが、サーバー全体の同期のために、プレーヤーの統計を含むクラスを構造体に変換する必要がありますか?

繰り返しますが、達成したいことは、新しく参加するプレーヤーが追加されて識別される、1 つのグローバルなプレーヤーのリストが必要なことです。私はすでに識別を行っています - 新しいインスタンスを追加している間、私はそのプレーヤーにID = PlayerList.Count - 1. ID は静的ですが、ローカルにする必要があります。PlayerList の要素が PlayerStats クラスのインスタンスである場合に最適です。したがって、各プレーヤーは (独自のインデックスで) ディスクからデータを PlayerList のインスタンスにロードします。その方が便利だと思いました(ただし、それ以外の方法はわかりません)。シングル プレイヤー モードでは機能しますが、マルチプレイヤー モードでは適切に設計する方法がわかりません。その静的リストはサーバー全体で、他のプレイヤーを認識している必要があるためです。

また、プロジェクト内のクラスで構成されている機器を同期する必要がある場合はどうでしょうか。

それを設計するのを何とか手伝ってくれませんか?新しい Unity マルチプレイヤー チュートリアルに基づいて、シンプルなマルチプレイヤー RPG を作成しようとしています。ここで、プレーヤーを識別し、そのデータを適切な場所にロードする必要があります。データは、キャラクター ジェネレーターによって既に生成されて保存されており、シングル プレーヤーでは既に適切にロードされています。プレイヤー データにはクラス PlayerStats のローカル シングルトン インスタンスを使用し、それらのインスタンスをサーバー全体のグローバル リストに保持する必要があると考えました。私の PlayerStats は PlayerStatsObject のコンポーネントです (gameobjectを持つ階層では空ですDontDestroyOnLoad)。シングルトン インスタンスに作成された PlayerStats クラスには、生成されたキャラクター全体と、バイタル、クラス、レース、クラスで作成された装備リストなどが含まれます。

したがって、基本的には、すべてのプレイヤーをリストに追加し、独自の PlayerStats を持ち、それらの PlayerStats を他のプレイヤー (および AI の敵/環境) が簡単に操作/変更できるようにする必要がありますが、それは簡単です。シングル プレイヤーです)。Player プレハブのコンポーネントとして PlayerStats を追加することは、私にはやり過ぎのように思えます。だから、それはのトンですGameObject.Find("Player").GetComponent<PlayerStats>();。悲惨なデザインになりそうです。

4

1 に答える 1

4

サーバー上のユーザーのUUIDを生成するのはどうですか。これらは、クライアント間でユーザーに関する情報を交換するための強固な基盤を提供します。

次のステップは、実際のデータ交換です。オブジェクトからデータを推定する方法が必要です。オブジェクトの完全なインスタンスをネットワーク経由で送信すると、かなりの帯域幅が要求され、他のクライアントがクラス自体の構造を知っていることを確認する必要はありません。したがって、必要なのは、マシン A に存在するのとまったく同じオブジェクトをマシン B に構築するための情報だけです。

ToString複雑なデータを文字列に変換するために使用される一種の標準です。そのようなデータを表示または保存するために最もよく使用されます。同期するオブジェクト フィールドを選択して、それらを文字列に結合できます。したがって、クラスにToStringメソッドを追加すると、次のことが可能になります。PlayerStats

  1. PlayerStatsインスタンスをループします(これについては後で詳しく説明します)
  2. それらを文字列に変換します
  3. これらの文字列を区切り文字で区切って 1 つの文字列に連結します (例: ##)
  4. クライアント/サーバーに送信する
  5. クライアントは文字列を分割して複数の文字列に戻すことができます
  6. UUID を照合することで、クライアントは既存のプレーヤーと新しく作成する必要があるプレーヤーを判別できます。

ループについては、Observer Patternを使用することをお勧めします。PlayerStatsつまり、この場合、オブジェクトのタイプごとに 1 つの監視インスタンスが作成されます。のすべてのインスタンスはPlayerStats、インスタンス化時にオブザーバーに登録されます。または、インスタンス化と登録を行うFactoryを作成できます。インスタンスが破棄PlayerStatsされたら、監視インスタンスから再度「サブスクライブ解除」する必要があります (ゴースト参照がアプリ​​ケーションに付きまとうのは望ましくありません)。

as コンポーネントを使用するというあなたの考えPlayerStatsは、それほど奇妙な考えではありません。しかし、コンポーネントを何度も見つけるのはリソースの無駄だというあなたの意見は正しいです。Observer パターンを使用すると、すべてのインスタンスを追跡PlayerStatsし、それらを簡単にループできます。

うまくいけば、これがあなたを正しい方向へと導きます!

于 2016-09-19T19:33:01.703 に答える