unity官方内置网络unet的实例教程(五)
本课程的地址:
第一节.www.jianshu.com/p/d4e35e547081
第二节:www.jianshu.com/p/d7481e83317c
第四节:www.jianshu.com/p/5b211f3f4ec6
第六节:www.jianshu.com/p/c58c1a888595
第七节:www.jianshu.com/p/b8cc2d15e2b5
第八节:www.jianshu.com/p/9f8f18a46266
我们接着上一章,继续将角色的射击行为进行网络化。为了使射击网络化,我们得更新 Bullet子弹预制体和脚本。
首先,打开Unity编辑器,找到Bullet子弹预制体,添加 NetworkIdentity 组件 和 NetworkTransform这样使子弹预制具有ID识别和变换信息的网络功能。见下图

接着,选中Hierarchy窗口中的 NetworkManager ,打开右侧属性面板的 Spawn Info,在 Registered Spawnable Prefabs的下面点击加号,然后将子弹预制体拖进去。见下图蓝色位置。

接下来,更新 PlayerController 脚本的代码,打开它进行编辑,最终的代码如下(动手实践是最好的学习方法,我把代码做成难以复制的图片,希望可以让大家加深印象):

好了,保存脚本,回到Unity,保存,重新生成游戏,进行测试,现在子弹可以同步啦,但是打到另外一个玩家,子弹被它的铁布衫给反弹走了,好吧,接下来我们去掉这一逆天的武功。
注:
在这里简单借鉴下官方介绍[Command]的概念
[Command]属性表示下面的函数将被客户端调用,将在服务端上运行。函数中的任何参数都将自动通过Command.Command传递给服务器,只能从本地玩家发送命令。在网络游戏中,会在服务端和所有的客户端产生游戏对象,服务端有专门负责进行管理的底层脚本,当服务端的数据发生变化,就会传输给所有的客户端,它们也随之改变。当客户端发送销毁等指令的时候,服务端也执行这些特殊的函数,并将数据发送给所有的客户端,即便是你刚进入游戏,也能同步即时的状态。
为了去掉玩家的铁布衫,需要给玩家添加生命值和相关的碰撞检测,让角色具有生死的概念。当然还是比现实的人多了复活的技能,谁叫它带着那么酷的墨镜呢!
首先,我们在Scripts文件夹里面新建一个脚本,重命名为:Bullet,将它拖到Bullet预制属性栏的下面。(或者可以在Bullet属性栏直接添加脚本并重命名)

打开脚本,开始写代码:

好了保存脚本,回到Unity编辑器,保存,重新生成游戏进行测试,两个角色互相射击,子弹碰撞到角色身体的时候,不再反弹而是消失了,然后可以看到在console控制台里面输出了:

咦?发现没有?怎么子弹消失自动同步了呢?我们没写关于子弹消失的同步代码怎么就自动实现了呢?原来在上面我们把子弹交给NetworkManager管理,所以当客户端调用销毁命令,服务器就执行了销毁,并发送给所有客户端子弹销毁命令。这些都是在底层代码实现的,我们知道如何使用就够了,如果想详细了解请去官方查阅相关信息。
好吧,子弹是击中了游戏中其他角色,可是现在这些角色都没有生命值,也看不到掉血什么的。给角色加个血条和生命值吧,一般的游戏不都是这么做的么?老规矩,先制作单机版本。
新建C#脚本,重命名为:Health,将它拖拽到Player属性面板中,打开它,开始写代码:
设置玩家最大生命值为100:public const int maxHealth = 100;
设置玩家当前生命值 默认等于最大生命值:public int currentHealth = maxHealth;
创建减少生命也就是造成伤害的公共函数:Take Damage()
最终的脚本如下:

接着更新子弹的脚本,调用刚才的Health脚本中的Take Damage()函数:

这样子弹就可以伤害角色了,但是不能直接看出来,所以加一个简单的血条吧。
右键,新建UI Image,这样也创建一个新的 Canvas和一个 EventSystem 。将Canvas重命名为:Healthbar Canvas,重命名Image为 “Background”,将 Rect Transform 的 Width 改为100 ,将Height至10。

将 Image组件的 Source Image 设定为 Input Field Background,将颜色设定为红色。

复制Background图片,重命名为:Foreground,首先在属性面板进行重置:

把它作为Background的子物体,像这样:

选中Foreground,选中颜色为绿色,将锚点设置为。

将Playerprefab从项目窗口拖到Hierarchy中,选中Healthbar Canvas,修改Canvas’ Render Mode 为World Space,拖拽Healthbar Canvas到 Player下面做为它的子物体。

选中 Healthbar Canvas,重置 RectTransform为默认值。

修改RectTransform’的缩放 Scale为(0.01, 0.01, 0.01),位置Position为(0.0, 1.5, 0.0),选中Player,在属性面板 上方点apply


保存游戏。为了使血条反映角色的生命值变化 Healthbar Canvas,需要修改Health脚本:

保存脚本,回到Unity,选中Player,在属性面板中找到Health脚本,按下图将Foreground拖入。

现在,让血条始终面对玩家,不然角色转身就变成一条线了。
新建C#脚本,重命名为:Billboard,拖拽它到Healthbar Canvason属性面板内,打开脚本,写下面的代码:

保存脚本,回到Unity,选中Player预制,像以前一样点击属性面板右上角的apply。然后删除Player预制。保存Unity。像以前一样,重新生成游戏,然后进行联网测试。可以发现:
目前,当玩家控制的角色相互射击时,Bullet和Health脚本在每个客户端和服务器上工作了,但是都在“本地”工作,没有发生同步,然而,子弹通过网络管理器被管理为生成对象,它们将被销毁。血条也没有变化。