【Unity Photon Fusion 2】多人联网插件,共享模式基础教程

这篇具有很好参考价值的文章主要介绍了【Unity Photon Fusion 2】多人联网插件,共享模式基础教程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、插件导入与配置准备

见主机模式基础教程

【Unity Photon Fusion 2】多人联网插件,主机模式基础教程-CSDN博客

2、共享模式基础使用

2.1 场景创建与玩家化身创建

概述
该部分解释了如何设置一个简单的场景以及如何创建一个玩家预制件。在本节结束时,您将拥有一个工作的网络场景,为每个连接的客户端生成一个播放器对象。

2.1.1 设置场景

从一个空的Unity场景开始。右键单击Unity中的Hierarchy选项卡,选择Fusion> Scene > Setup Networking in Scene
fusion联网network transform,unity知识学习分享,unity,游戏引擎

 这将在场景中添加一个Prototype Runner物体和一个Prototype Network Start物体。

fusion联网network transform,unity知识学习分享,unity,游戏引擎

  •  Prototype Runner包含Network Runner,它是运行Fusion模拟的核心组件。Network Events脚本允许您快速将自己的功能链接到各种网络事件,例如玩家加入或离开会话。
  • Prototype Network Start是一个原型组件,它包含一个用于快速加入Fusion房间的引导GUl。

接下来,在场景中添加一个地板,右键单击Unity中的Hierarchy选项卡,选择3D Object> Plane。将GameObject重命名为Floor并将其位置重置为(0, 0, 0)。

fusion联网network transform,unity知识学习分享,unity,游戏引擎

2.1.2 创建玩家预制件

        接下来创建播放器对象。右键单击层次结构,选择3d Object > 胶囊。将Gameobject重命名为PlayerCharacter。
        向其中添加一个Networkobject组件。该组件为对象提供网络标识,以便所有对等体都可以引用它。
        添加CharacterController组件。之后移动代码将使用这一点来移动玩家角色。
        最后,向其中添加一个NetworkTransform组件。NetworkTransform自动将对象的位置同步到其他客户端。
        将PlayerCharacter拖拽到Project窗口中创建预制件并将其从场景中删除。这样玩家角色就可以被生成了。

 fusion联网network transform,unity知识学习分享,unity,游戏引擎

2.1.3 生成玩家 

与单人游戏不同的是,场景中只有一个玩家对象是不够的。对于多人游戏,需要为每个加入会话的玩家生成一个玩家对象。为此,需要一个自定义脚本。创建一个PlayerSpawner脚本并打开它。将以下代码添加到其中:
 

using Fusion;
using UnityEngine;

public class PlayerSpawner : SimulationBehaviour, IPlayerJoined
{
    public GameObject PlayerPrefab;

    public void PlayerJoined(PlayerRef player)
    {
        if (player == Runner.LocalPlayer)
        {
            Runner.Spawn(PlayerPrefab, new Vector3(0, 1, 0), Quaternion.identity);
        }
    }
}

代码非常简单。IPlayerJoined接口有一个PlayerJoined函数,每当玩家加入会话时,如果行为与runner在相同的GameObject上,该函数就会被调用。这不仅适用于我们自己的玩家,也适用于从不同设备加入的其他玩家。它只需要为我们自己的播放器生成一个播放器对象。当一个对象用Runner.Spawn()时。它会自动复制到所有其他客户端。

SimulationBehaviour用于访问NetworkRunner,其中包含有关当前会话的所有信息,包括本地玩家的玩家ID。

将PlayerSpawner组件添加到Prototype Runner 对象中,并将PlayerCharacter预制件分配给它。
这样,玩家生成就完全设置好了。进入播放模式,按“Start Shared Client”启动共享模式的Fusion。

fusion联网network transform,unity知识学习分享,unity,游戏引擎
 玩家胶囊将出现在场景中。玩家还不能移动或与任何东西互动。在下一章中,我们将通过执行玩家移动来赋予玩家生命。

fusion联网network transform,unity知识学习分享,unity,游戏引擎

2.2 移动控制与相机控制

概述
在第该部分中,通过添加基于玩家输入和第一人称的玩家移动来扩展现有场景相机跟随正确的玩家对象。

2.2.1 玩家移动控制

在Fusion中,更新每一次tick(如移动)的游戏玩法代码不应该在Update / FixedUpdate中运行,而应该使用FixedUpdateNetwork。这确保了运动是平滑的,并在所有客户端上正确地插入。
创建一个新脚本,命名为PlayerMovement,并将以下代码添加到脚本中:

using Fusion;
using UnityEngine;

public class PlayerMovement : NetworkBehaviour
{
    private CharacterController _controller;

    public float PlayerSpeed = 2f;

    private void Awake()
    {
        _controller = GetComponent<CharacterController>();
    }

    public override void FixedUpdateNetwork()
    {
        // Only move own player and not every other player. Each player controls its own player object.
        if (HasStateAuthority == false)
        {
            return;
        }

        Vector3 move = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")) * Runner.DeltaTime * PlayerSpeed;

        _controller.Move(move);

        if (move != Vector3.zero)
        {
            gameObject.transform.forward = move;
        }
    }
}

 请注意,它继承自NetworkBehaviour而不是MonoBehaviour,后者提供FixedUpdateNetwork,并允许稍后使用Networked Properties。
HasStateAuthority可以用来检查客户端是否控制一个对象。NetworkTransform只将来自StateAuthority的更改同步到其他所有人。如果另一个客户端更改了对象的位置,则该更改将仅是局部更改,并且将来会被来自网络的数据覆盖。

总是使用Runner。在FixedUpdateNetwork中运行的代码的DeltaTime !

处理按钮按下
像GetButtonDown和Up这样的一次性输入会在Unity的Update中被触发。在Fusion中,移动等玩法代码应该在FixedUpdateNetwork中执行。这意味着需要特殊的处理来准确地跟踪按钮状态。

请注意,在FixedUpdateNetwork中检查按钮按下时也会出现相同的问题。

有多种方法可以捕获像FixedUpdateNetwork这样的输入:
1)、查询更新中的按钮按钮。将结果存储在bool中,并将其用于游戏逻辑。最后把它清理干净
固定更新网络
2)、使用Fusion的Networklnput和NetworkButtons。
3)、使用新的Unity输入系统,将Update Mode设置为Manual Update并在FixedUpdateNetwork调用IInputSystem.Update

以上选项仅适用于共享模式。在服务器/主机模式下运行Fusion时,总是使用Networklnput。 

2.2.2 玩家跳跃控制

让我们实现一个通过为玩家执行跳跃动作来处理按钮按压的例子。在本例中,使用上一节列出的选项中的选项1。
将PlayerMovement脚本中的代码替换为以下代码:
 

using Fusion;
using UnityEngine;

public class PlayerMovement : NetworkBehaviour
{
    private Vector3 _velocity;
    private bool _jumpPressed;

    private CharacterController _controller;

    public float PlayerSpeed = 2f;

    public float JumpForce = 5f;
    public float GravityValue = -9.81f;

    private void Awake()
    {
        _controller = GetComponent<CharacterController>();
    }

    void Update()
    {
        if (Input.GetButtonDown("Jump"))
        {
            _jumpPressed = true;
        }
    }

    public override void FixedUpdateNetwork()
    {
        // Only move own player and not every other player. Each player controls its own player object.
        if (HasStateAuthority == false)
        {
            return;
        }

        if (_controller.isGrounded)
        {
            _velocity = new Vector3(0, -1, 0);
        }

        Vector3 move = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")) * Runner.DeltaTime * PlayerSpeed;

        _velocity.y += GravityValue * Runner.DeltaTime;
        if (_jumpPressed && _controller.isGrounded)
        {
            _velocity.y += JumpForce;
        }
        _controller.Move(move + _velocity * Runner.DeltaTime);

        if (move != Vector3.zero)
        {
            gameObject.transform.forward = move;
        }

        _jumpPressed = false;
    }
}

这段代码向KCC添加了跳跃函数和速度/重力处理。
_jumpPressed用于跟踪按钮状态。该按钮在每次更新时进行轮询,以确保没有漏按,并在FixedUpdateNetwork结束时重置。

if (_controller.isGrounded)
{
    _velocity = new Vector3(0, -1, 0);
}

 是用来确保KCC保持固定在地面上,即使走在小斜坡上,只有跳跃允许玩家离开地面。

2.2.3 游戏测试

准备好PlayerMovement脚本后,返回Unity并将PlayerMovement组件添加到PlayerCharacter预制中。
现在是测试玩家移动的时候了。要有两个客户端可用,首先创建一个Unity构建。
进入File> Build Settings,将当前场景添加到列表中。然后按下窗口左下方的播放器设置按钮。
在播放器设置中的分辨率和呈现设置全屏模式为窗口,并确保在后台运行被选中。

fusion联网network transform,unity知识学习分享,unity,游戏引擎

返回到 Build Settings 窗口并选择 Build and Run 以创建生成。一旦构建完成,在Unity中进入播放模式,以便两个客户端可用。
在两个客户端上按 Start Shared Client 按钮。出现两个玩家,每个玩家由一个客户控制。测试走动和跳跃是否有效。

fusion联网network transform,unity知识学习分享,unity,游戏引擎
 

2.2.4 相机控制

为了完成播放器设置,让我们添加一个摄像机。
设置摄像头的方法有很多种(第三人称、第一人称等),执行方法也各不相同。在多人游戏中,通常需要单个摄像机跟随本地玩家对象。有两种常见的方法可以做到这一点。
1)、当本地播放器对象被生成时,让它实例化一个摄像机。
2)、让摄像机成为场景的一部分。当本地播放器对象生成时,让它将相机附加到自身上。
在本教程中使用第二种方法。
创建一个新脚本并命名为FirstPersonCamera。在其中添加以下代码
 

using UnityEngine;

public class FirstPersonCamera : MonoBehaviour
{
    public Transform Target;
    public float MouseSensitivity = 10f;

    private float verticalRotation;
    private float horizontalRotation;

    void LateUpdate()
    {
        if (Target == null)
        {
            return;
        }

        transform.position = Target.position;

        float mouseX = Input.GetAxis("Mouse X");
        float mouseY = Input.GetAxis("Mouse Y");

        verticalRotation -= mouseY * MouseSensitivity;
        verticalRotation = Mathf.Clamp(verticalRotation, -70f, 70f);

        horizontalRotation += mouseX * MouseSensitivity;

        transform.rotation = Quaternion.Euler(verticalRotation, horizontalRotation, 0);
    }
}

这是一个非常简单的第一人称摄像机实现。注意,代码不包含任何多人游戏元素。您可以将此相机替换为与目标对象(包括Cinemachine)一起工作的任何其他相机设置。
将FirstPersonCamera行为放在场景中的MainCamera GameObject上。没有必要拖拽一个目标。目标将在运行时由代码设置。
fusion联网network transform,unity知识学习分享,unity,游戏引擎

要分配目标,打开PlayerMovement脚本。添加一个变量来存储摄像机:

public Camera Camera;

 然后,当玩家对象生成时,如果它是本地玩家,则查找并设置相机。

public override void Spawned()
{
    if (HasStateAuthority)
    {
        Camera = Camera.main;
        Camera.GetComponent<FirstPersonCamera>().Target = transform;
    }
}

 在初始化Networkobjects时,请确保始终使用spawn而不是Awake/Start。在Awake/Start中,NetworkObject可能还没有准备好使用。

HasStateAuthority只对播放器控制的对象为真,所以只对本地播放器对象有效,对其他播放器对象无效。 

最后,因为在第一人称游戏中,玩家角色会朝着视觉方向移动,所以需要调整一下移动方向。将计算Vector3移动的行替换为:

Quaternion cameraRotationY = Quaternion.Euler(0, Camera.transform.rotation.eulerAngles.y, 0);
Vector3 move = cameraRotationY * new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")) * Runner.DeltaTime * PlayerSpeed;

2.3 Network Properties 网络属性 

 概述
本节展示了如何通过网络同步其他数据,除了玩家的位置使用网络属性

2.3.1 网络属性

        当您向networkobject添加NetworkTransform组件时,Fusion会同步它们的转换。其他状态,如脚本中的变量,不通过网络同步。要使状态在网络上同步,需要一个[Networked]属性。网络属性将其状态从StateAuthority同步到所有其他客户端。

        如果客户端在一个对象上更改了一个它没有StateAuthority的Networked Property,那么这个更改不会在网络上同步,而是作为一个本地预测应用,并且可以在将来被StateAuthority的更改覆盖。如果您希望在每个客户机上更新StateAuthority上的Networked Properties,请注意只更新它。

        网络属性的一个简单例子就是玩家的颜色。首先创建一个新脚本并命名为PlayerColor。添加一个Networked属性和一个公共字段来引用对象的MeshRender

using Fusion;
using UnityEngine;

public class PlayerColor : NetworkBehaviour
{
    public MeshRenderer MeshRenderer;

    [Networked]
    public Color NetworkedColor { get; set; }
}

注意,网络属性必须是属性({ get;set; }),不支持常规字段。
接下来在更新中添加代码,允许StateAuthority改变颜色:

void Update()
{
    if (HasStateAuthority && Input.GetKeyDown(KeyCode.E))
    {
        // Changing the material color here directly does not work since this code is only executed on the client pressing the button and not on every client.
        NetworkedColor = new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f), 1f);
    }
}

当按钮被按下时,网格渲染的颜色不会立即改变。相反,网络属性被更新。这样,颜色的变化将被复制到所有客户端。剩下的是每个客户端检查网络属性的变化,并相应地调整网格颜色。
在Fusion中,这是通过ChangeDetection完成的。在共享模式下做到这一点的最简单方法是使用OnChangedRender属性。首先添加一个函数,当NetworkedColor改变时执行。

void OnColorChanged()
{
    MeshRenderer.material.color = NetworkedColor;
}

然后用OnChangedRender属性调整Networked属性:

[Networked, OnChangedRender(nameof(OnColorChanged))]
public Color NetworkedColor { get; set; }

这个属性在每次渲染帧(Unity Update)中检测到属性变化时调用OnColorChanged函数。
将PlayerColor组件添加到PlayerCharacter预制件中,并在播放器上链接MeshRender。进入播放模式并按 E 键,你可以在编辑视图中检查玩家正在改变颜色。此时,您还可以创建一个构建来验证颜色是否通过网络正确同步。
fusion联网network transform,unity知识学习分享,unity,游戏引擎
 

2.4 RPCs 

概述
在最后一个部分,一个网络属性被添加到同步玩家的颜色到所有其他玩家。由于玩家对自己的网络属性拥有StateAuthority,他们可以直接更新自己的颜色值。
然而,这并不适用于网络对象的网络属性,其中StateAuthority是另一个客户端。
这部分包含了一个攻击玩家并在需要修改另一个玩家的网络属性时减少其生命值的例子。
 

2.4.1 修改其他玩家的网络属性

更改另一个客户端拥有状态权限的网络属性的方法是向对象的状态权限发送RPC(远程过程调用),并让它们更改网络属性
虽然可以通过代码更改网络财产的值。更改将仅在本地应用,而不会在网络上复制。
这方面的一个例子便是使用光线投射武器射击玩家。对于Fusion共享模式,一个简单的实现是让玩家在本地执行光线投射,如果它击中目标,则对目标施加伤害。注意,在服务器/主机模式下光线投射武器的方法是不同的。查看
Fusion Projectiles样本中的服务器/主机模式示例。
创建一个新脚本,并将其命名为Health。添加网络属性和更改检测功能,以记录运行状况值的更改:

using Fusion;
using UnityEngine;

public class Health : NetworkBehaviour
{
    [Networked, OnChangedRender(nameof(HealthChanged))]
    public float NetworkedHealth { get; set; } = 100;

    void HealthChanged()
    {
        Debug.Log($"Health changed to: {NetworkedHealth}");
    }
}

接下来添加一个RPC,射击者可以调用它对敌方玩家造成伤害:

[Rpc(RpcSources.All, RpcTargets.StateAuthority)]
public void DealDamageRpc(float damage)
{
    // The code inside here will run on the client which owns this object (has state and input authority).
    Debug.Log("Received DealDamageRpc on StateAuthority, modifying Networked variable");
    NetworkedHealth -= damage;
}

RpcSources.All 这些都允许任何人调用RPC。默认情况下,只有InputAuthority(与共享模式下的StateAuthority相同)可以调用RPC。
RpcTargets.StateAuthority设置只有StateAuthority接收RPC。这样做是因为州政府会更新健康网络财产。RPC函数内部的代码运行在RpcTarget客户端上,因此在本例中运行在可以更改其自己的Networked Properties的StateAuthority上。

接下来创建一个新脚本并命名为itRaycastAttack。将以下代码添加到其中

using Fusion;
using UnityEngine;

public class RaycastAttack : NetworkBehaviour
{
    public float Damage = 10;

    public PlayerMovement PlayerMovement;

    void Update()
    {
        if (HasStateAuthority == false)
        {
            return;
        }

        Ray ray = PlayerMovement.Camera.ScreenPointToRay(Input.mousePosition);
        ray.origin += PlayerMovement.Camera.transform.forward;

        if (Input.GetKeyDown(KeyCode.Mouse1))
        {
            Debug.DrawRay(ray.origin, ray.direction, Color.red, 1f);
        }
    }
}

这段代码是一个简单的单人游戏光线投射实现。HasStateAuthority检查只用于在StateAuthority上执行这段代码,这样当玩家按下fire按钮时,只有他们自己的玩家角色触发光线投射。
现在要对目标施加伤害,剩下的就是对其调用RPC函数。在调试之后。绘制线添加以下内容:

if (Runner.GetPhysicsScene().Raycast(ray.origin,ray.direction, out var hit))
{
    if (hit.transform.TryGetComponent<Health>(out var health))
    {
        health.DealDamageRpc(Damage);
    }
}

 完成后,将Health和RaycastAttack组件添加到玩家预制件中并创建一个构建。

2.4.2 其他RPC用例

请求State Authority修改网络属性是RPC最常见的用例。
RPC的其他有效用例包括:
1.在玩家之间发送嘲讽信息、表情或其他不稳定的非游戏互动。
⒉启动游戏(对游戏模式、地图进行投票,或者只是向主持人表明玩家已经准备好了)。
在大多数情况下,状态同步本身足以让玩家保持一致,向网络属性添加变化检测器可以处理大多数过渡情况,其中应用程序关心状态的变化,而不仅仅是实际状态本身。

2.4.3 游戏测试

恭喜你!你已经成功完成了Fusion共享模式基础教程。为了确保一切正常运行,现在是时候玩和测试游戏了。
在Unity中启动构建并进入播放模式,然后按Start Shared Client。右键点击其他玩家将在控制台上显示其生命值减少的信息。
您还可以在Unity的层次检查器中检查网络属性的健康值。
 文章来源地址https://www.toymoban.com/news/detail-859586.html

到了这里,关于【Unity Photon Fusion 2】多人联网插件,共享模式基础教程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity之Photon PUN2开发多人游戏如何实现组队功能

    Photon Unity Networking 2 (PUN2) 是一款基于Photon Cloud的Unity多人游戏开发框架。它提供了一系列易于使用的API和工具,使开发者可以快速构建多人戏,并轻松处理多人游戏中的网络同步、房间管理、玩家匹配等问题。 我们在查看Pun2的Demo时,会发现Demo中自带了一个简易的PhotonTeam和

    2024年02月11日
    浏览(13)
  • 【Unity工具,简单应用】Photon + PUN 2,做一个简单多人在线聊天室

    【Unity工具,简单学习】PUN 2,多人在线游戏开发,初步使用 需要有一定 UNITY 使用经验的开发者可以顺利阅读。 简单搭建一下大厅UI。 给 Laucher 节点一个 Launcher 脚本 Launcher 脚本如下,具体功能看注释 需要注意的是 PhotonNetwork.JoinOrCreateRoom(RoomName, new RoomOptions() { MaxPlayers = ma

    2024年02月08日
    浏览(14)
  • Unity之使用Photon Server + PUN2 开发局域网多人游戏

    Photon Engine是一款跨平台的实时多人游戏引擎,它提供了可靠的基础设施和工具,使开发者能够轻松地构建和部署多人游戏。Photon Engine支持多种平台,包括PC、移动设备和Web,同时还提供了多种语言的SDK,如C++、C#、Java、JavaScript等,使得开发者可以使用自己熟悉的编程语言进

    2024年02月13日
    浏览(14)
  • unity多人联机(Mirror插件)有史以来最全的基础教程(附加报错提示和官方手册修改)

    目录 START👀 (☞゚ヮ゚)☞Mirror简介☜(゚ヮ゚☜) 组件介绍: 组件1:NetworkManager 组件2:NetworkManagerHUD(需要配合Network Manager组件) 组件3:NetworkIdentity 组件4:network discoverynetwork discoveryHUD 错误注意: 最后,对手册内容的一点修改: 今天我们只讲代码和组件,大家拿小本本记好了,字

    2024年02月02日
    浏览(15)
  • Unity联网多人游戏技术方案调研

    Listen Server (Host) 和 Relay转发服务器游戏包同时包含客户端和服务端逻辑,联网时一个客户端开主,称为Host,其他客户端连入。局域网和互联网都支持。互联网需要有一个匹配服务器帮助找到不同人建立的主机。如果不使用Relay服务器,那对于互联网连接就要使用NAT穿透下的

    2023年04月09日
    浏览(48)
  • VR多人协同(Photon Server & Pun2 & VRIF)

    内容介绍: 采用Photon Server作为本地服务器,然后使用Pun2连接本地服务进行VR多人交互 Photon Server部署 1、下载并解压: photon-server-sdk_v5-0-12-24499-rc1.zip 2、授权(因官方授权问题可以转用V4.0Server:VR多人协同(多人游戏本地服务器)(Photon Server V4.0)) 获取地址: 点击领取你的

    2024年02月16日
    浏览(10)
  • IT互联网行业资源共享云计算模式及创新技术

    作者:禅与计算机程序设计艺术 在IT行业中,作为基础设施提供者的公司往往需要承担高昂的运营成本、大量的维护工作、复杂的管理系统等等。相对于传统的自建机房,公有云服务或托管服务等更加经济和便捷。利用云端资源可以节省企业内部服务器资源投入,提升业务运

    2024年02月08日
    浏览(17)
  • Unity_Photon

    (2条消息) 【Unity3D】Photon环境搭建_photon框架_little_fat_sheep的博客-CSDN博客 主要代码 : PhotonNetwork.ConnectUsingSettings(); 链接成功。 状态:ClientState.ConnectedToMasterServer 创建房间 : PhotonNetwork.CreateRoom(roomName); 连接成功后。 创建成功后。 回调用于检测前序操作是否成功。 PhotonCallBa

    2024年02月08日
    浏览(11)
  • Unity原生语音识别/无插件/可离线/不需要联网 语音识别

    直接上代码,保证自己的设备连接了麦克风,之后把下面代码直接挂在场景的空物体上,运行即可

    2024年02月03日
    浏览(16)
  • Microsoft.OneNote多人共享:详细步骤,存在的问题与解决方式

    OneNote是微软出品的笔记本软件,可以跨平台使用并支持多人协作,对于需要长久合作的小规模队伍来说,是一款很好的协同工作软件。由于在国内,OneNote内的协作设置很可能存在问题,这里提供一种解决方法。 1. 传统OneNote共享方式: 1) “成员A(共享发起者)”在笔记本

    2024年02月04日
    浏览(10)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包