0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ApplibotAdvent Calendar 2024

Day 23

マルチプレイ対応の雑記

Last updated at Posted at 2024-12-23

こちらは Applibot Advent Calendar 2024 23日目の記事になります。前回の記事はコチラです。

はじめに

Unityで作られたゲームのマルチプレイ対応をする時に思ったことなどを雑に書きます。
まず、伝えたいのは将来的にマルチプレイすることは絶対にない場合以外はマルチプレイを考慮して仕様と実装した方が良いです。
Netcode Facts & Fiction
オンラインゲームのしくみ

オフラインゲームができれば
後は通信の機能を追加するだけでオンラインゲームにできるだろう。
この一言で通信機能の追加は後回しにされがちです。そして、プロジェクト末期の通信機能を追加する段階で、炎上することがよくあります。この発言は、大きな間違いなのです。

Unreal Engineのドキュメント

早期のマルチプレイヤーの計画
プロジェクトのどこかの時点でマルチプレイヤー機能が必要になる可能性がある場合は、プロジェクトの最初からマルチプレイヤーを念頭に置いてゲームプレイすべてを構築する必要があります。チームがマルチプレイヤーを作成するための追加手順を常に実装していれば、ゲームプレイを構築するプロセスにかかる手間はシングルプレイヤー ゲームとあまり変わりません。長期的に見れば、プロジェクトでチームがデバッグやサービス提供を行うことが全体として簡単になります。そして、Unreal Engine でマルチプレイヤー用にプログラミングされたゲームプレイは、シングルプレイヤーでも動作します。

それに対し、ネットワーキングなしで構築済みのコードベースをリファクタリングするには、プロジェクト全体を綿密にチェックして、ほぼすべてのゲームプレイ関数を再プログラミングする必要があり、チーム メンバーは、その時点までは当たり前だと思い込んでいたプログラミングのベスト プラクティスを学び直す必要があります。また、ネットワークの速度や安定性によって生じる技術的なボトルネックに対応する準備もできていないでしょう。

プロジェクトの終盤でネットワーキングを導入するのは、最初からネットワーキングを計画しておくより大量のリソースを必要とする厄介な作業です。したがって、プロジェクトでマルチプレイヤー機能が必要になることはないと確信している場合以外は、常に マルチプレイヤー用にプログラミングすることを強くお勧めします。

このように先人達が後から追加するのはやめとけと警告しています。
ただ、マルチプレイの実装経験もなく業務で後からマルチプレイ機能を追加することになってから上記の内容を知る人も多いでしょう。

Tips

UnityからPure C#へ

まず、Unityにガチガチに依存したコードをC#サーバーで動かせるようにする場合Pure C#にする必要があります。
最初からロジックがPure C#で分離されている場合は問題ありませんが
何も気にせずUnityでクラス追加すると MonoBehaviour を継承していると思います。
オフラインゲームが既にある程度できていて今から設計を大きく変更ができない場合はpartialを使ってクラス分割してロジックだけのPure C#ファイルにして、そのファイルだけサーバー側プロジェクトに共有してください!

Hoge.cs
public class Hoge : MonoBehaviour
{
    // 演出用のフィールドやメソッド

    // ロジック用のフィールドやメソッド
}

これをこうするだけ、簡単ですね!

Hoge.cs
public partial class Hoge : MonoBehaviour
{
    // 演出用のフィールドやメソッド
}
Hoge.Logic.cs
public partial class Hoge
{
    // ロジック用のフィールドやメソッド
}

基本の対応はこれですが、依存してるクラスなど全部分離する必要があるので最初からロジックはPure C#で書いていた方がいいです。
地道な作業と動くようになるまでが大変なので...

アセットの注意点

AI用のBehavior TreeアセットなどをScriptableObjectで作っている場合、そのままではC#サーバーで使うことができません。
そのためJSONやMessagePackなど他の形式に変換する必要があります。
アセット同士が再起的に参照している場合、Unityでは同じアセットが同じインスタンスになると思います。
しかし他の形式にシリアライズしてC#サーバーでデシリアライズする場合、特に何も気にしないとそれぞれ別のインスタンスになってしまってメモリ的にも影響出てしまいます。また、ロジック以外にフィールドがあるとローカルでは同一インスタンスでサーバー上では別インスタンスになってしまって挙動が変わってしまうので注意してください。

※試してないですが、MemoryPackならそこら辺を気にせずできるかもしれません

シングルトンの注意点

staticを使ってSingletonにしている場合に困ることがあります。
クライアントエンジニアが特に気にせず実装するとユーザーは一人、インゲームは一つしかないと思って実装すると思います。
しかし、サーバー上で複数のユーザー、複数のインゲームを動かす場合にその前提でシングルトンを使っていると終わります。
シングルトンを使わないようにするか、必要な単位でDIするようにしましょう。

おわりに

この記事を読んで、最初からマルチプレイ対応した方が良いと思って貰えたら嬉しいです。

以上、Applibot Advent Calendar 2024 23日目の記事でした。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?