unity文件 中unity文件Script文件 出现错误

Photon、订阅、托管选项和如何开始的概述

Network首字母缩写,后文同不再重复解释)总是连接一个为玩家提供房间、匹配玩家并提供同房间通信的专用服务器。Photon unity文件 Networking在后台不止使用一个服务器:

几个“游戏服务器”运行特定的房间(匹配的)同时一个“主服务器”保持追踪各个房间并匹配玩家。

服务器端你有两個选项

Exit Games Cloud是一个为你提供托管和负载均衡的Photon服务器(该服务器由ExitGames公司全局管理)的服务。提供免费试用而且商业通途的订阅成本是相对低廉的。(这个云端类似于国内的阿里云和腾讯云它们都是提供可托管的云服务器服务)

服务运行一个固定的逻辑,所以你不能实现你洎己的服务器端游戏逻辑相反,客户端需要被授权

客户端通过“applicationid”分隔,这关系到您的游戏标题和“游戏版本”有了这个,你的玩镓不会与另一个开发或旧的游戏迭代发生冲突

如果你是在资源商店(资源商店是指unity文件里面的Asset Store,后文同)里购买的一个带Photon云服务订阅的插件包跟着这些步骤:

l  发送一封带如下类容的邮件到

你的姓名和公司(如果有的话)

资源商店的发票/购买 ID(购买后会收到带发票嘚邮件)

作为替代的Photon云服务,你可以运行自己的服务器和开发服务器端逻辑在我们的“负载平衡”C#解决方案上这将为您提供服务器逻辑嘚完全控制。

Kit的首字母缩写意思是软件开发工具包。)可以在这里下载:

五分钟内启动服务器教程:

当你导入PUN时“向导”窗口会弹出。輸入您的电子邮件地址登记到云端跳过这一步输入一个现有的帐户的AppID或切换到“自托管”Photon 输入您的服务器的地址。

如下图所示这将在項目中(在PhotonServerSettings里)创建一个云服务或您自己的Photon服务器的配置。

PUN由相当多的文件组成但只有一个真正重要:PhotonNetwork。这个类包含所需的所有函数和變量如果你有定制要求,你也可以修改源文件-毕竟这个插件只是Photon的实现

Interface的首字母缩写,意思是应用程序接口)是如何工作的这里马仩就有几个例子。

PUN总是使用一个主服务器和一个或多个游戏服务器主服务器管理当前运行在不同的游戏服务器上的游戏,并在当你加入戓创建一个房间时将提供一个游戏服务器地址PUN(客户端)自动切换到游戏服务器。

个人匹配被称为房间他们是相互独立的,并以名称為标记ID房间被分组成一个或多个大厅。大堂是匹配的可选部分如果你明确地不使用自定义大厅,PUN将使用一个由所有房间组成的单一的夶堂

默认情况下,在连接后PUN将加入默认的大厅这个大厅向客户发送一个现有的房间列表,所以玩家可以选择一个房间(通过名称或一些列出的属性)使用PhotonNetwork.GetRoomList()方法来进入当前列表。列表在时间间隔内被更新来保持低流量

客户端不必加入一个大厅来加入或创建房间。如果伱不想在您的客户端显示房间列表在你连接之前设置PhotonNetwork.autoJoinLobby= false,你的客户端将会跳过大堂

你可以使用一个以上的大厅来组织你游戏所需的房间列表。PhotonNetwork.JoinLobby是加入一个特定的大厅的方法你可以在客户端上完成操作-服务器将会保持跟踪它们。只要名称和类型相同对应的TypedLobby将对于所有的愙户端都一样。

一个客户总是只在一个大厅而在一个大厅里,创造一个房间也将涉及到这个大厅多个大厅意味着客户端得到更短的房間列表,这是很好的房间列表是无限的。

玩家不会注意到对方在大厅里也不能发送数据(以防止当它会变得拥挤时发生问题)。

服务器都在专用的机器上运行-没有所谓的玩家托管的“服务器”您不必费心记住服务器的组织,因为API为你都隐藏了

上面的代码是任何使用PhotonNetwork功能的应用所必须的。它设置你的游戏客户端游戏版本和使用安装向导配置(保存在:PhotonServerSettings上文中有截图)。当你自己托管Photon服务器时也可以使用该向导另外,使用Connect()方法连接服务器时你可以忽略PhotonServerSettings文件

Photon的负载均衡逻辑是使用AppID区分你的和别人的玩家。同样的游戏版本将新客户端嘚和旧客户端的玩家区分开来由于我们不能保证不同PUN版本之间相互兼容,我们在你的游戏版本发送之前添加PUN版本到你的游戏版本(从PUN

下┅步你会想加入或创建一个房间。下面的代码展示了一些必要的功能:

目前正在运行的游戏列表是由主服务器的大厅提供的它可以像其他房间一样被加入,但只提供和更新的房间列表PhotonNetwork插件会在连接后自动加入大堂。

当你加入一个房间时列表将不再更新。

显示房间列表(在大厅里):

另外游戏可以使用随机配对:它会尝试加入任何房间,并且如果没有一个房间可以容纳该玩家就会失败在这种情况丅:创建一个没有名字的房间,并等待直到其他玩家随机加入

高级匹配和Room属性

完全随机的配对并不总是玩家喜欢的东西。有时你只想玩┅个特定的地图或只是2vs2

Photon云和负载均衡里,你可以任意设定房间的属性和那些在JoinRandom加入的玩家过滤器

房间属性是同步到所有房间中的玩镓,并在跟踪当前的地图、回合、开始时间等信息时很有用这些信息被当作字符串键值的散列表来处理。优选短键

您也可以将选定的屬性发送到大厅。这使得它们可以被列表列出也可以被随机配对。并不是所有大厅里的房间属性都是有趣的所以你在创建房间的时候萣义一系列的属性。

请注意“ai”还不是房间属性里的一个键值它不会出现在大厅,直到它在游戏里通过Room.SetCustomProperties()方法被设置当你改变“map”或“ai”的值时,他们也会在大厅里在一个很短的延迟后被更新

保持列表短以确保性能不会受到加载列表影响。

JoinRandom方法中,你可以传递一个包含該方法所期望的房间属性和最大玩家值的哈希表当服务器为你选择一个“合适的”房间时这些作为过滤器。

如果你传递更多的过滤器属性一个房间与它们相匹配的机会较低。最好限制选项

确保你从不过滤那些大厅没有的属性(见上文)。

PUN使用几个回调让你的游戏知道狀态的变化如“连接”或“加入游戏”。所有您需要做的是在任何MonoBehaviour中实现合适的方法并在事件发生时被调用。

为了获得一个良好的可鼡回调函数的总览可以在Photon.PunBehaviour类中看一看。如果你让你的脚本继承PunBehaviour(代替MonoBehaviour)您可以很容易地重写个人回调函数。如果你开始键入“override”关键芓你的编码IDE应该为您列出了回调,所以它们在编码时也很容易找到(IDEIntegrated

这包括建立游戏房间的基本知识。接下来是游戏中的实际交流

在一个房间里,你可以发送网络信息给其他连接的玩家此外,你能够发送缓冲的消息缓存消息也将被发送到未来连接的玩家(以生荿玩家为例)。

Call的首字母缩写意思是远程过程调用,下文会有详细解释)还是利用PhotonViewPhoton消息视图详见后文)属性OnSerializePhotonView。虽然有更多的网络互動你可以监听回调函数来检测特定的网络事件(如OnPhotonInstantiate, OnPhotonPlayerConnected)并且你可以触发它们中的一些事件(也就是说会调用实例化方法PhotonNetwork.Instantiate)。不要担心如果伱困惑的最后一段,下一段我们将解释每一个主题

当组在任何PhotonView上被改变时是不被同步的。保持photonviews在所有客户端上在同一组里是由开发人员決定的如果需要这样的话。对同样的photonviews使用不同的组数在几个客户端会导致一些不一致的行为(PhotonView是用于发送视图消息的脚本组件)

一些網络消息只在接收端检查他们的接收组,即:

这是技术原因:Photon服务器只支持不被缓存且不是针对特定的演员的信息群体这在未来可能会妀变。

为了发送消息和可选的实例化/分配其他的PhotonViews在你的游戏中每时每刻都需要至少一个PhotonView.

如果你将Transform挂到PhotonView的观察属性上,你可以选择同步PositionRotationScale或者在玩家身上的这些字段组合这对那些原型或小游戏可以是一个伟大的帮助。注:任何观察到的值的一个变化将发送所有观察到的徝-不仅是单独改变了的值此外,更新不是平滑的或以内插值替换的

一个PhotonView 可以被设置来观察一个MonoBehaviour。在这种情况下该脚本的OnPhotonSerializeView方法将会被調用。这种方法被调用来根据该脚本是否被本地玩家控制来读写一个对象的状态

下面简单的代码显示了如何在几行代码中添加字符状态哃步:

如果你发送”ReliableDeltaCompressed”的东西,确保总是以同样的顺序写入数据到二进制流(二进制01所组成的数据像是溪流一样所以在英文中被称为Stream)。如果你没有写入数据到PhotonStream更新不发送。这在暂停时可能有用现在,以另一种方式交流:RPCs

远程过程调用(RPCs)正是顾名思义:方法可鉯在同房间的远程客户端上被调用。要启用远程对MonoBehaviour中某个方法的调用你必须应用注解:[PunRPC ]

一个PhotonView实例需要在同一游戏对象上来调用标记功能。

组件然后在它上面调用RPC

因此不是直接调用目标方法,而是在一个PhotonView上调用RPC()方法提供调用方法的名称,哪些玩家应该调用该方法然后提供一个参数列表。

注意:用于RPC()方法的参数列表必须符合预期的参数个数!如果接收客户端找不到匹配的方法则会记录一个错誤。这个规则有一个例外:RPC方法的最后一个参数的类型可以是PhotonMessageInfo类型这将为每个调用提供一些语境。

RPCs和负载水平的时机

RPCs在远程客户端的具體PhotonViews上被调用并且始终以与之匹配的客户端为目标。如果远程客户端不知道匹配的PhotonViewRPC丢失。

丢失RPCs一个典型的原因是当客户端加载和设置等級时一个客户更快或在房间里更长一段时间,并发送重要的RPCs到那些在其他客户端上还没有加载好的目标对象同样的情况发生在RPCs缓冲时。

解决方法是在加载场景的时候暂停消息队列下面的代码展示了你可以怎样操作:

禁用消息队列将会延迟进来的和输出的消息,直到消息队列被解锁显然,当你准备好继续的时候解锁消息队列就非常重要了

属于上一个加载场景但是仍然到达的远程过程调用RPCs将会在这个時候被丢弃。但是你应该能够用RPC来在两个场景间定义一个间断

unity文件网络之间的区别

person)服务器通过unity文件客户端运行(所以是通过其中一個玩家,也就是说客户端也可以是服务器服务器也可以是客户端)

l  Photon也是基于服务器-客户端,但是有一个专用的服务器;不再有由于主机離开而连接中断

因为防火墙/路由器等。连接永远不能被保证有一个较低的成功率。

Private Network的首字母缩写意思是虚拟专用网络)。

Photon击败unity文件網络性能我们还没有数字来证明这一点,但库已经优化了几年了此外,由于unity文件服务器是玩家托管延迟/信号查验通常是更糟;你依靠玩家作为服务器的连接。这些连接永远不会比你的专用Photon服务器的连接更好

unity文件网络解决方案一样,PUN插件也是免费的您可以为您的遊戏订阅使用Photon云托管服务。或者你可以租用自己的服务器并在上面运行Photon。免费许可证可以使多达100个玩家同时在线其他许可证是一次性費用(因为您做托管)并且解除并发用户限制(当然,仍然会受到服务器和宽带的限制)

unity文件似乎并没有给他们的网络实现的太多优先。很少有功能改进和错误修正也是很少Photon的解决方案是积极维护和部分是可用的源代码。此外Photon已经提供了比unity文件更多的功能,如内置的負载平衡和离线模式

Photon主服务器和朴素的UNet主服务器有一点不同的是:在我们的例子中,它是一个在所谓的“游戏大厅”里列出当前正在进荇的游戏房间名称的Photon服务器像unity文件的主服务器,它将客户端转化成游戏服务器实际的游戏在这些客户端服务器中完成。

在每一场游戏伱需要为每一个玩家实例化一个或更多的玩家对象下面列出各种要做的选项。

PUN可以通过传递一个起始位置、旋转和预设名到PhotonNetwork.Instantiate方法中来自動完成孵化一个对象要求:预制应可以直接在Resources/文件夹下找到,这样才可以在运行时加载预置注意网络播放器:在资源文件夹中的一切嘟会从默认的第一个场景加载为二进制流。在网络播放器设置下您可以通过使用“First streamed level”指定第一级通过使用Resources文件夹中的资产。如果你为你嘚第一个游戏场景设置这个如果你的预加载器和主菜单不使用Resources文件夹下的资源,它们将不会被减慢

那么,整个开发文档有三百多页這里就不全部写出来了,请需要的朋友下载附件中完整翻译的PDF文档

}

通过脚本之家下载dll的朋友可将丅面的代码保存为“注册.bat“,放到dll文件同级目录(只要在同一个文件夹里面有这两个文件即可)双击注册.bat,就会自动完成Assembly-unity文件Script-firstpass.dll注册(win98不支持)

丅面是系统与dll版本对应的注册bat文件(64位的系统对应64位dll文件,32位系统对应32位的dll文件如果64位的系统安装32位的dll文件,请将下面的system32替换为SysWOW64即可)

}
项目中引用了一个插件源码修妀插件源码的时候遇到一个问题,就是一个脚本文件调用另外一个脚本文件的函数的时候一直提示缺失命名空间的引用找不到此对象。泹是我明明已经把它的命名空间加上了还是提示错误,后面才发现原来这两个脚本属于两个程序集定义当前调用的脚本程序集没有包含另外一个,导致引用失败

网上找了一篇博客对 .asmdef文件进行了详细的介绍,这里贴出原文链接:

得益于此功能开发者可以在一个文件夹Φ自定义程序集。定义明晰的依赖关系可以确保脚本更改后,只会重新生成必需的程序集减少编译时间。

项目越大脚本越多编译时間必然会越长。在进行项目迭代时这很容易制约效率,因此设置好程序集定义文件可以提高工作效率减少脚本编译的时间。

如上图洳果你仅更改了Main.dll中的脚本,其它程序集都不需要重新编译由于Main.dll包含的脚本更少,因此它的编译速度比Assembly-CSharp.dll更快 同样,Stuff.dll的更改仅会导致Main.dll和Stuff.dll重噺编译

注意:ADF所在的文件夹名称,以及ADF的文件名跟程序集的名称没有关系。程序集的名称只跟ADF文件中的Name属性有关创建时对ADF命名的话,属性中的Name也会相应修改

下面我们使用一个实际案例看看这个功能如何使用
例如在2017.3之前的版本中的的脚本目录结构是这样的

我们按照目錄结构分别创建一个ADF,并且在Scripts文件夹下创建一个Main的ADF

我们随便打开一个脚本可以看到VS将这几个分别识别为了几个C#工程

刚刚创建的ADF还差一些沒有设置,就是依赖关系比如Network要依赖SDK中的内容,如果不设置就会像下图一样报错

下面我们来修复这个问题,选中Network ADF文件然后在References中添加SDK嘚引用,别忘了点击下面的Apply

现在不报错了再打开VS,也不报错了可以看到Network这个C#工程中加了一条SDK的引用

常见问题:多层级的ADF

如果一个文件夾及子文件夹中,有多个ADF每个脚本被添加到离这个脚本最短路径的ADF中去。
比如上面实战环节的Utils中并没有创建ADF那么ADF就会被添加到父目录嘚Main中

如果你搞不清楚一个脚本究竟被包含在了哪个ADF中,只需要选中这个脚本在Inspector面板中就会清楚的看到

强烈建议你对项目中的所有脚本使鼡ADF,或完全不使用否则,没有使用ADF的脚本会在每次ADF重新编译时也被重新编译这会减少你在项目中ADF所带来的好处。

还有就是一定要对目錄结构好好进行划分

感觉这个功能设计是好的但是实际项目中由于脚本文件的划分,和自己定义公共插件库的划分不是非常明确导致腳本直接会经常出现引用,如果引用过多就导致ADF失去了他的优势,反而感觉比较麻烦容易出现问题。个人感觉如果项目编译真的很慢而且项目脚本功能有明确的划分,实在ADF还是不错的选择
}

我要回帖

更多关于 unity文件 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信