当前位置: 首页 > news >正文

松江品划网站建设维护网站首页的优化

松江品划网站建设维护,网站首页的优化,沈阳酒店企业网站制作公司,彩票交易网站开发【Unity工具,简单应用】Photon PUN 2,做一个简单多人聊天室前置知识,安装,及简单UI大厅聊天室简单同步较复杂同步自定义同步最终效果前置知识,安装,及简单UI 【Unity工具,简单学习】PUN 2&…

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

  • 前置知识,安装,及简单UI
  • 大厅
  • 聊天室
  • 简单同步
  • 较复杂同步
  • 自定义同步
  • 最终效果

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

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

大厅

  • 简单搭建一下大厅UI。
    Laucher 节点一个 Launcher 脚本
    在这里插入图片描述
  • 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 levelPhotonNetwork.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 的物体并给予它对应的脚本组件
    在这里插入图片描述
  • 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 connectingif (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 disconnectsif (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 文件夹下:
    在这里插入图片描述
  • 第二步,指定该物体需要同步什么信息。对于该球,我们只需要同步它的位置信息即可。
    物体若需要同步信息,则必须创建 Photon View 脚本。
    物体若需要同步信息,则必须创建 Photon View 脚本。
    物体若需要同步信息,则必须创建 Photon View 脚本。
    重要的信息重复三次
    物体若需要同步 transform 信息,则直接给它 Photon Transform View 脚本即可
    在这里插入图片描述
  • 这里,Ownership 表示该物体的所有权是否转移,比如 A 创建了该物体,是否允许 B 更改它的信息。这里还设计到主机与从机的区别。但这里我们不更改别的信息,设置 fixed` 即可
  • 这里 Synchronization 选择 Unreliable On Change 即可,Observable Search 选择同步的观察信息,可以直接选择 Auto Find Active 或者设置 Manual 然后手动给予它需要同步信息的脚本即可。
  • 能被观察到的脚本必须实现 IPunObservable 接口,实现 IPunObservable.OnPhotonSerializeView 方法。

较复杂同步

  • 我们搜索一下已经有的脚本,发现官方直接支持我们如下的同步脚本:
    在这里插入图片描述
  • 也就是说,若需要同步的观察信息只有 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) 处是什么意思呢?
    在这里插入图片描述
    这里每行对话物体,由于挂载在 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 脚本,就需要去里面注册某物体类型
  • 很麻烦,不怎么推荐,相当于指定某个类型的序列化和反序列化的规则,可以自己去搜集信息。

最终效果

  • 我和室友,使用的是两台笔记本的两个客户端,在里面进行聊天
    在这里插入图片描述
  • 经过测试发现,若某玩家退出后,由该 owner 通过 PhotonNetwork.Instantiate 创建的同步物体会自动 Destroy。猜测可以通过转移所有权的方式保留聊天记录。
http://www.bjxfkj.com.cn/article/100390.html

相关文章:

  • 合肥专业网站优化价格app软件推广平台
  • 广州市疫情防控新闻发布会直播企业网站seo排名
  • 做视频网站需要什么高端技术标题优化
  • 成都网站推广嘉兴关键词优化报价
  • 自己做网站怎么让字体居中长尾关键词挖掘爱站工具
  • 找程序员做网站长春百度推广公司
  • 杭州哪些做网站公司好seo软件服务
  • 网站规划与设计一千字域名解析ip138在线查询
  • wordpress 做app分销seo怎么做整站排名
  • 佛山专业建设网站平台推广计划书怎么写
  • python开发手机网站开发网络平台销售
  • 个人淘宝客网站有哪些seo优化思路
  • wordpress 页脚声明关键词排名优化官网
  • 济南做网站的好公司网上国网app推广方案
  • 全屏响应式网站网站的优化seo
  • 济宁网站建设top网络广告人社区
  • wordpress头部标签描述知了seo
  • 广告推广是什么工作南昌百度搜索排名优化
  • 做微商城网站电商运营是做什么的
  • python做网站 知乎如何优化百度seo排名
  • 30个成功的电子商务网站设计服装网络营销策划书
  • 做网站的重要性市场推广怎么写
  • 北京顺义住房和城乡建设委员会网站品牌推广策划方案怎么写
  • 哪里做网站最好seo关键词排名技术
  • 做时时彩网站需要加盟网站seo诊断报告怎么写
  • 重庆永川网站建设价格招商外包公司
  • wordpress可以做什么站爱站小工具圣经
  • 怎么做的网站怎么放上网推广seo公司
  • 微信你的意义是什么小程序哪里有seo排名优化
  • 穷游网站 做行程 封面上海seo优化外包公司