美文网首页
Unity3D 网络游戏实战(第2版)

Unity3D 网络游戏实战(第2版)

作者: 学识浅薄的胖 | 来源:发表于2021-12-15 16:13 被阅读0次

    书籍作者: 罗培羽 著
    ISBN:9787111612179
    推荐程度: 有编程经验的,强烈推荐

    在学习 Unity 3D 的过程中,从图书馆借来了此书。该书总体由浅入深,步骤清晰,文字简练,在阅读学习过程中,发现存在少许错误,特此记录。

    书中大部分工程使用的 Unity 版本为 2017.3.0f3,本人使用的 Unity 版本为 2019.4.31f1c1 。经过代码实践,书中大部分函数均与 2019 一致,存在不同时,会在本文列出。

    第 1 章 网络游戏的开端:Echo

    • 第 9 页代码 Echo.cs 内的 socket.connect 拼写缺失字母 e

    第 3 章 实践出真知:大乱斗游戏

    • 第 68 页 Main 代码的编写,应将前几页的 NetManager 类的 Update 调用,放置在 Main 的 Update 函数内调用。否则,OnEnter 条件无法触发。

    • 第 70 页 OnEnter 函数代码的编写,注意 otherHumans 在使用前应进行初始化。例如:

    // 声明时初始化
    public Dictionary<string, BaseHuman> otherHumans = new Dictionary<string, BaseHuman>();
    
    // 或者 在 Awake 里初始化
    private void Awake()
    {
        otherHumans = new Dictionary<string, BaseHuman>();
    }
    
    • 第 89 页 Hit 协议,此处描述的协议并非最终代码使用的协议,具体协议应参考第 91 页的代码。格式为: Hit|<攻击发动者>,<伤害承担者>

    第 4 章 正确收发数据流

    • 第 96 页的图 4-6 半包现象,其中第二个文字描述错误,应为 接收端 Receive 而非 发送端 Receive

    • 第 105 页的 OnReceiveData 函数代码,其中在处理 readBuff 获取消息时,读取了 buffCount 的字节长度,此处应使用 bodyLength 更合适, 代码如下:

    string s = System.Text.Encoding.UTF8.GetString(readBuff, 2, bodyLength);
    
    • 第 119 页在描述 Queue 的使用方法时,为了保证队列使用方法的一致性,可将 First() 替换为 Peek()First() 是需要引入 System.Linq 命名控件的,而 Peek()Enqueue()Dequeue() 均属于队列类的基本操作。两者使用效果一致。

    • 第 126 页读写功能小节,其中 Read 方法的代码里对数组的复制,此处源数组的读取下标应为 readIdx 而不应该为 0 ,否则当 bytes 数组的 length > 8 时, 数组不移动而下次读取仍然从 0 开始读取,这导致数据错误。代码如下:

    public int Read(byte[] bs, int offset, int count){
      count = Math.Min(count, length);
      // 此处应修改为 readIdx
      Array.Copy(bytes, readIdx, bs, offset, count);
      readIdx += count;
      CheckAndMoveBytes();
      return count;
    }
    
    • 第 131 页将 ByteArray 应用到异步程序的代码, 此处存在代码错误。作者的想法应该是读取 bodyLength 后,当数组内接收字节长度为一个完整的 package 则进行解析。原代码如下:
    if ( readBuff.length <= 2 )
      return;
    int readIdx = readBuff.readIdx;
    byte[] bytes = readBuff.bytes;
    
    Int16 bodyLength = (Int16) ((bytes[readIdx + 1] << 8) | bytes[readIdx]);
    
    // 此处存在错误, length 包括了长度的两个字节,实际应为 readBuff.length < 2 + bodyLength
    if (readBuff.length < bodyLength)
      return;
    
    readBuff.readIdx += 2;
    
    

    结合书中对 ByteArray 的方法描述,应修改为以下代码:

    if ( readBuff.length <= 2 )
      return;
    
    // 注意 ReadInt16 函数内,会对 readIdx 执行 + 2 操作
    Int16 bodyLength = readBuff.ReadInt16();
    
    // 由于 length 指的是 writeIdx - readIdx , 所以可直接与 bodyLength 比较
    
    if (readBuff.length < bodyLength)
    {
      // 如果字节数达不到长度,则需要继续等待接收,并将 readIdx 还原为读取长度之前
      readBuff.readIdx -= 2;
      return;
    }
    

    第 7 章 通用服务端框架

    • 第 204 页心跳机制,这里使用了 lastPingTime 记录最近一次接收 Ping 指令的时间。按照书中的代码的话,需要在客户端接入的时候初始化一次这个变量。否则,在第 206 页的 CheckPing 方法中,判断一直生效,因为 lastPingTime 初始化为 0 。

    • 第 221 页 IsAccountExist 的代码中, try...catch 捕获的异常输出描述有误,代码如下:

    ...
    catch(Exception e){
      // 书中描述为 IsSafeString
      Console.WriteLine("[ 数据库 ] IsAccountExist err, " + e.Message);
      return false;
    }
    

    第 8 章 完整大项目《坦克大战》

    • 第 249 页移动控制的代码,其中 MoveUpdate 函数最后控制 GameObject 移动时,无需重复嵌套 transform ,如 transform.transform.position += s; 只写前面的 transform 即可。

    • 第 258 页编写跟随摄像头脚本代码,在 LateUpdate 函数中部分代码缺失,但文字描述有提及。文中丢失 Vector3.MoveTowards 方法。如下:

    // 原文代码
    void LateUpdate(){
      // ... 前面代码省略,此处有误
      // 应为 Vector3.MoveTowards(cameraPos, targetPos, Time.deltaTime * speed);
      cameraPos = (cameraPos, targetPos, Time.deltaTime * speed);
    }
    

    第 9 章 UI界面模块

    • 第 281 页界面层级管理的描述中,定义枚举类型 Layer,分别有 Layer.Panel 和 Layer.Panel 两项。 这里笔误,结合上下文应该是 分别有 Layer.Panel 和 Layer.Tip 两项。

    • 第 282 页的 Init 函数代码内,有一行代码有误 layer.Add(Layer.Tip, tip);

    • 第 288 页的登录面板部件说明表格中,出现笔误,密码文字标签应为 PwText 而不是 PwTest

    • 第 289 页的登录面板类的段落文字描述中,新建文件夹统一放置面板脚本文件,命名出现笔误, 应为 module/Login 而不是 mudule/Login

    • 第 298 页 OnShow 函数 代码笔误,根据文字描述,本节代码是关于注册窗口 RegisterPanel 的,而在 OnShow 函数内监听的消息是登录 MsgLogin,此处应改为 MsgRegister。下方的 OnClose 函数一样需修改, 不过前面小节编写的 LoginPanel 代码应做相同处理,作者前面没有加上。代码如下:

    public override void OnShow(params object[] args){
        // 前面代码省略...
        NetManager.AddMsgListener("MsgRegister", OnMsgRegister);
    }
    
    public override void OnShow(params object[] args){
        // 前面代码省略...
        NetManager.RemoveMsgListener("MsgRegister", OnMsgRegister);
    }
    

    第 10 章 游戏大厅和房间

    • 第 313 页的操作栏部件说明表格中,出现笔误,刷新按钮应为 RefreshButton 而不是 ReflashButton

    第 11 章 战斗和胜负判定

    • 第 376 页 ResetPlayers 函数内,设定 Player 的生命值在设置出生点时直接赋值,无需再写一个循环赋值。

    • 第 379 页胜负决断函数,代码里函数名拼写有误,应为 Judgement

    相关文章

      网友评论

          本文标题:Unity3D 网络游戏实战(第2版)

          本文链接:https://www.haomeiwen.com/subject/ilxetrtx.html