Unity多人游戏和网络功能(三) 游戏物体的派生

2024-04-17 14:08

本文主要是介绍Unity多人游戏和网络功能(三) 游戏物体的派生,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

游戏物体的派生

在Unity中,使用Instantiate()函数创建新的 游戏 物体有时也被叫做Spawning,在网络HLAPI中,派生(Spawn)有更特殊的含义。在服务器权威式的网络模式下,在服务器上派生一个物体,意味着这个物体也同时应该在相连的客户端上创建,而且这个创建的物体应该被派生系统所管理。物体状态在服务器上的更新会被实时发送到客户端,当物体在服务器上被销毁时,这个物体也应该同时在客户端上被修改。派生出的物体还同时应该被添加到服务器管理的网络物体的集合中,当有一个新的客户端加入时,这些物体也都应该在新的客户端上被派生出来。这些物体每个都有一个唯一的网络标识符,而且标识符在服务器和客户端上是一致的。

当网络标识的物体在客户端上被派生的时候,他们应该具有和服务器上相同的状态,包括物体的位置,运动状态和同步的变量。因此一个客户端被创建的时候,应该总是拿到最新的数据,这可以避免客户端上在错误的初始位置创建物体,又在更新数据包到达的时候瞬间移动物体的问题。

这听起来很好,但是马上问题就来了。如何在客户端上创建物体?当物体的状态改变的时候,又有一个新的客户端连接进来怎么办?在新连接的客户端上应该创建物体的哪个版本?

客户端上创建的物体是从服务器上传给NetworkServer.Spawn的预设体中创建的。在NetworkIdentity属性面板中显示了这个物体的资源ID,这是一个标识预设体的ID。为了让这个过程工作的更有效,客户端需要执行一个注册过程,他们必须要执行ClientScene.RegisterPrefab来告诉系统客户端创建物体的资源ID。

注册的过程最简单的方式是在NetworkManager的编辑器中完成,“Spawn Info”部分可以让你不用写一行代码就完成预设体的注册。也可以在NetworkClient创建的时候用代码来完成。代码如下:

using UnityEngine;
usingUnityEngine.Networking;

public classMyNetworkManager : MonoBehaviour
{
public GameObject alienPrefab;

NetworkClient myClient;

// Create a client and connect to theserver port
public void SetupClient()
{
ClientScene.RegisterPrefab(alienPrefab);

myClient =  new  NetworkClient();

myClient.RegisterHandler(MsgType.Connect,OnConnected);
myClient.Connect("127.0.0.1",4444);
}
}

在这个例子中,用户应该拖放一个预设体到MyNetworkManager脚本的alienPrefab槽位上。当一个物体在服务器上被创建之后,同样的物体将被创建在客户端上。这种资源的注册保证资源和场景一起加载,因此创建时没有资源加载的延迟。关于对象池和动态创建资源的情况,可以使用ClientScene.RegisterSpawnHandler()函数,它可以用来注册客户端派生一个物体的回调函数。

下面是一个创建拥有随机生成的树叶的树的例子:

class Tree :NetworkBehaviour
{
[SyncVar]
public int numLeaves;
}

class MySpawner :NetworkBehaviour
{
public GameObject treePrefab;

public void Spawn()
{
GameObject tree =(GameObject)Instantiate(treePrefab, transform.position, transform.rotation);
tree.GetComponent<Tree>().numLeaves= Random.Range(10,200);
NetworkServer.Spawn(tree);
}
}
要完成上面的功能,工程中需要有一棵树的预设体,并有叫做Tree的脚本和NetworkIdentity组件。然后在场景的MySpawner脚本中,把这个树的预设体拖放到脚本的treePrefab槽位上。这个树的预设体还必须注册为可派生的物体,可以通过NetworkManager的UI界面,也可以在代码中使用ClientScene.RegisterPrefab()函数。

当代码运行时,在客户端上派生出来的树会具有和服务器上的树相同的叶子数量

约束条件

- 在派生的预设体物体上,在根节点上必须要有一个NetworkIdentity组件;

- 一个NetworkBehaviour脚本必须像NetworkIdentity一样绑定在物体的根节点上;

- 预设体如果没有NetworkIdentity组件,将不能被绑定在NetworkManager上;

物体创建流程:

派生物体的实际流程为:

- 注册一个包含NetworkIdentity组件的预设体

- 在服务器上创建出该物体

- 调用游戏代码为物体设置初始值(三维物体上的物理力不会马上生效)

- 调用NetworkServer.Spawn()方法

- 服务器上这个物体的NetworkBehaviour组件里的所有同步变量(SyncVars)的值被收集并序列化

- 包含同步变量数据的MsgType.ObjectSpawn类型的网络消息被发送给所有的客户端

- 服务上调用OnStartServer()函数,并把isServer设置为true

- 客户端接收ObjectSpawn消息,并从注册的预设体中创建游戏物体

- 在创建的物体上应用接收到的同步变量值

- 每个客户端执行OnStartClient() 函数 ,isClient变量设置为True

- 在 游戏 进行过程中,同步变量的值的修改都会被自动同步到所有的客户端,直到游戏结束

- 服务器上调用NetworkServer.Destroy()

- 给所有的客户端发送MsgType.ObjectDestroy类型的消息

- 所有的客户端执行OnNetworkDestroy方法,实例被销毁

玩家物体:

玩家 物体在网络HLAPI中有点特殊,NetworkManager对玩家物体的处理流程是:

- 将包含NetworkIdentity组件的预设体注册为派生预设体

- 客户端连接到服务器

- 客户端调用AddPlayer(), 发送MsgType.AddPlayer类型的消息给服务器

- 服务器接收到消息,调用NetworkManager.AddPlayer()

- 服务器从预设体中创建物体

- 服务器上为新创建的玩家物体调用NetworkManager.AddPlayerForConnection()

- 玩家物体被创建出来(你不需要再调用NetworkManager.Spawn())

- 一个MsgType.Owner类型的消息发送给客户端(只发送给这个连接进来的客户端)

- 客户端接收到消息

- 客户端上调用OnStartLocalPlayer,并且将isLocalPlayer设置为True

要注意的是,OnStartLocalPlayer()会在OnStartClient()之后被调用,这发生在玩家物体被创建,并接收到Owner消息的时候。所以在OnStartClient 函数 中,isLocalPlayer属性还没有被设置。 

因为OnStartLocalPlayer()只在 玩家 自己的客户端上执行,因此这里是对本地玩家执行初始化的好地方。这应该包括开启输入控制,启动 摄像机 跟随等功能。一般情况下,只有本地玩家拥有活动的摄像机。

定制派生函数

在客户端上派生 游戏 物体的默认行为可以使用派生处理函数进行定制。你可以在客户端上使用ClientScene.RegisterSpawnHandler()函数注册Spawn和un-Spawn回调函数。这个函数接收两个函数代理类型的变量,一个用来处理物体创建,另一个处理物体的销毁。

// 客户端上的物体创建处理函数
public delegateGameObject SpawnDelegate(Vector3 position, NetworkHash128 assetId);

// 客户端上的物体销毁处理函数
public delegate voidUnSpawnDelegate(GameObject spawned);
物体创建 函数 中的assetId可以在预设体的NetworkIdentity.assetId属性中找到,他是自动设置的。你可以使用下面的代码进行创建:

// 创建一个唯一的assetId
NetworkHash128creatureAssetId =  new  NetworkHash.Parse("e2656f");

// 注册这个assetId的处理函数
ClientScene.RegisterSpawnHandler(creatureAssetId,SpawnCreature, UnSpawnCreature);

// 派生一个物体,SpawnCreature()将在客户端上被调用
NetworkServer.Spawn( game Object,creatureAssetId);
使用定制的派生函数的时候,有时候unspawn一个物体但是不销毁他们是有用的。这可以通过调用NetworkServer.UnSpawnObject()来实现。这将引发一个消息被发送给un-spawn的物体,在客户端上定制的unspawn函数将被调用。这个函数被调用后不会销毁这个物体。

注意的是,在 伺服器 上,物体不会再本地客户端上被创建出来,因为这个物体在服务器上已经有了,所以派生处理 函数 不会被调用。

创建客户端授权的物体

可以派生一个物体并把这个物体授权给某个客户端。这可以通过NetworkServer.SpawnWithClientAuthority()来完成。它接收与目标客户端关联的NetworkConnection变量作为参数。

对于这些物体,hasAuthority属性在被授权的客户端上将为True,而且OnStartAuthority()将会在被授权的客户端上被调用。这个客户端就可以发起控制这个物体的命令。在其他的客户端上,hasAuthority属性将为False。 

拥有客户端授权的派生物体必须在NetworkIdentity上设置LocalPlayerAuthority属性

例如,要允许 玩家 派生并控制一个物体:

[Command]
void CmdSpawn()
{
var go = (GameObject)Instantiate(
otherPrefab, 

transform.position + new  Vector3(0,1,0),
Quaternion.identity);
NetworkServer.SpawnWithClientAuthority(go, connectionToClient);
}

这篇关于Unity多人游戏和网络功能(三) 游戏物体的派生的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/912003

相关文章

Go语言实现将中文转化为拼音功能

《Go语言实现将中文转化为拼音功能》这篇文章主要为大家详细介绍了Go语言中如何实现将中文转化为拼音功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 有这么一个需求:新用户入职 创建一系列账号比较麻烦,打算通过接口传入姓名进行初始化。想把姓名转化成拼音。因为有些账号即需要中文也需要英

基于WinForm+Halcon实现图像缩放与交互功能

《基于WinForm+Halcon实现图像缩放与交互功能》本文主要讲述在WinForm中结合Halcon实现图像缩放、平移及实时显示灰度值等交互功能,包括初始化窗口的不同方式,以及通过特定事件添加相应... 目录前言初始化窗口添加图像缩放功能添加图像平移功能添加实时显示灰度值功能示例代码总结最后前言本文将

使用Python实现批量访问URL并解析XML响应功能

《使用Python实现批量访问URL并解析XML响应功能》在现代Web开发和数据抓取中,批量访问URL并解析响应内容是一个常见的需求,本文将详细介绍如何使用Python实现批量访问URL并解析XML响... 目录引言1. 背景与需求2. 工具方法实现2.1 单URL访问与解析代码实现代码说明2.2 示例调用

SSID究竟是什么? WiFi网络名称及工作方式解析

《SSID究竟是什么?WiFi网络名称及工作方式解析》SID可以看作是无线网络的名称,类似于有线网络中的网络名称或者路由器的名称,在无线网络中,设备通过SSID来识别和连接到特定的无线网络... 当提到 Wi-Fi 网络时,就避不开「SSID」这个术语。简单来说,SSID 就是 Wi-Fi 网络的名称。比如

Java实现任务管理器性能网络监控数据的方法详解

《Java实现任务管理器性能网络监控数据的方法详解》在现代操作系统中,任务管理器是一个非常重要的工具,用于监控和管理计算机的运行状态,包括CPU使用率、内存占用等,对于开发者和系统管理员来说,了解这些... 目录引言一、背景知识二、准备工作1. Maven依赖2. Gradle依赖三、代码实现四、代码详解五

最好用的WPF加载动画功能

《最好用的WPF加载动画功能》当开发应用程序时,提供良好的用户体验(UX)是至关重要的,加载动画作为一种有效的沟通工具,它不仅能告知用户系统正在工作,还能够通过视觉上的吸引力来增强整体用户体验,本文给... 目录前言需求分析高级用法综合案例总结最后前言当开发应用程序时,提供良好的用户体验(UX)是至关重要

python实现自动登录12306自动抢票功能

《python实现自动登录12306自动抢票功能》随着互联网技术的发展,越来越多的人选择通过网络平台购票,特别是在中国,12306作为官方火车票预订平台,承担了巨大的访问量,对于热门线路或者节假日出行... 目录一、遇到的问题?二、改进三、进阶–展望总结一、遇到的问题?1.url-正确的表头:就是首先ur

使用C#如何创建人名或其他物体随机分组

《使用C#如何创建人名或其他物体随机分组》文章描述了一个随机分配人员到多个团队的代码示例,包括将人员列表随机化并根据组数分配到不同组,最后按组号排序显示结果... 目录C#创建人名或其他物体随机分组此示例使用以下代码将人员分配到组代码首先将lstPeople ListBox总结C#创建人名或其他物体随机分组

如何评价Ubuntu 24.04 LTS? Ubuntu 24.04 LTS新功能亮点和重要变化

《如何评价Ubuntu24.04LTS?Ubuntu24.04LTS新功能亮点和重要变化》Ubuntu24.04LTS即将发布,带来一系列提升用户体验的显著功能,本文深入探讨了该版本的亮... Ubuntu 24.04 LTS,代号 Noble NumBAT,正式发布下载!如果你在使用 Ubuntu 23.

TP-LINK/水星和hasivo交换机怎么选? 三款网管交换机系统功能对比

《TP-LINK/水星和hasivo交换机怎么选?三款网管交换机系统功能对比》今天选了三款都是”8+1″的2.5G网管交换机,分别是TP-LINK水星和hasivo交换机,该怎么选呢?这些交换机功... TP-LINK、水星和hasivo这三台交换机都是”8+1″的2.5G网管交换机,我手里的China编程has