断线重连
断线重连
备注:编程元件建立工程后,默认就包含断线重连的功能示例,可以搜索S2C_OnReconnected消息,了解其用法。
下面的例子,会介绍如何从头开始制作断线重连功能。
此外,也可以在资源社区,获取模板《断线重连示例》,体验该功能。
--需要恢复的成员local Reconnect = {    camera_state=nil,    ui_state=nil,    change_number=0}--通过编程元件的自定义属性,获取按钮实例Idlocal elementId = System:GetScriptParentID()local far_camera_button=CustomProperty:GetCustomProperty(elementId,"远景摄像机按钮",CustomProperty.PROPERTY_TYPE.CustomUI) --远景摄像机按钮local near_camera_button=CustomProperty:GetCustomProperty(elementId,"近景摄像机按钮",CustomProperty.PROPERTY_TYPE.CustomUI) --近景角相机按钮local change_number_text=CustomProperty:GetCustomProperty(elementId,"切换次数数字",CustomProperty.PROPERTY_TYPE.CustomUI) --切换次数数字的控件
local playersInfo={}--记录全部玩家的状态信息
--客户端初始化function Reconnect:GameClientInit()    --客户端初始化,注册断线重连消息    System:BindNotify(NetMsg.S2C_OnReconnected, self.S2C_OnReconnected, self)end--服务器初始化function Reconnect:GameServerInit()    --服务器初始化,注册客户端请求记录信息    System:BindNotify(NetMsg.C2S_SaveClientInfo, self.OnSaveClientInfo, self)    -- 注册断线重连事件。断线重连时,同步当前游戏状态给客户端    System:RegisterEvent(Events.ON_PLAYER_RECONNECTED, self.OnServerReconnected, self)
end--客户端开始时function Reconnect:GameClientOnStart()    --举例:点击[远景摄像机按钮]    UI:RegisterPressed(far_camera_button,function ()        --分别设置相机和界面的状态        Reconnect:SetCamera(1)        Reconnect:SetUI(1)        --向服务器发消息,记录相机信息        --注意:因为目前不能直接发送引擎结构体消息(例如Engine.Vector),所以这里发送的是状态信息。        System:SendToServer(NetMsg.C2S_SaveClientInfo,            {                camera_state=1,                ui_state=1,            }        )    end)    --[近景摄像机按钮]注册点击事件,功能类似    UI:RegisterPressed(near_camera_button,function ()        Reconnect:SetCamera(2)        Reconnect:SetUI(2)        System:SendToServer(NetMsg.C2S_SaveClientInfo,            {                camera_state=2,                ui_state=2,            }        )    end)
end--服务器开始时function Reconnect:GameServerOnStart()    --创建一个生物,方便查看效果    Creature:SpawnCreature(1114000000000005,Engine.Vector(0,500,0),Engine.Vector(1,0,0),1)
    -- 获取当前登录服务器的所有玩家ID    local playerIds = Character:GetAllPlayerIds()    --遍历数据    for _, v in ipairs(playerIds) do        local player_info={} --初始化一个表来管理记录的信息        --定义默认值        player_info.camera_state=1        player_info.ui_state=1        player_info.change_number=0        --将玩家ID作为键,玩家信息表作为值,存储到playersInfo中        playersInfo[v]=player_info        System:SendToClient(v, NetMsg.S2C_OnReconnected,playersInfo[v]) --游戏开始,第一次同步初始信息给客户端    end
end
--根据状态,设置控件的显示或隐藏function Reconnect:SetUI(state)    if state==1 then        --远景时,显示近景按钮        UI:SetVisible({far_camera_button},false)        UI:SetVisible({near_camera_button},true)    elseif state==2 then        --近景时,显示远景按钮        UI:SetVisible({far_camera_button},true)        UI:SetVisible({near_camera_button},false)    endend
--根据状态,设置相机位置和角度function Reconnect:SetCamera(state)    if state==1 then        --将相机挂载到目标(远)        local pos=Engine.Vector(1000,500,100)        local rot=Engine.Rotator(0,0,180)        Camera:BindOnWorldPosition(pos,rot,0.1)        print("@@## far camera 1")
    elseif state==2 then        --将相机挂载到目标(近)        local pos=Engine.Vector(250,500,100)        local rot=Engine.Rotator(0,0,180)        Camera:BindOnWorldPosition(pos,rot,0.1)        print("@@## near camera 2")    end
end
--服务器,收到客户端请求,记录信息function Reconnect:OnSaveClientInfo(msgId, msg, playerId)    if msg.camera_state~=nil then        -- 直接更新消息中包含的键        for key, value in pairs(msg) do            playersInfo[playerId][key] = value        end    end    --记录切换次数    playersInfo[playerId].change_number=playersInfo[playerId].change_number+1    --当服务器处理完成,返回给客户端数据    System:SendToClient(playerId, NetMsg.S2C_OnReconnected,playersInfo[playerId])
end
-- 断线重连逻辑,服务器下发需要同步的信息function Reconnect:OnServerReconnected(playerId, levelId)    System:SendToClient(playerId, NetMsg.S2C_OnReconnected, playersInfo[playerId])end
-- 客户端,收到服务器下发的数据function Reconnect:S2C_OnReconnected(msgId, msg)    if msg~=nil then        for key,value in pairs(msg) do            self[key]=value        end        --设置相机        self:SetCamera(self.camera_state)        --设置文本        UI:SetText({change_number_text},tostring(self.change_number))        --设置按钮        self:SetUI(self.ui_state)
    end
end
return Reconnect