RPC 与服务端游戏逻辑
最后更新:2026 年 7 月 16 日
PlayServ 中的 RPC,是在 game server 上运行游戏逻辑的机制。服务端代码写在客户端代码库里,标记出来供发现,部署时由代码分析器抽取,最后在服务端运行时中执行。
何时使用 RPC
当你需要让 gameplay 逻辑在 game server 上执行,以降低作弊风险、避免把关键逻辑暴露在客户端 build 中时,就使用 RPC。
PlayServ 不依赖在服务端跑一 整套无头引擎运行时 —— 那是某些传统多人架构的做法。PlayServ 的做法是分析游戏代码、找出服务端代码,只把这部分服务端代码部署到服务端运行时。
服务端逻辑写在与客户端 gameplay 代码分开的类中。这让本地执行和调试成为可能,但也要求你在用到服务端代码的地方把它绑定进来。
服务端执行模型
服务端逻辑由客户端开发者在客户端代码库里编写,但必须显式声明出来,代码分析器才能识别到它,并在部署时上传到服务端。
一个最小的服务端类示例:
[Server]
public class Domain
{
// May contain state
bool flag = true;
public void RollDice(int dice)
{
flag = dice % 2 > 0;
var player = PlayServ.GetPlayer("a123");
player.Name = "Vasya";
player.Update();
}
public string DoSomethingCool(int dice)
{
return flag ? "Ice!" : "Nice";
}
}
在客户端代码中调用这段服务端代码:
class CustomBehaviour : NetworkBehaviour
{
// Allows local debugging and remote execution
private Domain _domain = PlayServ.Remote(Domain);
public void Init(Vector3 velocity, PlayerRef owner)
{
_domain.RollDice(1);
_domain.DoSomethingCool(); // "Ice!"
}
}
在服务端代码中调用 SDK
PlayServ 中的服务端代码可以访问 SDK,因此完全能实现一个功能齐备的 game server。
用于编译服务端代码的那份 SDK,包含了 SDK 各服务模块之间交换信号所用的同一套传输协议。这样,服务端代码在调用其他服务端代码或平台模块时,就能以 SDK 客户端的身份行事。
与普通游戏客户端不同,服务端代码不需要连接 Proxy Module。它的信号会直接路由到总线,再投递给最终接收方。
服务端之间的调用与打包
如果一个服务端类调用了另一个服务端类,被调用的那些服务端类有可能不会被收进服务端包(Archive.zip)。
因此,服务端分析器会把这类引用替换成面向 RPC 的桩,并生成一个带方法桩的 proxy 类,由它去发起 RPC 调用。
// Instead of:
private RPC_Domain _domain = PlayServ.Remote(RPC_Domain);
// Use:
PlayServ.Remote("Domain").Invoke("DoSomethingCool", params);
静态服务端类
另一种做法是使用 static 服务端类。这样就不必初始化服务端 domain,也让分析器能更可靠地识别出对 [Server] 方法的调用 ,并把它们替换成 RPC 调用。
下一步
- Extending SDK Components —— 用 Handler 和中间件风格的 Pipeline 扩展 SDK 的行为
- Events system —— Event 契约,以及用于客户端与服务端通信的
Wait/Stop订阅 - Data Mutation & Model Extending —— 持久化数据改动,以及把 Entity 行为写成方法