Unity结合C++开发服务器实现多人游戏(七)

角色登场,消失及同步化

以下实现客户端登陆后, 构建角色的登场,消失在游戏场景中.
1.    客户端A登陆成功的话,角色的位置发送给服务器”进入游戏”通知.
2.    服务器端接收信息后,发送客户端A已经存在角色信息,并且发送其它客户端新的信息.
3.    客户端接收后添加新角色到游戏场景中.
客户端 "进入游戏!" 的信息在PIDL中定义.
  
global Simple 1000
  
{
  
    JoinGameScene([in] float x, [in] float y,  [in] float z, [in] float angle);
  
    Player_Appear([in] int hostID, [in] std::wstring userID,
  
        [in] float x, [in] float y,  [in] float z,
  
        [in] float vx, [in] float vy,  [in] float vz,
  
        [in] float angle);
  
    Player_Disappear([in] int hostID);
  
...
  
客户端登陆成功的话,通知服务器 "进入游戏!".
  
        m_stub.NotifyLoginSuccess = (HostID  remote, RmiContext rmiContext) =>
  
        {
  
            //  join the world!
  
            m_proxy.JoinGameScene(HostID.HostID_Server,  RmiContext.ReliableSend,
  
                m_localPlayer.transform.position.x,
  
                m_localPlayer.transform.position.y,
  
                m_localPlayer.transform.position.z,
  
                m_localPlayer.GetComponent<PlayControl>().carAngle); //  show 30 ends here
  
...
  
现在,添加服务器处理的代码.
  
class SimpleServer
  
{
  
    DECRMI_Simple_JoinGameScene;
  
...
  
  
  
DEFRMI_Simple_JoinGameScene(SimpleServer)
  
{
  
    // validation  check
  
    auto it =  m_remoteClients.find(remote);
  
    if (it == m_remoteClients.end())
  
    {
  
        return true;
  
    }
  
    auto& rc =  it->second;
  
  
  
    // update player  info
  
    rc->m_x = x;
  
    rc->m_y = y;
  
    rc->m_z = z;
  
    rc->m_angle =  angle;
  
以上代码中JoinGameScene继续添加一下代码.
  
DEFRMI_Simple_JoinGameScene(SimpleServer)
  
{
  
...
  
    assert(it->first  == remote);
  
  
  
    // Let incomer  know others, let others know incomers.
  
    for (auto otherIter : m_remoteClients)
  
    {
  
        if (otherIter.first != it->first)
  
        {
  
            auto&  otherRC = otherIter.second;
  
            m_proxy.Player_Appear((HostID)it->first,  RmiContext::ReliableSend,
  
                (HostID)otherIter.first,
  
                otherRC->m_userID,
  
                otherRC->m_x,  otherRC->m_y, otherRC->m_z,
  
                otherRC->m_vx,  otherRC->m_vy, otherRC->m_vz,
  
                otherRC->m_angle);
  
            m_proxy.Player_Appear((HostID)otherIter.first,  RmiContext::ReliableSend,
  
                (HostID)it->first,
  
                rc->m_userID,
  
                rc->m_x,  rc->m_y, rc->m_z,
  
                rc->m_vx,  rc->m_vy, rc->m_vz,
  
                rc->m_angle);
  
        }
  
    }
  
以上代码解析如下:
1.    接收到的更新游戏角色的信息。
2.    传递之前客户端名单,告知客户端新用户的加入 同样,告知新客户端现有客户端的加入。
客户端离开的情况,进行相反的处理. 离开后,出现"客户端OO消失"的信息.
  
  
  
    m_netServer->OnClientLeave =  [this](CNetClientInfo* info, ErrorInfo*, const ByteArray&)
  
    {
  
        //  let others know the disappear
  
        vector<int>  others;
  
        for (auto otherIter : m_remoteClients)
  
        {
  
            others.push_back(otherIter.first);
  
        }
  
        m_proxy.Player_Disappear((HostID*)others.data(),  others.size(),
  
            RmiContext::ReliableSend,
  
            info->m_HostID);
  
...
  
调用以上远程函数时,变量HostID的数组进入.这样的话,可对多个设备进行信息发送.
添加客户端中调用Player_Appear的处理代码.,在游戏场景中角色登场.
  
public class NetManager : MonoBehaviour
  
{
  
    public GameObject m_remotePlayerPrefab;
  
  
    void Start()
  
    {
  
  
        m_stub.Player_Appear  = (HostID remote, RmiContext rmiContext, int hostID,  System.String userID, float x, float y, float z, float vx, float vy, float vz, float angle) =>
  
        {
  
            if (hostID != (int)m_netClient.GetLocalHostID())
  
            {
  
                var  rot = Quaternion.AngleAxis(angle, new UnityEngine.Vector3(0,  1, 0));
  
  
                var  remotePlayerCharacter =  (GameObject)Instantiate(m_remotePlayerPrefab, new UnityEngine.Vector3(x, y, z), rot);
  
                remotePlayerCharacter.name  = "RemotePlayer/" +  hostID.ToString();
  
            }
  
            return true;
  
        };
  
设置以下条件.
Unity Editor中选择NetManager GameObject后,在 Inspector中 m_remotePlayerPrefab下添加名为RemotePlayer的Prefab.如果没有 RemoteCar Prefab的话,制作场景内LocalPlayer的复制版后,并删除所有的 Script Behavior.
调用Player_Disappear后, 此角色在游戏场景中被删除.
  
m_stub.Player_Disappear =  (Nettention.Proud.HostID remote,
  
    Nettention.Proud.RmiContext  rmiContext, int hostID) =>
  
{
  
    var g =  GameObject.Find("RemotePlayer/" +  hostID.ToString());
  
    if (g != null)
  
    {
  
        Destroy(g);
  
    }
  
    return true;
  
};
  

现在进行测试. 运行两个以上的客户端后,角色登场.
首先会出现角色的位置,但是无法操控,下篇将继续讲述.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值