此篇来填坑,有些坑是unet自身问题,而大部分则是理解不准确造成的(或者unity定义太复杂)

问题一: isLocalPlayer 值一直是false

出现场景:NetworkLobbyPlayer中重写 OnClientEnterLobby()方法时出现(public override void OnClientEnterLobby()),当时想法是当玩家进入lobby后对local Player进行个性化设置,但返回结果一直是false。此问题在其他情况可能也会出现。

解决方案:此问题主要是对isLocalPlayer,isServer以及isClient定义不清楚。isServer:在服务端的活动的player,此值均为true,即不管是server端StartHost时自己建立的client还是Server Spawn产生,只要在服务端显示,此值均为true。isClient:由Server端spawn产生,并作为client运行的,此值均为true,即只要是Spawn产生的,不管是在服务端还是在客户端,此值均为true。所以服务端存在的player,isServer和isClient均为true,客户端isclient均为true,isServer均为false。(isServer与isClient并没有对立关系)。isLocalPlayer是生成的玩家可以控制的player,不管是服务端(如果服务端也有玩家)还是客户端均只有一个player的isLocalPlayer值为true。isLocalPayer在执行OnStartLocalPlayer回调时赋值为true,即生成本地的player时赋值,而OnClientEnterLobby回调时只是数据层面已经客户端连接进来,但是还没有建立client的gameobject,所以此时isLocalPlayer并未赋值(默认false)。而且只有本地

玩家的player是Create产生的,先回调OnClientEnterLobby,后回调函数OnStartLocalPlayer,而且其他玩家(敌人)则是有服务端Spawn产生的,只调用回调OnClientEnterLobby。

问题二: Server disconnect due to error:timeout

出现场景:当Server运行时,client断开时出现(第一次断开不会出现,第二次断开以及以后均会出现)

解决方案:无法解决,但不影响运行。谷歌很多此,在unity论坛中有unity人员(自己号称)unet自身bug,此问题类似于tcp或者udp编程时,客户端主动断开连接,而服务端虽然接受到了断开的消息(甚至没有接收到),但依然接受下一条消息,此时报错(如果有人看过作者写过的一个tcpServer,会看到类似问题)。当然对于unet来说此问题可能涉及到的东西比较复杂,号称已经解决,但是在后续版本中一直存在,笔者为unity2017,仍存在此问题,并未下载补丁进行尝试,谷歌出来的此问题来源如下,如果不想出现此问题可以在重写OnServerDisconnect时不调用基函数,只添加NetworkServer.DestroyPlayersForConnection(conn)即可。

public virtual void OnServerDisconnect(NetworkConnection conn)
{
NetworkServer.DestroyPlayersForConnection(conn);
if (conn.lastError != NetworkError.Ok)
{
if (LogFilter.logError)
{
Debug.LogError("ServerDisconnected due to error: " + conn.lastError);
}
}
}

问题三: Client disconnect due to error:timeout

出现场景:当在lobby场景中调用DropConnection断开玩家与Server的连接时出现

解决方案:无法解决,但不影响运行。谷歌很多此,此问题也没有很好的得到解决,有点类似与问题三。

问题四: A connection has already set as ready....

出现场景:远程客户端调用RemovePlayer()退出游戏又重新加入时出现。在OnClientSceneChanged的base中会调用AddPlayer,也会出现此问题(目前选择直接暴力注释掉base方法)

解决方案:unity远程客户端和服务端建立连接时先建立NetworkConnection,然后分别建立服务端和客户端的游戏物体,所以调用removePlayer方法时只是在clientscene中removePlayer,并没有断开连接,所以在重新加入游戏时会出现此问题(即本身的connection还存在),此问题不影响运行,但是不确定会有其他隐患,多以在上一篇中远程客户端断开连接时采用matchmaker的DropConnection方法(调用此方法时会自动移除服务端和游戏端的游戏物体),但此方法又会引发问题三,可以采用connectionToServer进行解决,具体看问题六。

问题五: Local Connection already exists 以及ClientScene::AddPlayer: playerControllerId of 0 already in use

出现场景:建立游戏的主机销毁游戏时出现

解决方案:主机建立游戏,如果想要销毁游戏需要三步,第一步销毁player(remove Player方法),第二部断开connection(可以理解为销毁游戏即destroy Match),第三部StopHost。第一步时为了移除clientScene中的player,如果缺少则会引发ClientScene::AddPlayer: playerControllerId of 0 already in use问题。如果缺少第二部则会引发问题四,而且游戏不会销毁。如果缺少第三部,怎会引发 Local Connection already exists,因为不管是否销毁游戏,建立游戏主机的本机player即使服务端player,又是client端player,所以localconnection会一直存在,只有StopHost才会断开此本地连接。

问题六:connectionToClient以及connectionToServer应用

出现场景:此问题设计到离开游戏的定义。以魔兽争霸(frozenstone暴露年龄了)为例,局域网建立一个游戏,局域网内其他玩家加入此游戏,那么客户端(加入游戏的玩家)只能自己离开游戏,所以此时对应的问题四出现的场景即加入游戏的玩家自己离开游戏。建立游戏的玩家可以选择自己退出游戏(销毁游戏)也可以选择将不顺眼的玩家踢出,前者自己退出游戏对应问题五场景。那么踢出其他游戏时就是对应此问题。即要想踢出玩家,只要断开此玩家有服务端的连接即可。

解决方案:connectionToClient定义为服务端与客户端的连接,但是只在服务端有效(只有在服务端此connectionToClient变量才有效)。所以此情况下只要调用connectionToClient的Disconnect方法并dispose即可。相反,connectionToServer定义为仍然为服务端与客户端的连接,但是此方法只在local client有效,所以问题四也可以调用connectionToServer的Disconnect方法并dispose(此方法为测试,但从释义上将可行,并且应该可以避免问题四和问题三)

问题七:drop Connection与destroyconnection时场景重新加载

出现场景以及解决方案:第一次dropconnection时场景会重新加载(并非在dropconnection的回调中调用重新加载,二十直接在dropconnection方法中就重新加载),之后再次调用则不会重新加载,目前看不到内部代码,所以只能避免使用drop Connection,所以问题四中离开游戏时可以使用connectionToServer进行尝试。

destroyconnection是每次调用都会加载场景,其实可以理解,每次重新创建游戏时回到最初也是可以接受的,不过要想不重新加载只能查看源码了。

问题八:DontDestroyOnLoad问题

出现场景以及解决方案:在上一篇中开头讲过不要在自定义的LobbyManager中添加DontDestroyOnLoad,如果反复进行自身场景的加载就会一直不停的添加LobbyManager,即没加载一次都会生成一个新的LobbyManager,而原来的又不会销毁掉。而NetworkManager中已经存在,所以不要直接调用了,很多视频demo中都加了此语句,但是他们那些demo都是一根筋跑到底,没有出现重新加载的问题,所以此处要慎重,实现像调用可以看http://www.xuanyusong.com/archives/2938。而且如果添加了DontDestroyOnLoad还可能会出现中间

LobbyManager丢失的情况,之前做一个项目时,有一个插件也用到此方法,但是一重新加载就导致DontDestroyOnLoad对应的组件(脚本)获取不到,但是editor中查看此组件(脚本)时存在的,所以慎重调用。

问题九:超上限加入游戏

出现场景以及解决方案:当游戏设置玩家为2,即使人数已满,但仍然可以加入此游戏,但是加入后的游戏玩家显示会有问题,所以只能在加入游戏前自己做判断,不能靠unet自己处理。

问题十:ready后自动开始游戏

出现场景以及解决方案:当当前游戏中的所有玩家均ready后立马开始游戏,即当前只有一个玩家,没有达到游戏玩家数,若此玩家发送了准备(sendreadytobeginMessage),则服务端调用OnLobbyServerPlayersReady,并在其base方法中立马开启游戏,所以此处不能调用其base方法。

PS:到此为止,踩了很多坑,目找时间看看networkmanager源码,unet的思路很不错,如果发展好了将会使多人在线游戏开变得更加简单。他与传统的客户端服务端分离不同(即客户端与服务端是不同的类),他揉合在一起,但又设定好了不同的角色与权限,虽然理解起来比较费解,但是应用起来确实方便。

NetworkManager网络通讯_问题汇总(四)的更多相关文章

  1. NetworkManager网络通讯_破产版NetworkManager(五)

    根据对NetWorkServer 以及NetworkClient的理解,编写一个简易版的NetWork Manager.惯例全部代码放在最后 (一)NetWorkServer与NetworkClien ...

  2. NetworkManager网络通讯_NetworkManager(二)

    本文主要来实现一下自定UI(实现HUD的功能),并对Network Manger进行深入的讲解. 1)自定义manager 创建脚本CustomerUnetManger,并继承自NetworkMang ...

  3. NetworkManager网络通讯_Example(一)

    ---恢复内容开始--- 用户手册,范例精讲. 用户手册上给出了一个简单的范例,并指出可以以此为基础进行相开发,再次对范例进行精讲.(NetworkManager对使用unity的轻量级游戏开发有很大 ...

  4. NetworkManager网络通讯_NetworkLobbyManager(三)

    此部分可以先建立游戏大厅,然后进入游戏,此处坑甚多耗费大量时间.国内百度出来的基本没靠谱的,一些专栏作家大V也不过是基本翻译了一下用户手册(坑啊),只能通过看youtube视频以及不停的翻阅用户手册解 ...

  5. NetworkManager网络通讯_networkReader/Writer(六)

    unet客户端和服务端进行消息发送时可以采用上一节中方法,也可以直接用networkReader/Writer类进行发送 (一)服务端/客户端注册消息 ; m_Server.RegisterHandl ...

  6. 容联云通讯_提供网络通话、视频通话、视频会议、云呼叫中心、IM等融合通讯能力开放平台。

    容联云通讯_提供网络通话.视频通话.视频会议.云呼叫中心.IM等融合通讯能力开放平台. undefined

  7. DIOCP网络通讯流程

    DIOCP 运作核心探密   原文连接: http://blog.qdac.cc/?p=2362 原作者: BB 天地弦的DIOCP早已经广为人知了,有很多的同学都用上了它,甚至各种变异.修改版本也出 ...

  8. dicom网络通讯入门(2)

    第二篇,前面都是闲扯 其实正文现在才开始,这次是把压箱底的东西都拿出来了. 首先我们今天要干的事是实现一个echo响应测试工具 也就是echo 的scu,不是实现打印作业管理么.同学我告诉你还早着呢. ...

  9. Socket网络通讯开发总结之:Java 与 C进行Socket通讯 + [备忘] Java和C之间的通讯

    Socket网络通讯开发总结之:Java 与 C进行Socket通讯 http://blog.sina.com.cn/s/blog_55934df80100i55l.html (2010-04-08 ...

随机推荐

  1. 基于MFCC的语音数据特征提取概述

    1. 概述 语音是人类之间沟通交流的最直接也是最快捷方便的一种手段,而实现人类与计算机之间畅通无阻的语音交流,一直是人类追求的一个梦想. 伴随着移动智能设备的普及,各家移动设备的厂家也开始在自家的设备 ...

  2. 『嗨威说』算法设计与分析 - STL中Sort函数的实现原理初探

    本文索引目录: 一.对Sort算法实现的个人阅读体会 二.Sort算法使用的三个排序算法的优点介绍 2.1 插入排序的优缺点 2.2 堆排序的优缺点 2.3 快速排序的优缺点 2.4 新的结合排序—— ...

  3. Entity Framework Core生成的存储过程在MySQL中需要进行处理及PMC中的常用命令

    在使用Entity Framework Core生成MySQL数据库脚本,对于生成的存储过程,在执行的过程中出现错误,需要在存储过程前面添加 delimiter // 附:可以使用Visual Stu ...

  4. [Job] 找工作小结

    有近2个月没有更新博客,主要精力放在了投递会议论文和秋招找工作方面.这里简单总结一下秋招笔试面试的几点建议和感受. 投递的NLP算法工程师岗位,主要参加过面试的公司有腾讯(春招),蚂蚁金服(春招),追 ...

  5. 浏览器端获取短信验证码java实现——阿里云短信服务

    需求:浏览器端输入手机号,获取验证码.点击登录,验证验证码是否输入错误.是否超时等情况,一旦校验通过,将用户数据保存到数据中(业务逻辑). 前提:注册阿里用户,开通短信服务,申请key.秘钥.签名.短 ...

  6. SpringBoot 定时任务实现方式

    定时任务实现的几种方式: Timer:是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务.使用这种方式可以让你的程序按照某一个频度执行,但 ...

  7. 简单动态字符串(SDS)

    SDS 前提:在redis中,C字符串只会作为字符串字面量用在一些无须对字符串进行修改的地方,比如打印日志: redisLog(REDIS_WARNING, “Redis is ready to ex ...

  8. 如何评价一个VR体验设计?

    如何评价一个VR系统的体验是好是坏?或者说,哪些因素会破坏一个VR的体验? Kruij和Riecke教授在IEEE VR会议上提到了四个角度:Congnition,Game User Experien ...

  9. CSS定位与布局

    我们在编写网页代码时,首先应该做的就是设计好页面的布局形式,然后再往里面填充内容.网页布局的好与坏,直接决定了网页最终的展示效果.PC端常见的网页布局形式有两列布局.三列布局等.在CSS中,我们通常使 ...

  10. Python 必备面试基础知识-3

    今天继续分享 Python 相关的面试题,你准备好了嘛! 网络编程篇 1. 简述 OSI 七层协议 是网络传输协议,人为的把网络传输的不同阶段划分成不同的层次. 七层划分为:应用层.表示层.会话层.传 ...