Я хочу отделить сетевой код от моей игровой логики. Это нужно не только для того, чтобы иметь возможность разделить игровую логику между однопользовательским и многопользовательским режимами игры, я также хочу этого из-за принципа разделения интересов.
Мой текущий подход заключается в создании кода для моих классов, связанных с сетью, таким образом, чтобы существовала онлайн- и офлайн-версия. Я делаю это с помощью шаблонов T4.
В результате классы выглядят следующим образом:
Автономная/одиночная версия:
// T4 GENERATED CODE
// Head (Singleplayer version)
class StandaloneHelloWorld : MonoBehaviour, IHelloWorld
{
private string name;
public void SayHello()
{
SayHelloInternal();
}
// Body
public string Name
{
get { return name; }
set { name = value; }
}
void SayHelloInternal()
{
Debug.Log(Name + ": Hello World");
}
}
Многопользовательская версия:
// T4 GENERATED CODE
// Head (Multiplayer version)
class NetworkedHelloWorld : NetworkBehaviour, IHelloWorld
{
[SyncVar]
private string name;
public void SayHello()
{
CmdSayHello();
}
[Command]
void CmdSayHello()
{
RpcSayHello();
}
[ClientRpc]
void RpcSayHello()
{
SayHelloInternal();
}
// Body
public string Name
{
get { return name; }
set { name = value; }
}
void SayHelloInternal()
{
Debug.Log(Name + ": Hello World");
}
}
Они оба имеют общий интерфейс, чтобы скрыть реализацию от вызывающих:
interface IHelloWorld
{
string Name { get; set; }
void SayHello();
}
Итак, как вы можете видеть, обе реализации используют одно и то же тело, разделяя большую часть кода, а точки входа зависят от того, подключена ли реализация к сети или нет. Также обратите внимание, что две реализации наследуют разные базовые классы.
Преимущества:
- Код одиночной игры не зависит от сетевого кода и наоборот.
- Нет дублирующегося кода (по крайней мере, ни одного, который нужно поддерживать вручную)
Недостатки:
- Поддержка интерфейсов в Unity ограничена. Я бы не смог ссылаться на экземпляры сцены IHelloWorld из редактора.
- Необходимость поддерживать отдельные префабы для режимов одиночной/многопользовательской игры.
- Необходимость вмешиваться в T4/генерацию кода
Знаете ли вы лучшие способы справиться с этим? Как вы решили эту проблему?