【Unity工具,简单应用】Photon + PUN 2,做一个简单多人在线聊天室

这篇具有很好参考价值的文章主要介绍了【Unity工具,简单应用】Photon + PUN 2,做一个简单多人在线聊天室。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前置知识,安装,及简单UI

  • 【Unity工具,简单学习】PUN 2,多人在线游戏开发,初步使用
  • 需要有一定 UNITY 使用经验的开发者可以顺利阅读。

大厅

  • 简单搭建一下大厅UI。
    Laucher 节点一个 Launcher 脚本
    【Unity工具,简单应用】Photon + PUN 2,做一个简单多人在线聊天室
  • Launcher 脚本如下,具体功能看注释
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Photon.Pun;
using Photon.Realtime;

public class Launcher : MonoBehaviourPunCallbacks
{
    public string RoomName = "Room";		// 设置房间名,确保每次连接到同一个房间
    private string gameVersion = "1";

    [SerializeField]
    private const byte maxPlayersPerRoom = 4;	// 设置单房间最多玩家数
    [SerializeField]
    private GameObject controlPanel;
    [SerializeField]
    private GameObject progressLabel;

    void Awake()
    {
        // Then let master server can use PhotonNetwork.LoadLevel()
        // Everyone will see the same level
        PhotonNetwork.AutomaticallySyncScene = true;	// 确保该变量为 true,否则无法同步

        progressLabel.SetActive(false);
        controlPanel.SetActive(true);
    }
    public void Connect()
    {
        progressLabel.SetActive(true);
        controlPanel.SetActive(false);
        if (PhotonNetwork.IsConnected)			// 若已连接,则直接加入到房间
        {
            PhotonNetwork.JoinOrCreateRoom(RoomName, new RoomOptions() { MaxPlayers = maxPlayersPerRoom }, default);
        }
        else
        {
            PhotonNetwork.ConnectUsingSettings();		// 用 PhotonServerSettings 来连接
            PhotonNetwork.GameVersion = gameVersion;
        }
    }
    public override void OnJoinRandomFailed(short returnCode, string message)	// 若加入随机房间失败
    {
        Debug.Log("PUN Basics Tutorial/Launcher:OnJoinRandomFailed() was called by PUN. No random room available, so we create one.\nCalling: PhotonNetwork.CreateRoom");

        // #Critical: we failed to join a random room, maybe none exists or they are all full. No worries, we create a new room.
        PhotonNetwork.CreateRoom(RoomName, new RoomOptions() { MaxPlayers = maxPlayersPerRoom });
    }

    public override void OnJoinedRoom()		// 若加入了某房间,则加载聊天室场景,不要使用 UNITY的加载场景方法
    {
        Debug.Log("PUN Basics Tutorial/Launcher: OnJoinedRoom() called by PUN. Now this client is in a room.");

        PhotonNetwork.LoadLevel("ChatingRoom");
    }
    public override void OnConnectedToMaster()	// 运行ConnectUsingSettings()后会先连接到 Master节点,再创建或加载房间
    {
        Debug.Log("PUN Basics Tutorial/Launcher: OnConnectedToMaster() was called by PUN");
        PhotonNetwork.JoinOrCreateRoom(RoomName, new RoomOptions() { MaxPlayers = maxPlayersPerRoom }, default);
    }
    public override void OnDisconnected(DisconnectCause cause)	// 若失去连接后
    {
        progressLabel.SetActive(false);
        controlPanel.SetActive(true);
        Debug.LogWarningFormat("PUN Basics Tutorial/Launcher: OnDisconnected() was called by PUN with reason {0}", cause);
    }

}
  • 需要注意的是 PhotonNetwork.JoinOrCreateRoom(RoomName, new RoomOptions() { MaxPlayers = maxPlayersPerRoom }, default); 方法,若该房间名的房间不存在则创建,否则加载该房间。
  • 在输入框中,把该字符串赋值给 PhotonNetwork.NickName 即表示该玩家的名称,需非空
    PhotonNetwork.NickName = defaultName;

聊天室

  • 聊天室的UI如下
    添加一个 GameManagerPUN 的物体并给予它对应的脚本组件
    【Unity工具,简单应用】Photon + PUN 2,做一个简单多人在线聊天室
  • GameManagerPUN 脚本如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Photon.Pun;
using Photon.Realtime;
public class GameManagerPUN : MonoBehaviourPunCallbacks
{
    public string DialogueText = "DialogueText";
    [SerializeField]
    private InputField _inputField;
    public GameObject Content;


    void Start()
    {
        GameObject go = PhotonNetwork.Instantiate("Sphere", Vector3.zero, Quaternion.identity);
        go.GetComponent<ChangeRandomPosition>().change();	// 用 PhotonNetwork.Instantiate 创建一个物体,让它的位置随机变一下,代表显示该房间内的玩家个数
    }

    public override void OnLeftRoom()
    {
        SceneManager.LoadScene("LobbyScene");
    }
    public void LeaveRoom()	// 退出按钮的监听器直接调用该代码即可调用 OnLeftRoom() 方法,退出大厅
    {
        PhotonNetwork.LeaveRoom();
    }

    public override void OnPlayerEnteredRoom(Player other)	// 自动监听是否有玩家进入
    {
        Debug.LogFormat("OnPlayerEnteredRoom() {0}", other.NickName); // not seen if you're the player connecting

        if (PhotonNetwork.IsMasterClient)
        {
            Debug.LogFormat("OnPlayerEnteredRoom IsMasterClient {0}", PhotonNetwork.IsMasterClient); // called before OnPlayerLeftRoom
        }
    }

    public override void OnPlayerLeftRoom(Player other)	// 自动监听是否有玩家退出
    {
        Debug.LogFormat("OnPlayerLeftRoom() {0}", other.NickName); // seen when other disconnects

        if (PhotonNetwork.IsMasterClient)
        {
            Debug.LogFormat("OnPlayerLeftRoom IsMasterClient {0}", PhotonNetwork.IsMasterClient); // called before OnPlayerLeftRoom
        }
    }

    public void SendMessage()	// 发送消息,记录发送消息者名称,与它发送的消息,然后创建一个UI物体,加载到滚动content中
    {
        string res = PhotonNetwork.NickName + " : " + _inputField.text;
        GameObject obj = PhotonNetwork.Instantiate(DialogueText, Vector3.zero, Quaternion.identity);
        obj.GetComponent<Text>().text = res;
        obj.GetComponent<SentenceAsync>().str = res;
        obj.transform.SetParent(Content.transform);
        _inputField.text = "";	// 发送玩后清空输入框
    }
}
  • 同步文本信息脚本 SentenceAsync 如下,需要实现 IPunObservable 接口的 OnPhotonSerializeView 方法
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using UnityEngine.UI;
public class SentenceAsync : MonoBehaviourPunCallbacks, IPunObservable
{
    public string str;
    public GameManagerPUN gm;
    public GameObject pa;


    void IPunObservable.OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    {
        if (stream.IsWriting)
        {
            stream.SendNext(str);
        }
        else
        {
            str = (string)stream.ReceiveNext();
            if (pa == null)		// 用于在不同客户端的同步处理
            {
                pa = GameObject.Find("Content");
                this.gameObject.transform.SetParent(pa.transform);
                this.GetComponent<Text>().text = str;
            }
        }
    }
}
  • 没错,该同步脚本纠结了我好几个小时,才成功处理对。为什么这么麻烦呢?

简单同步

  • 同步的基本原理比较复杂, 所幸该 Photon + Pun2 给我们封装的差不多了,我们只需要知道基础的内容即可
  • 简单来说,假设有客户端 A,B,C,他们都连接服务器 X
    在客户端 A 处,玩家创建了一个球,若只是普通创建,则只有 A 处的玩家能看到该球。
    若希望每个客户端都能看到该球,首先需要使用 PhotonNetwork.Instantiate(str, Vector3, Quaternion) 方法进行同步创建。注意创建物体通过给定它的字符串 str,该预设体的路径必须在该 PhotonUnityNetworking / Resources 文件夹下:
    【Unity工具,简单应用】Photon + PUN 2,做一个简单多人在线聊天室
  • 第二步,指定该物体需要同步什么信息。对于该球,我们只需要同步它的位置信息即可。
    物体若需要同步信息,则必须创建 Photon View 脚本。
    物体若需要同步信息,则必须创建 Photon View 脚本。
    物体若需要同步信息,则必须创建 Photon View 脚本。
    重要的信息重复三次
    物体若需要同步 transform 信息,则直接给它 Photon Transform View 脚本即可
    【Unity工具,简单应用】Photon + PUN 2,做一个简单多人在线聊天室
  • 这里,Ownership 表示该物体的所有权是否转移,比如 A 创建了该物体,是否允许 B 更改它的信息。这里还设计到主机与从机的区别。但这里我们不更改别的信息,设置 fixed` 即可
  • 这里 Synchronization 选择 Unreliable On Change 即可,Observable Search 选择同步的观察信息,可以直接选择 Auto Find Active 或者设置 Manual 然后手动给予它需要同步信息的脚本即可。
  • 能被观察到的脚本必须实现 IPunObservable 接口,实现 IPunObservable.OnPhotonSerializeView 方法。

较复杂同步

  • 我们搜索一下已经有的脚本,发现官方直接支持我们如下的同步脚本:
    【Unity工具,简单应用】Photon + PUN 2,做一个简单多人在线聊天室
  • 也就是说,若需要同步的观察信息只有 Animator, Rigidbody, Transform 那么可以直接挂载相应的脚本进行同步。
  • 那如果我们需要同步某数值信息,比如 int, float, string 呢?该三种信息同步相应来说比较容易
    仍然,我们需要实现 IPunObservable 接口,实现 IPunObservable.OnPhotonSerializeView 方法
    void IPunObservable.OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    {
        if (stream.IsWriting)		// 若流正在写,我们发送接下来要同步的信息 string str
        {
            stream.SendNext(str);
        }
        else
        {
            str = (string)stream.ReceiveNext();		// 接受流的下一个输出,并转化为 (string) 类型
            if (pa == null)		// (1)
            {
                pa = GameObject.Find("Content");
                this.gameObject.transform.SetParent(pa.transform);
                this.GetComponent<Text>().text = str;
            }
        }
    }
  • 我们发现,其他脚本都很好懂,那么 (1) 处是什么意思呢?
    【Unity工具,简单应用】Photon + PUN 2,做一个简单多人在线聊天室
    这里每行对话物体,由于挂载在 Canvas 中,且挂载 Text 组件,所以必须为 Rect Transform 组件
    尽管 Rect Transform 组件是继承自 Transform 组件,但是它的信息与 Transform 组件截然不同,所以官方提供的 Photon Transform View 不能使用(你挂载就会出bug,可以F12查看该脚本原码)
  • 难道我们去实现能同步 RectTransform 或者 Text 信息的脚本?写起来有点麻烦…
    但是我们转念一想,我们需要同步的信息只有 发送信息的字符串而已
    所以我们只同步字符串。由于 PhotonNetwork.Instantiate() 方法已经为我们创建了该同步物体,所以别的组件都是创建出来的,只是其中的信息没有同步而已
  • 我们还需要同步哪个信息?
    RectTransform? 不需要,由于我们使用 ScrollView,自动处理它的各种坐标信息
    Text? 我们只需给予其 Text.text = str 即可,其他的字体啥信息都默认即可
    还有一个隐藏的需要同步的信息 —— 该物体的 父对象。父对象由于我们没有同步,所以它默认会创建在世界根节点的下面,不会显示在 ScrollView 下。
    由于该 ScrollView 下面的那些默认物体是每个玩家一开始就是一样的,所以我们只需要单纯通过 (1) 指定,把自己挂载到该父对象上即可。

自定义同步

  • 若需要自定义同步,由于 stream.ReceiveNext() 强转类型只支持默认的那三个 int, float, string,所以你想同步比如说 Rect Transform 或者 XXXscript 脚本,就需要去里面注册某物体类型
  • 很麻烦,不怎么推荐,相当于指定某个类型的序列化和反序列化的规则,可以自己去搜集信息。

最终效果

  • 我和室友,使用的是两台笔记本的两个客户端,在里面进行聊天
    【Unity工具,简单应用】Photon + PUN 2,做一个简单多人在线聊天室
  • 经过测试发现,若某玩家退出后,由该 owner 通过 PhotonNetwork.Instantiate 创建的同步物体会自动 Destroy。猜测可以通过转移所有权的方式保留聊天记录。

文章来源地址https://www.toymoban.com/news/detail-472372.html

到了这里,关于【Unity工具,简单应用】Photon + PUN 2,做一个简单多人在线聊天室的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • Photon Unity Networking 实时多人在线游戏开发解决方案

    作者:禅与计算机程序设计艺术 2019年,由英特尔、Facebook等公司联合举办的GDC大会上宣布了Unity Technologies将推出一个新品牌——Unity Game Development Platform(UGDP)。这个平台将包括对虚幻引擎4、Unreal Engine 4和原生Unity引擎的支持。在这个平台基础上,Unity Technologies推出了实时的多

    2024年02月09日
    浏览(24)
  • 在Unity中使用Photon(网络多人联机)

    photon官网地址

    2024年02月04日
    浏览(26)
  • 【Unity Photon Fusion 2】多人联网插件,共享模式基础教程

    见主机模式基础教程 【Unity Photon Fusion 2】多人联网插件,主机模式基础教程-CSDN博客 概述 该部分解释了如何设置一个简单的场景以及如何创建一个玩家预制件。在本节结束时,您将拥有一个工作的网络场景,为每个连接的客户端生成一个播放器对象。 2.1.1 设置场景 从一个空

    2024年04月27日
    浏览(26)
  • 【Unity Photon Fusion 2】多人联网插件,主机模式基础教程

            Fusion是Unity的一個新的高性能狀態同步網路庫。Fusion在組建時考慮到了簡化性,可以自然地集成到普通的Unity工作流程中,同時也提供了先進的功能,如資料壓縮、客戶端預測和開箱即用的延遲補償。         本質上,Fusion依靠最先進的壓縮演算法,以最小的

    2024年04月15日
    浏览(29)
  • 如何用photon创建多人vr应用《一》photon插件的导入及设置中国区

    2018.4.2.2版本及以上unity适用 第一步,打开unity导入photon包,为什么要2018.4.2.2版本呢,因为最低2018.4.2.2才能用pun2插件, 就这个东西。 导入进去之后,申请好photon pun远程服务器, Multiplayer Game Development Made Easy | Photon Engine 去中国区光子云免费申请 | 光子引擎photonengine中文站 申

    2023年04月08日
    浏览(27)
  • 项目实训--Unity多人游戏开发(十一、PUN框架--游戏场景篇(加载与同步))

    本地加载 有许多方法,举几个例子: 本地加载 本地异步加载(场景内容过多时,防止卡顿异步加载) 多人游戏加载场景 pun2插件加载 这个异步加载起初是觉得场景内容如果过多会引起卡顿。所以把这个应用在了单机模式上。 至于多人游戏加载场景,可能用不到而且也没法

    2024年02月01日
    浏览(38)
  • 【Unity 3D】利用C#、Unity和Socket实现简单的在线聊天室工具(附源码 简单易懂)

    需要源码请点赞关注收藏后评论区留言并且私信~~~ 下面利用Unity和C#语言做一个简单的聊天室程序,主要用到的技术就是Socket通信连接,需要一个客户端和一个服务器端,服务器端就使用C#语言的控制台完成 下面就开始搭建C#语言服务器端 1:新建一个C#语言控制台程序 2:命名

    2024年02月05日
    浏览(42)
  • Unity mirror实现多人同时在线(LINUX)保姆级

    话不多说直接开始 1 申请服务器(阿里云/腾讯云) 笔者这边直接白嫖的阿里云一个月,测试学习一个月应该是够了。记得重置密码并记录 申请完成后点击左侧目录找到云服务器。记住这个公有服务器,等等会用到。 2 Unity Mirror 坦克大战场景 在NetworkManager找到对应地址,填写

    2024年02月06日
    浏览(50)
  • 基于Unity客户端与服务端实现登录与注册以及多人在线聊天

    1.在Unity下,创建一个GameManager空对象,用于启动客户端连接以及实例化一个登录页面LoginView的Prefab,并将脚本LoginView挂载在上面。 2.创建一个Client类,用于客户端向服务端发起连接请求,并且发送给服务端消息以及接收服务端的响应 3.创建一个脚本LoginView挂载在LoginView对象上

    2024年04月16日
    浏览(33)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包