客户端-服务器通信写法
客户端-服务器通信写法
注意:在编程元件方案中,(除非另行标明)创作者必须使用客户端-服务器模式来进行通信。
注意:Lua脚本会默认同时在客户端与服务器运行,因此需要自行处理客户端/服务器环境的区分。
--在编程元件的使用过程中,可以使用客户端-服务器模式(C/S模式)方式来进行通信。
--下面是一个例子(也可以在默认的新建工程模版中找到):
--步骤1:首先定义网络协议(消息),例如,在GameEntry中定义NetMsg = { OnSeverLog = 1000, -- 服务端日志打印}
--步骤2:发送消息--这里的例子是,服务器发送消息到全部客户端(SendToAllClients),类似的消息函数还有SendToClient,SendToServer--下面是ServerLog函数的实现local function ServerLog(...) printLog(...) -- 是否将服务端日志发送至客户端 local PrintToClient = true if PrintToClient then System:SendToAllClients( NetMsg.SeverLog, --第一个参数是消息id {...} --第二个参数是消息内容,这里的{...}是可变参数列表 ) endend
--步骤3:接收消息一方,注册网络协议--这里的例子是,在游戏开始时,客户端注册网络协议(一般客户端接受消息,在GameClient:OnStart()中注册;服务器接受消息,在GameServer:OnStart()中注册)function GameClient:OnStart() --System:BindNotify(msgId,callback,ref)第一个参数是消息id,第二个参数是回调函数(这里传入了函数名),第三个参数是回调函数所属的self System:BindNotify(NetMsg.OnSeverLog, self.OnSeverLog, self)end
--步骤4:编辑收到消息后回调函数的逻辑,这里的例子是在客户端收到消息后打印logfunction GameClient:OnSeverLog(msgId, msg)--第一个参数是消息id,第二个参数是消息内容 if msg then printLog("[GameClient:OnSeverLog]", msgId, table.unpack(msg)) endend备注:如果是服务器收到客户端消息,回调函数参数一般写成如下面的例子
function GameServer:OnMsgRequest(msgId, msg, playerId)--第三个参数是发消息的客户端玩家角色id printLog("Client Msg Request",msgId, msg.text, msg.count,playerId)--试着日志打印各项参数end备注:如果不需要使用self(冒号代表函数默认传入了self参数),那么在注册时也可以省略self,例如下文:
System:BindNotify(_CS.NetNotify.OnSeverLog, OnSeverLog)对应的回调函数可以这样写:
local function OnSeverLog(msgId, msg)更多关于冒号参数的使用:
MyClass:FunWithParams(1,2,3,4)--调用函数并传入四个参数,实际传入五个参数为self,1,2,3,4
MyClass.FunWithParams(1,2,3,4)--调用函数并传入四个参数,实际传入四个参数为1,2,3,4
FunWithParams(1,2,3,4)--(本地函数用法)调用函数并传入四个参数,实际传入四个参数为1,2,3,4
--总结:带冒号函数的会有一个隐藏self传出去,下面会有各种函数的写法和调用方法,参数传入按照顺序一一对应
function Myclass:FunWithParams(a,b,c) --实际传参顺序为self,a,b,c,(有个隐藏的self) --在各种情况下实际获取到的参数 --MyClass:FunWithParams(1,2,3,4) self = self a = 1 b = 2 c = 3 用冒号的话会多传一个self进来 --MyClass.FunWithParams(1,2,3,4) self = 1 a = 2 b = 3 c = 4 --FunWithParams(1,2,3,4) self = 1 a = 2 b = 3 c = 4end
local function FunWithParams(a,b,c) --实际传参顺序为a,b,c,(没有self,所以访问self的话是nil,也可以自己在参数那边写个self) --在各种情况下实际获取到的参数 --FunWithParams(1,2,3,4) a = 1 b = 2 c = 3end
function Myclass.FunWithParams(a,b,c) --实际传参顺序为a,b,c,(没有self,所以访问self的话是nil,也可以自己在参数那边写个self) --在各种情况下实际获取到的参数 --MyClass:FunWithParams(1,2,3,4) a = self b = 1 c = 2 用冒号的话会多传一个self进来 --MyClass.FunWithParams(1,2,3,4) a = 1 b = 2 c = 3end
function(a,b,c) --实际传参顺序为a,b,c,(没有self,所以访问self的话是nil,也可以自己在参数那边写个self) --此为匿名函数 --在各种情况下实际获取到的参数 ---------------------------------------------------------------------- System:SendToServer(_CS.NetNotify.OnFunWithParams,1,2,3) System:BindNotify(_CS.NetNotify.OnFunWithParams, function(a,b,c) a = 1,b=2,c=3 end)
System:SendToServer(_CS.NetNotify.OnFunWithParams,1,2,3) System:BindNotify(_CS.NetNotify.OnFunWithParams, function(a,b,c) a = self,b=1,c=2 --因为bind后面加了一个参数self,所以实际传参顺序为self,1,2,3 --这部分不要死记硬背 只是这个api会这样传 --注意看文档给个回调函数的参数数量,只要一一对应就没问题,本质上这个就是没冒号的普通函数 --不过是匿名无法被其他地方使用而已 --建议匿名函数只在回调函数中使用,免得混淆 end,self) ----------------------------------------------------------------------end