在多人游戏中有一个关键字叫做 replication“复制”,
该关键字用来将 服务端变量同步到客户端中。
如果某些变量需要 服务端、客户端 保持同步,就需要在 replication{} 语句块中加入变量名;
以下代码参考自:PlayerReplicationInfo.uc
replication
{
if( Role==ROLE_Authority )
Score;
}
这里同步的是 Score 变量,并且前面有一个条件判断 Role==ROLE_Authority
表示该变量由“服务端”发送,客户端将接收到该变量的远程副本。
同步条件是为了应付各种“特殊情况”指定要同步的变量,虚幻官方文档中会有介绍。
如果要在一个条件下同步多个变量 可用逗号隔开;这些变量应该都是类成员变量。
replication
{
if( Role==ROLE_Authority )
Score, Deaths, bHasFlag;
}
为了更方便的说明多人游戏中的“变量复制”,我们将获得随机的“颜色值”。
前提是将原来的插件代码清理一下,改成如下
var color TrailColor;
function PostBeginPlay()
{
// 设置计时器,每一秒执行一次
SetTimer(1, true);
}
function Timer()
{
local PlayerController PC;
local string color_str;
// 得到“随机颜色值”
TrailColor = class'Canvas'.static.MakeColor(rand(255),rand(255),rand(255),255);
PC = Level.GetLocalPlayerController();
if (PC != none)
{
// 在玩家控制台输出:颜色值
color_str = "TrailColor: " $ string(TrailColor.r) $ ", "
$ string(TrailColor.g) $ ", "
$ string(TrailColor.b);
PC.Player.Console.Message(color_str, 0);
}
}
代码编写流程如下:
-
定义类成员变量 TrailColor 用于存储“颜色值”
-
游戏开始后,设置好“每秒执行一次”的计时器
-
在计时器中获取随机颜色值,并将其格式化输出到“玩家控制台”
在 Canvas 类中正好有一个制作颜色值的静态函数,所以直接拿来用;
访问类的静态函数 这里暂不做解释。
由于颜色值是一个“结构体”有 r、g、b 三个整数成员,
需要使用强制类型转换 string() 才能拼接成字符串输出。
符号 $ 可用来拼接两个字符串。
这里的颜色值是随机产生的,如果只用模拟函数 客户端也产生的随机数,
将产生不同的数字,即 服务器端的颜色 和 客户端的颜色 不可能相同。
为了保持变量值的同步,我们需要“复制声明”和“处理接收”。
这里将需要同步的变量 TrailColor 写入“复制声明”中
replication
{
unreliable if (Role == ROLE_Authority)
TrailColor;
}
条件 if 前面又加了一个关键字 unreliable 表示“不可靠复制”,
所谓不可靠是为了节省宽带,不用检测变量值的完全同步。
默认情况是可靠同步,为了预防掉帧等问题 可靠同步需要多次确定变量值,会占用更多网络资源。
变量值是同步之后 还需要一个函数在接收到同步数据后进行处理,
客户端在接收到同步数据后 会调用函数 PostNetReceive() 进行后续处理
最终我们在接收到变量复制后,将颜色值应用到“路径提示”上
simulated function PostNetReceive()
{
local RedWhisp RW;
// 更改“商店路线”的颜色
foreach DynamicActors(class'KFMod.RedWhisp', RW)
{
RW.mColorRange[0] = TrailColor;
RW.mColorRange[1] = TrailColor;
}
}
该函数不需要接收参数,因为 TrailColor 是类成员变量,可直接在函数中访问;
并且函数前面还有一个 simulated 模拟关键字,用于让客户端模拟执行。
并且还要在“默认属性”中设置 bNetNotify=true 表示允许网络通知
defaultproperties
{
GroupName="KF-ABCMutator"
FriendlyName="ABCMutator"
Description="..."
RemoteRole=ROLE_SimulatedProxy
bAlwaysRelevant=true
bAddToServerPackages=true
bNetNotify=true
}
用 VM 启动游戏进入房间,在商店时间提示路径时 会发现路径颜色发生改变;
服务端 只是负责发送数据 而没有接收数据,所以“服务端”不会执行 PostNetReceive() 函数。
提示:不建议用正版与破解版测试,破解版进不了正版的监听房间。
使用正版用于编译插件,然后扔到破解版上创建房间即可。
如果想让服务器端也执行“路径换颜色”效果,可以单独在 Timer 函数内执行替换颜色。
或将颜色替换 另写成一个函数,可供多处调用(实际上就是让服务端单独执行一次换颜色)。
完整的插件代码:
// 插件类
class ABCMutator extends Mutator;
var color TrailColor;
function PostBeginPlay()
{
// 设置计时器,每一秒执行一次
SetTimer(1, true);
}
function Timer()
{
// 得到“随机颜色值”
TrailColor = class'Canvas'.static.MakeColor(rand(255),rand(255),rand(255),255);
// 服务端单独执行 路径颜色替换
ReplacePathColor();
}
replication
{
unreliable if (Role == ROLE_Authority)
TrailColor;
}
// 路径颜色替换
simulated function ReplacePathColor()
{
local RedWhisp RW;
// 更改“商店路线”的颜色
foreach DynamicActors(class'KFMod.RedWhisp', RW)
{
RW.mColorRange[0] = TrailColor;
RW.mColorRange[1] = TrailColor;
}
}
// 处理数据同步
simulated function PostNetReceive()
{
local PlayerController PC;
local string color_str;
// 访问 路径颜色替换
ReplacePathColor();
PC = Level.GetLocalPlayerController();
if (PC != none)
{
// 在玩家控制台输出:颜色值
color_str = "TrailColor: " $ string(TrailColor.r) $ ", "
$ string(TrailColor.g) $ ", "
$ string(TrailColor.b);
PC.Player.Console.Message(color_str, 0);
}
}
defaultproperties
{
GroupName="KF-ABCMutator"
FriendlyName="ABCMutator"
Description="..."
RemoteRole=ROLE_SimulatedProxy
bAlwaysRelevant=true
bAddToServerPackages=true
bNetNotify=true
}
更多关于网络复制的参考资料,请查看虚幻官方文档: