unity多人联机插件_基于Photon Cloud的Unity多人游戏开发日志_新的场景,新的开始...

0a6de46b05336424f60f5db9dac74782.png

基于Photon Cloud的Unity多人游戏开发日志目录

Berkeley Zhou:基于Photon Cloud的Unity多人游戏开发日志_目录​zhuanlan.zhihu.com
84f36ee4916af274f668970e7c01b46b.png

上一次我们讲到如何创建一个虚拟房间并加入

Berkeley Zhou:基于Photon Cloud的Unity多人游戏开发日志_房间,对战的开始​zhuanlan.zhihu.com
84f36ee4916af274f668970e7c01b46b.png

现在该离开大厅进入我们的游戏了

是的,我们需要一个新的场景了

暂且叫它PlayGround吧

建一个60x60的地面

ab9a0c533ecdeb865c38ca0427475c62.png

这个地面白的辣眼睛,我用一款插件给他上一个测试贴图

插件名称叫做Forceling World Grid

以前是支持全版本的,不知道为啥现在只支持2019版本了QAQ

b386590f0ce4fb09eb345159bfe43757.png

用上插件的效果

779aa183d9b263307fac6649043a17d6.png

不仅不辣眼睛了,还有标尺。简直是Demo好伙伴

想要我介绍这个插件的可以评论区反馈一下

好了言归正传,我们赶紧把场景搭完

fcaa6b0d3df1d05f00378e4dce0138b9.png
新建四面墙

新场景建立完成,我们回到熟悉的ConnectManager里面

再在OnJoinedRoom()回调函数里面加上如下内容

    public override void OnJoinedRoom()
    {
        Debug.Log("Join successful!");
        if (PhotonNetwork.CurrentRoom.PlayerCount == 1)
        {
            Debug.Log("Initiative load level.");
            PhotonNetwork.LoadLevel(1);
        }

        base.OnJoinedRoom();
    }

这段代码什么意思呢

就是说,如果房间里只有一个人,我们就主动载入新场景

我知道你现在非常疑惑,但是问题我们慢慢解决

首先我们看一下载入场景的代码PhotonNetwork.LoadLevel(1);

这就和以前的SceneManager.LoadScene()方法截然不同了,我们现在使用的是网络载入

然后就是LoadLevel(1)这个1在哪里

熟悉场景载入的同学应该就知道了,这是在BuildSettings里面设置好的,我们现在去设置一下

8df2086b6a144927570c6401c7227b75.png

然后我们再来回顾一下,如果房间里的玩家数量是一个,我们就主动载入场景,那这个玩家是谁呢?

当然就是我们自己啦!

所以只有在房间里只有自己的时候我们要主动载入场景

因为在Photon的定义中,刚刚是你调用了Create()函数创建你的房间,你就是房主

那如果其他玩家加入房间怎么办呢?

这个时候我们就要设置一个重要的参数了

在Start()函数里面写上如下代码

    void Start()
    {
        //Connect();
        PhotonNetwork.AutomaticallySyncScene = true;
    }

这句PhotonNetwork.AutomaticallySyncScene =true;就是在说:

如果你不是房主,你就得听房主的话,跟着房主同步载入场景

你的房主在那个场景,你就要在哪个场景

这些都写好了,我们看下成果

80ce8111bfe9ef4b34a62fe53cb83289.png

传 统 艺 能

但是等等,你觉得这期就这么结束了吗???

我不要你觉得,我要我觉得

我觉得还可以改进一些内容(•̀ロ•́) ✧ ~~

8eeddd800da5c0c5281a6a06c49f0971.png

还记得这个加入游戏的按钮吗,理论上必须要连接上服务器才能能加入房间

但是我们没有写这样的限制

我们回到ConnectManager里面,加一个序列化变量

    [Tooltip("<加入游戏>按钮")]
    [SerializeField]
    Button joinRoomButton;

然后改写一下连接上和断开连接的回调函数

    public override void OnConnected()
    {
        Debug.Log("Connect successful!");
        if (joinRoomButton!=null)
            joinRoomButton.interactable = true;

        base.OnConnected();
    }
    public override void OnDisconnected(DisconnectCause cause)
    {
        if (joinRoomButton!=null)
            joinRoomButton.interactable = false;

        base.OnDisconnected(cause);
    }

这里写if(joinRoomButton!=null)也是为了解耦,让加入房间的按钮不是必须存在的。

然后Start()函数也可以改一改

    void Start()
    {
        //Connect();
        PhotonNetwork.AutomaticallySyncScene = true;
        if (joinRoomButton != null)
        {
            if (PhotonNetwork.IsConnected)
            {
                joinRoomButton.interactable = true;
            }
            else
            {
                joinRoomButton.interactable = false;
            }
        }
    }

测试一下

4682e785572e3667ecc3508e8550e4bd.png

4aa49f9a426f0e3e1c94e618343bd5fc.png

完全成功

晾出代码,收工睡觉


ConnectManager

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Realtime;
using Photon.Pun;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class ConnectManager : MonoBehaviourPunCallbacks
{

    #region 序列化变量
    [Tooltip("最大房间玩家数量")]
    [SerializeField]
    byte maxPlayerNumber = 4;

    [Tooltip("<加入游戏>按钮")]
    [SerializeField]
    Button joinRoomButton;
    #endregion

    #region GameVersion

    string gameVersion = "2";

    #endregion

    // Start is called before the first frame update
    void Start()
    {
        //Connect();
        PhotonNetwork.AutomaticallySyncScene = true;
        if (joinRoomButton != null)
        {
            if (PhotonNetwork.IsConnected)
            {
                joinRoomButton.interactable = true;
            }
            else
            {
                joinRoomButton.interactable = false;
            }
        }
    }

    // Update is called once per frame
    void Update()
    {

    }

    #region Public Methods
    /// <summary>
    /// 连接方法,如果已经连接上了Debug一下
    /// </summary>
    /// <returns></returns>
    public void Connect()
    {
        if (PhotonNetwork.IsConnected)
        {
            Debug.Log("Already Connected");
        }
        else
        {
            PhotonNetwork.GameVersion = gameVersion;
            PhotonNetwork.ConnectUsingSettings();
        }
    }

    public void JoinRoom()
    {
        //如果还没有连上服务器
        if (!PhotonNetwork.IsConnected)
        {
            Connect();
        }
        else
        {
            PhotonNetwork.JoinRandomRoom();
        }
    }
    #endregion

    #region PUN Callbacks

    public override void OnConnected()
    {
        Debug.Log("Connect successful!");
        if (joinRoomButton!=null)
            joinRoomButton.interactable = true;

        base.OnConnected();
    }

    public override void OnDisconnected(DisconnectCause cause)
    {
        if (joinRoomButton!=null)
            joinRoomButton.interactable = false;

        base.OnDisconnected(cause);
    }

    public override void OnJoinRandomFailed(short returnCode, string message)
    {
        PhotonNetwork.CreateRoom(null, new RoomOptions { MaxPlayers = maxPlayerNumber });
        Debug.Log("Join room failed, create one.");

        base.OnJoinRandomFailed(returnCode, message);
    }

    public override void OnJoinedRoom()
    {
        Debug.Log("Join successful!");
        if (PhotonNetwork.CurrentRoom.PlayerCount == 1)
        {
            Debug.Log("Initiative load level.");
            PhotonNetwork.LoadLevel(1);
        }

        base.OnJoinedRoom();
    }
    #endregion
}

InputFieldManager

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class InputFieldManager : MonoBehaviour
{
    #region Required Compoments
    public InputField userNameInputField;
    public IOManager ioManager;
    #endregion

    // Start is called before the first frame update
    void Start()
    {
        //如果存在玩家用户名的储存文件
        if (ioManager.UserNameExist())
        {
            Debug.Log(ioManager.ReadUserName());
            userNameInputField.text = ioManager.ReadUserName();
        }
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

IOManager

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;

public class IOManager : MonoBehaviour
{
    #region File Names
    [Tooltip("玩家用户名信息存储地址")]
    [SerializeField]
    string userNameFileName = "/UserID.txt";
    #endregion

    #region Public Field
    #endregion

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    #region Public Method
    /// <summary>
    /// 写入玩家用户名
    /// </summary>
    /// <param name="name"></param>
    public void WriteUserName(string name)
    {
        string filePath = Application.dataPath + userNameFileName;
        //文件读写流
        StreamWriter sw;
        //文件地址信息
        FileInfo fi = new FileInfo(filePath);
        //如果文件不存在
        if (!fi.Exists)
        {
            sw = fi.CreateText();
        }
        //如果存在
        else
        {
            //销毁文件
            File.Delete(filePath);
            sw = fi.CreateText();
        }
        sw.WriteLine(name);
        //关闭&销毁流
        sw.Close();
        sw.Dispose();
    }

    /// <summary>
    /// 读取玩家的用户名
    /// </summary>
    /// <returns></returns>
    public string ReadUserName()
    {
        string filePath = Application.dataPath + userNameFileName;
        //先判断一下文件是否存在
        if (!File.Exists(filePath))
        {
            Debug.Log("User name file donot exist.");
            return null;
        }

        //打开文件读取流
        StreamReader sr = File.OpenText(filePath);
        string userName = sr.ReadLine();
        sr.Close();
        sr.Dispose();

        return userName;
    }

    public bool UserNameExist()
    {
        string filePath = Application.dataPath + userNameFileName;
        //先判断一下文件是否存在
        if (File.Exists(filePath))
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    #endregion
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值