国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【Unity工具,簡(jiǎn)單應(yīng)用】Photon + PUN 2,做一個(gè)簡(jiǎn)單多人在線聊天室

這篇具有很好參考價(jià)值的文章主要介紹了【Unity工具,簡(jiǎn)單應(yīng)用】Photon + PUN 2,做一個(gè)簡(jiǎn)單多人在線聊天室。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

前置知識(shí),安裝,及簡(jiǎn)單UI

  • 【Unity工具,簡(jiǎn)單學(xué)習(xí)】PUN 2,多人在線游戲開(kāi)發(fā),初步使用
  • 需要有一定 UNITY 使用經(jīng)驗(yàn)的開(kāi)發(fā)者可以順利閱讀。

大廳

  • 簡(jiǎn)單搭建一下大廳UI。
    Laucher 節(jié)點(diǎn)一個(gè) Launcher 腳本
    【Unity工具,簡(jiǎn)單應(yīng)用】Photon + PUN 2,做一個(gè)簡(jiǎn)單多人在線聊天室
  • 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";		// 設(shè)置房間名,確保每次連接到同一個(gè)房間
    private string gameVersion = "1";

    [SerializeField]
    private const byte maxPlayersPerRoom = 4;	// 設(shè)置單房間最多玩家數(shù)
    [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,否則無(wú)法同步

        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 來(lái)連接
            PhotonNetwork.GameVersion = gameVersion;
        }
    }
    public override void OnJoinRandomFailed(short returnCode, string message)	// 若加入隨機(jī)房間失敗
    {
        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()		// 若加入了某房間,則加載聊天室場(chǎng)景,不要使用 UNITY的加載場(chǎng)景方法
    {
        Debug.Log("PUN Basics Tutorial/Launcher: OnJoinedRoom() called by PUN. Now this client is in a room.");

        PhotonNetwork.LoadLevel("ChatingRoom");
    }
    public override void OnConnectedToMaster()	// 運(yùn)行ConnectUsingSettings()后會(huì)先連接到 Master節(jié)點(diǎn),再創(chuàng)建或加載房間
    {
        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); 方法,若該房間名的房間不存在則創(chuàng)建,否則加載該房間。
  • 在輸入框中,把該字符串賦值給 PhotonNetwork.NickName 即表示該玩家的名稱(chēng),需非空
    PhotonNetwork.NickName = defaultName;

聊天室

  • 聊天室的UI如下
    添加一個(gè) GameManagerPUN 的物體并給予它對(duì)應(yīng)的腳本組件
    【Unity工具,簡(jiǎn)單應(yīng)用】Photon + PUN 2,做一個(gè)簡(jiǎn)單多人在線聊天室
  • 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 創(chuàng)建一個(gè)物體,讓它的位置隨機(jī)變一下,代表顯示該房間內(nèi)的玩家個(gè)數(shù)
    }

    public override void OnLeftRoom()
    {
        SceneManager.LoadScene("LobbyScene");
    }
    public void LeaveRoom()	// 退出按鈕的監(jiān)聽(tīng)器直接調(diào)用該代碼即可調(diào)用 OnLeftRoom() 方法,退出大廳
    {
        PhotonNetwork.LeaveRoom();
    }

    public override void OnPlayerEnteredRoom(Player other)	// 自動(dòng)監(jiān)聽(tīng)是否有玩家進(jìn)入
    {
        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)	// 自動(dòng)監(jiān)聽(tīng)是否有玩家退出
    {
        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()	// 發(fā)送消息,記錄發(fā)送消息者名稱(chēng),與它發(fā)送的消息,然后創(chuàng)建一個(gè)UI物體,加載到滾動(dòng)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 = "";	// 發(fā)送玩后清空輸入框
    }
}
  • 同步文本信息腳本 SentenceAsync 如下,需要實(shí)現(xiàn) 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)		// 用于在不同客戶(hù)端的同步處理
            {
                pa = GameObject.Find("Content");
                this.gameObject.transform.SetParent(pa.transform);
                this.GetComponent<Text>().text = str;
            }
        }
    }
}
  • 沒(méi)錯(cuò),該同步腳本糾結(jié)了我好幾個(gè)小時(shí),才成功處理對(duì)。為什么這么麻煩呢?

簡(jiǎn)單同步

  • 同步的基本原理比較復(fù)雜, 所幸該 Photon + Pun2 給我們封裝的差不多了,我們只需要知道基礎(chǔ)的內(nèi)容即可
  • 簡(jiǎn)單來(lái)說(shuō),假設(shè)有客戶(hù)端 A,B,C,他們都連接服務(wù)器 X
    在客戶(hù)端 A 處,玩家創(chuàng)建了一個(gè)球,若只是普通創(chuàng)建,則只有 A 處的玩家能看到該球。
    若希望每個(gè)客戶(hù)端都能看到該球,首先需要使用 PhotonNetwork.Instantiate(str, Vector3, Quaternion) 方法進(jìn)行同步創(chuàng)建。注意創(chuàng)建物體通過(guò)給定它的字符串 str,該預(yù)設(shè)體的路徑必須在該 PhotonUnityNetworking / Resources 文件夾下:
    【Unity工具,簡(jiǎn)單應(yīng)用】Photon + PUN 2,做一個(gè)簡(jiǎn)單多人在線聊天室
  • 第二步,指定該物體需要同步什么信息。對(duì)于該球,我們只需要同步它的位置信息即可。
    物體若需要同步信息,則必須創(chuàng)建 Photon View 腳本。
    物體若需要同步信息,則必須創(chuàng)建 Photon View 腳本。
    物體若需要同步信息,則必須創(chuàng)建 Photon View 腳本。
    重要的信息重復(fù)三次
    物體若需要同步 transform 信息,則直接給它 Photon Transform View 腳本即可
    【Unity工具,簡(jiǎn)單應(yīng)用】Photon + PUN 2,做一個(gè)簡(jiǎn)單多人在線聊天室
  • 這里,Ownership 表示該物體的所有權(quán)是否轉(zhuǎn)移,比如 A 創(chuàng)建了該物體,是否允許 B 更改它的信息。這里還設(shè)計(jì)到主機(jī)與從機(jī)的區(qū)別。但這里我們不更改別的信息,設(shè)置 fixed` 即可
  • 這里 Synchronization 選擇 Unreliable On Change 即可,Observable Search 選擇同步的觀察信息,可以直接選擇 Auto Find Active 或者設(shè)置 Manual 然后手動(dòng)給予它需要同步信息的腳本即可。
  • 能被觀察到的腳本必須實(shí)現(xiàn) IPunObservable 接口,實(shí)現(xiàn) IPunObservable.OnPhotonSerializeView 方法。

較復(fù)雜同步

  • 我們搜索一下已經(jīng)有的腳本,發(fā)現(xiàn)官方直接支持我們?nèi)缦碌耐侥_本:
    【Unity工具,簡(jiǎn)單應(yīng)用】Photon + PUN 2,做一個(gè)簡(jiǎn)單多人在線聊天室
  • 也就是說(shuō),若需要同步的觀察信息只有 Animator, Rigidbody, Transform 那么可以直接掛載相應(yīng)的腳本進(jìn)行同步。
  • 那如果我們需要同步某數(shù)值信息,比如 int, float, string 呢?該三種信息同步相應(yīng)來(lái)說(shuō)比較容易
    仍然,我們需要實(shí)現(xiàn) IPunObservable 接口,實(shí)現(xiàn) IPunObservable.OnPhotonSerializeView 方法
    void IPunObservable.OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    {
        if (stream.IsWriting)		// 若流正在寫(xiě),我們發(fā)送接下來(lái)要同步的信息 string str
        {
            stream.SendNext(str);
        }
        else
        {
            str = (string)stream.ReceiveNext();		// 接受流的下一個(gè)輸出,并轉(zhuǎn)化為 (string) 類(lèi)型
            if (pa == null)		// (1)
            {
                pa = GameObject.Find("Content");
                this.gameObject.transform.SetParent(pa.transform);
                this.GetComponent<Text>().text = str;
            }
        }
    }
  • 我們發(fā)現(xiàn),其他腳本都很好懂,那么 (1) 處是什么意思呢?
    【Unity工具,簡(jiǎn)單應(yīng)用】Photon + PUN 2,做一個(gè)簡(jiǎn)單多人在線聊天室
    這里每行對(duì)話(huà)物體,由于掛載在 Canvas 中,且掛載 Text 組件,所以必須為 Rect Transform 組件
    盡管 Rect Transform 組件是繼承自 Transform 組件,但是它的信息與 Transform 組件截然不同,所以官方提供的 Photon Transform View 不能使用(你掛載就會(huì)出bug,可以F12查看該腳本原碼)
  • 難道我們?nèi)?shí)現(xiàn)能同步 RectTransform 或者 Text 信息的腳本?寫(xiě)起來(lái)有點(diǎn)麻煩…
    但是我們轉(zhuǎn)念一想,我們需要同步的信息只有 發(fā)送信息的字符串而已
    所以我們只同步字符串。由于 PhotonNetwork.Instantiate() 方法已經(jīng)為我們創(chuàng)建了該同步物體,所以別的組件都是創(chuàng)建出來(lái)的,只是其中的信息沒(méi)有同步而已
  • 我們還需要同步哪個(gè)信息?
    RectTransform? 不需要,由于我們使用 ScrollView,自動(dòng)處理它的各種坐標(biāo)信息
    Text? 我們只需給予其 Text.text = str 即可,其他的字體啥信息都默認(rèn)即可
    還有一個(gè)隱藏的需要同步的信息 —— 該物體的 父對(duì)象。父對(duì)象由于我們沒(méi)有同步,所以它默認(rèn)會(huì)創(chuàng)建在世界根節(jié)點(diǎn)的下面,不會(huì)顯示在 ScrollView 下。
    由于該 ScrollView 下面的那些默認(rèn)物體是每個(gè)玩家一開(kāi)始就是一樣的,所以我們只需要單純通過(guò) (1) 指定,把自己掛載到該父對(duì)象上即可。

自定義同步

  • 若需要自定義同步,由于 stream.ReceiveNext() 強(qiáng)轉(zhuǎn)類(lèi)型只支持默認(rèn)的那三個(gè) int, float, string,所以你想同步比如說(shuō) Rect Transform 或者 XXXscript 腳本,就需要去里面注冊(cè)某物體類(lèi)型
  • 很麻煩,不怎么推薦,相當(dāng)于指定某個(gè)類(lèi)型的序列化和反序列化的規(guī)則,可以自己去搜集信息。

最終效果

  • 我和室友,使用的是兩臺(tái)筆記本的兩個(gè)客戶(hù)端,在里面進(jìn)行聊天
    【Unity工具,簡(jiǎn)單應(yīng)用】Photon + PUN 2,做一個(gè)簡(jiǎn)單多人在線聊天室
  • 經(jīng)過(guò)測(cè)試發(fā)現(xiàn),若某玩家退出后,由該 owner 通過(guò) PhotonNetwork.Instantiate 創(chuàng)建的同步物體會(huì)自動(dòng) Destroy。猜測(cè)可以通過(guò)轉(zhuǎn)移所有權(quán)的方式保留聊天記錄。

文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-472372.html

到了這里,關(guān)于【Unity工具,簡(jiǎn)單應(yīng)用】Photon + PUN 2,做一個(gè)簡(jiǎn)單多人在線聊天室的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包