前言:

photon PUN是一款用于实现联网对战的插件,通过简单的设计,就可以实现加入大厅,加入房间,并且进行对战,玩家可以同步动画和位置等参数,同时可以通过RPC机制,广播参数,实现房间内的玩家消息共享。

对战实现

1.打开photon官网,再打开账号,登录。

2.点击Your Applications,创建应用,选择PUN,按要求填写,然后再复制Appid,打开unity创建项目。

3.在unity的资源商店中搜索photon PUN,下载导入。

4.粘贴刚才复制的appid,点击setup project—close

5.新建一个场景,添加如下的UI组件,一个是名字输入面板,点击之后进入大厅。


6.在场景中新建一个空物体,命名NetWorkManager,同样新建一个脚本NetworkManager,填充命名空间PUN,更改继承类为MonoBehaviourPunCallbacks,首先在start函数中启动。连接服务器,具体的代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using UnityEngine.UI;
using Photon.Realtime;public class NetworkManager : MonoBehaviourPunCallbacks
{#region 私有变量#endregion#region 公开变量public static NetworkManager _instance;//单例public InputField nameInputField;//名字输入框public InputField RoomnameInputField;//房间名输入框public GameObject readyBtn;//准备按钮public GameObject startBtn;//开始游戏按钮public GameObject NamePanel;//名字设置面板public GameObject LobbyPanel;//大厅面板public GameObject RoomPanel;//房间面板public GameObject StartInitPanel;//开始初始化面板#endregion#region Mono函数private void Awake(){if (_instance == null){_instance = this;}}private void Start(){PhotonNetwork.ConnectUsingSettings();//初始化设置,连接服务器}private void Update(){if (PhotonNetwork.LocalPlayer.IsMasterClient)//判断是否是房主,是就显示开始游戏按钮,不是就显示准备按钮{readyBtn.SetActive(false);startBtn.SetActive(true);}else{readyBtn.SetActive(true);startBtn.SetActive(false);}}#endregion#region 按钮函数/// <summary>/// 名字设置按钮/// </summary>public void SetNicknameButton(){if (nameInputField.text.Length < 2)return;PhotonNetwork.NickName = nameInputField.text;//将输入的名字上传至网络if(PhotonNetwork.InLobby)//判断是否在大厅内,在就显示大厅,隐藏名字面板{LobbyPanel.SetActive(true);NamePanel.SetActive(false);Debug.Log("已经在大厅中");}}/// <summary>/// 创建或加入房间按钮/// </summary>public void joinOrCreateRoomBtn(){if(RoomnameInputField.text.Length<=2){return;}LobbyPanel.SetActive(false);RoomOptions roomOptions = new RoomOptions { MaxPlayers = 4 };//房间最大人数4人PhotonNetwork.JoinOrCreateRoom(RoomnameInputField.text, roomOptions, default);RoomPanel.SetActive(true);}#endregion#region Photon函数public override void OnJoinedRoom(){if (PhotonNetwork.LocalPlayer.IsMasterClient)//判断是否是房主,是就显示开始游戏按钮,不是就显示准备按钮{readyBtn.SetActive(false);startBtn.SetActive(true);}else{readyBtn.SetActive(true);startBtn.SetActive(false);}}/// <summary>/// 当成功连接该服务器/// </summary>public override void OnConnectedToMaster(){NamePanel.SetActive(true);//显示名字面板StartInitPanel.SetActive(false);//隐藏开始初始化面板PhotonNetwork.JoinLobby();//加入大厅Debug.Log("加入大厅成功");}#endregion
}

7.新建一个RoomManagerList的空物体,同理新建一个RoomMnaager脚本,主要用来管理房间列表的显示:

using Photon.Pun;
using Photon.Realtime;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class RoomManager : MonoBehaviourPunCallbacks
{public GameObject roomNamePrefab;//房间显示的预制体public Transform gridLayout;//预制体的父物体/// <summary>/// 房间更新的函数,每次房间消失或者增加,就会进行调用,所以要对消失的时候进行特殊处理/// </summary>/// <param name="roomList">返回的房间参数</param>public override void OnRoomListUpdate(List<RoomInfo> roomList){Debug.Log("roomlist:" + roomList.Count);for (int i = 0; i < gridLayout.childCount; i++)//遍历父物体下的子物体{if (gridLayout.GetChild(i).gameObject.GetComponentInChildren<Text>().text == roomList[i].Name)//有相同的物体{Destroy(gridLayout.GetChild(i).gameObject);//销毁if (roomList[i].PlayerCount == 0)//如果房间玩家为0{roomList.Remove(roomList[i]);//移除该房间}}}foreach (var room in roomList)//遍历生成房间的显示{GameObject newRoom = Instantiate(roomNamePrefab, gridLayout.position, Quaternion.identity, gridLayout);//生成房间按钮newRoom.GetComponent<RoomBtn>().roomName = room.Name;//设置房间名字newRoom.GetComponentInChildren<Text>().text = room.Name + "(" + room.PlayerCount + "/4)";//显示参数}}
}

8.为了点击房间按钮,可以进入该房间,所以给按钮添加脚本事件,新建一个脚本RoomBtn,房间按钮是一个预制体,需要事先进行设置,在scroll view里面的content下新建按钮,然后记得给content添加Vertical layout group和content size fitter组件,同理在玩家面板,也需要设计玩家对应的预制体,方法类似,代码如下:

using Photon.Pun;
using Photon.Realtime;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class RoomBtn : MonoBehaviourPunCallbacks
{public string roomName;void Start(){}/// <summary>/// 点击按钮,加入该房间/// </summary>public void JoinRoomBtn(){PhotonNetwork.JoinRoom(roomName);//加入房间NetworkManager._instance.RoomPanel.SetActive(true);//显示房间面板NetworkManager._instance.LobbyPanel.SetActive(false);//隐藏大厅面板}}

9.在进入房间后,需要对玩家进行更新,同时要判断是不是房主,如果是,房主则可以进行开始游戏,如果不是,则显示一个准备按钮。这里其实也可以做一个聊天的联机,添加以下组件,作为聊天的输入和显示。

脚本InRoom代码:

using Photon.Pun;
using Photon.Realtime;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class InRoom : MonoBehaviourPunCallbacks
{public GameObject playerInfoPrefab;//玩家按钮预制体public Transform conlayout;//父物体List<GameObject> mplayers = new List<GameObject>();Player[] allplayers;bool ready = false;public InputField contentInput;//聊天输入框public GameObject textPrefab;//文本预制体public Transform layoutContent;//父物体void Start(){}/// <summary>/// 当加入房间时/// </summary>public override void OnJoinedRoom(){allplayers = PhotonNetwork.PlayerList;foreach (var item in allplayers){GameObject obj = Instantiate(playerInfoPrefab, conlayout);m_PlayerInfo _PlayerInfo = obj.GetComponent<m_PlayerInfo>();_PlayerInfo.playerName = item.NickName;obj.GetComponentInChildren<Text>().text = item.NickName + "(" + "未准备" + ")";mplayers.Add(obj);}}/// <summary>/// 当有玩家进入时,更新玩家列表/// </summary>/// <param name="newPlayer"></param>public override void OnPlayerEnteredRoom(Player newPlayer){GameObject obj = Instantiate(playerInfoPrefab, conlayout);m_PlayerInfo _PlayerInfo = obj.GetComponent<m_PlayerInfo>();_PlayerInfo.playerName = newPlayer.NickName;obj.GetComponentInChildren<Text>().text = newPlayer.NickName+"("+"未准备"+")";mplayers.Add(obj);}/// <summary>/// 当有玩家离开时,更新玩家列表/// </summary>/// <param name="otherPlayer"></param>public override void OnPlayerLeftRoom(Player otherPlayer){foreach (var item in mplayers){if (item.GetComponentInChildren<Text>().text.Contains(otherPlayer.NickName)){Destroy(item);break;}}}/// <summary>/// 当离开房间时,如果房间内还有人,则设置其他人为房主/// </summary>public override void OnLeftRoom(){foreach (var item in mplayers){if (item.GetComponentInChildren<Text>().text.Contains(PhotonNetwork.LocalPlayer.NickName)){if (PhotonNetwork.LocalPlayer.IsMasterClient){foreach (var p in allplayers){if (p != PhotonNetwork.LocalPlayer){PhotonNetwork.CurrentRoom.SetMasterClient(p);break;}}}Destroy(item);break;}}}Dictionary<string, bool> IsPlayerReady = new Dictionary<string, bool>();//使用字典来进行数据广播,广播字典/// <summary>/// 准备按钮事件/// </summary>public void SetReadyBtn(){foreach (var item in mplayers){m_PlayerInfo playerinfo = item.GetComponent<m_PlayerInfo>();if (!IsPlayerReady.ContainsKey(playerinfo.playerName)){IsPlayerReady.Add(playerinfo.playerName, false);}}ready = !ready;foreach (var item in IsPlayerReady){if(item.Key== PhotonNetwork.LocalPlayer.NickName){IsPlayerReady[item.Key] = ready;break;}}photonView.RPC("ReadyBtn", RpcTarget.All,PhotonNetwork.LocalPlayer.NickName,IsPlayerReady);}[PunRPC]void ReadyBtn(string xname,Dictionary<string,bool> keyValuePairs){foreach (var item in keyValuePairs){if(item.Value==true){foreach (var p in mplayers){if(p.GetComponentInChildren<Text>().text.Contains(item.Key)){p.GetComponentInChildren<Text>().text = item.Key + "(" + "已准备" + ")";break;}}}else{foreach (var p in mplayers){if (p.GetComponentInChildren<Text>().text.Contains(item.Key)){p.GetComponentInChildren<Text>().text = item.Key + "(" + "未准备" + ")";break;}}}}//foreach (var item in mplayers)//{//    Debug.Log(item.GetComponentInChildren<Text>().text);//    if (item.GetComponentInChildren<Text>().text.Contains(xname))//    {//        if(ready)//        {//          item.GetComponentInChildren<Text>().text= xname + "(" + "已准备" + ")";//        }//        else//        {//            item.GetComponentInChildren<Text>().text = xname + "(" + "未准备" + ")";//        }//        break;//    }//}}//发送消息public void SendMessInfoBtn(){string info = PhotonNetwork.LocalPlayer.NickName + " :" + contentInput.text;photonView.RPC("SendMess", RpcTarget.All,info);}[PunRPC]void SendMess(string mess){GameObject textobj = Instantiate(textPrefab, layoutContent);textobj.GetComponentInChildren<Text>().text = mess;}//开始游戏public void StartGameButton(){photonView.RPC("LoadGameScene", RpcTarget.All);}[PunRPC]void LoadGameScene(){PhotonNetwork.LoadLevel(1);}
}

这里还添加了一个代码,绑定给玩家的按钮,

代码内容:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class m_PlayerInfo : MonoBehaviour
{public string playerName;}

10.新建一个场景,记得添加在build setting里面。在这个场景中,搭一个简单的地面,同时新建一个胶囊体,作为玩家的预制体Player。添加以下组件,将他拖到以下的文件夹中,删除场景中的Player:


11.新建一个脚本,命名为GameManager,主要是用来生成玩家,记得在场景中添加,代码如下:

using Photon.Pun;
using Photon.Realtime;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class GameManager : MonoBehaviourPunCallbacks
{public static GameManager _insatnce;// Start is called before the first frame updatevoid Awake(){_insatnce = this;int index = 0;Player[] players = PhotonNetwork.PlayerList;foreach (var item in players){if (item.NickName == PhotonNetwork.NickName){index = item.ActorNumber - 1;//  PhotonNetwork.Instantiate("Player", m_spawns.mySpawns[index].spawnPos.position, Quaternion.identity);PhotonNetwork.Instantiate("Player", Vector3.zero, Quaternion.identity);Debug.Log("userid:" + item.ActorNumber);}}}
}

12.新建mPlayer脚本,用来控制玩家移动

using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class mPlayer : MonoBehaviourPunCallbacks
{void Update(){if (photonView.IsMine){MoveController();}}public void MoveController(){float h = Input.GetAxis("Horizontal");float v = Input.GetAxis("Vertical");transform.Translate(new Vector3(h, 0, v) * 10 * Time.deltaTime);}
}

13.这样,一个基础的联机机制的小demo就完成了。其实整体来说,photon这套联机机制,入门很简单,但是后期拓展和优化需要花点时间。

最后是项目源码:源码地址

使用Photon PUN创建简单对战游戏相关推荐

  1. Unity+ Photon服务器实时对战游戏——Photon服务器介绍(一)

    最近打算做实时对战的类似lol的游戏,也在学习使用Photon服务器,就分享一下.这可能是一个系列文章.记录一下学习过程,分享一下经验收获. 今天先介绍一下Photon服务器是什么,可以做什么,为什么 ...

  2. Unity 2D游戏开发快速入门第1章创建一个简单的2D游戏

    Unity 2D游戏开发快速入门第1章创建一个简单的2D游戏 即使是现在,很多初学游戏开发的同学,在谈到Unity的时候,依然会认为Unity只能用于制作3D游戏的.实际上,Unity在2013年发布 ...

  3. c++rpg黑框游戏_c++实现简单RPG对战游戏的代码.doc

    c实现简单RPG对战游戏的代码 c++实现简单RPG对战游戏的代码 #include#include#includeenum propte {sw,ar,mg};class container//人物 ...

  4. python做一个简单的对战游戏

    今天没什么事情,就自己做了一个简单的对战游戏. 这个小游戏流程大概是这样的 开始游戏 ↓ 选择人物出场顺序及技能 ↓  ←  ←  ←  ←  ←  ←  ←  ←  ← ← ↖ 开始战斗→胜利方→+ ...

  5. Unity 3D 创建简单的几何模型 || Unity 3D Assets 游戏资源目录管理

    Unity 3D 创建简单的几何模型 Unity 3D 是一个强大的游戏开发引擎.在游戏开发中使用的模型常常是从外部导入的,Unity 3D 为了方便游戏开发者快速创建模型,提供了一些简单的几何模型, ...

  6. Unity之使用Photon PUN开发多人游戏教程

    前言 Photon是一个网络引擎和多人游戏平台,可以处理其服务器上的所有请求,我们可以在 Unity(或其他游戏引擎)中使用它,并快速把游戏接入Photon的网络中,而我们就可以专注于在项目中添加逻辑 ...

  7. 学习在Unity中创建一个动作RPG游戏

    游戏开发变得简单.使用Unity学习C#并创建您自己的动作角色扮演游戏! 你会学到什么 学习C#,一种现代通用的编程语言. 了解Unity中2D发展的能力. 发展强大的和可移植的解决问题的技能. 了解 ...

  8. pygame简单的俄罗斯方块游戏和简单的打字游戏

    1.pygame简单的俄罗斯方块游戏 一.对战的方块管理 定义一个BlockManage管理对战的方块 根据BlockManage根据传入的玩家id返回方块,保证每个玩家拿到的方块序列是一致的,所以在 ...

  9. .net 实时通信_【WebSocket】实时多人答题对战游戏

    本文公众号来源:后端技术漫谈 作者:蛮三刀把刀 前言 前两章教程,我们使用WebSocket的基础特性打造了一个小小聊天室,并在第二章对其进行了集群化改造. 系列教程回顾: 手把手搭建WebSocke ...

  10. 快速创建精彩的Flash游戏(一) Flash2D游戏引擎简介

    原文链接:http://xiazhihui321.blog.163.com/blog/static/81328893201141851158857/ Adobe Flash自诞生之日就与游戏结下不解之 ...

最新文章

  1. win8下Python学习——搭建web.py框架
  2. python pdb 调试
  3. 计算机桌面显示保护眼睛设置,电脑屏幕如何设置最保护眼睛
  4. 加时间水印_如何在手机照片上添加时间和日期?打开这个设置即可添加,超方便...
  5. python可视化拖拽平台_python 有没有类似 VS 那种可以拖拽界面的 IDE?
  6. hashmap底层原理_周末自己动手撸一个 HashMap,美滋滋
  7. Error running ‘Unnamed‘: Unable to open debugger port (127.0.0.1:xxxx)
  8. jQuery 第三章
  9. 荣登Github日榜!微信最新开源MMKV
  10. UltraEdit文本编辑器-UE
  11. JDK8新特性Stream流使用详解
  12. 如何快速增加qq名片赞
  13. MAC 下 解决ZOC 自动断开
  14. Android如何实现音频合成
  15. 【ArnoldC4D】6.ArnoldToC4D_光泽和反射光线深度(glossy_and_reflection)
  16. Ar详细制作发布流程
  17. 手把手实现MATLAB的CNN回归
  18. qq视频转码失败怎么办_测试音视频,究竟测什么?(三)
  19. java中doc文件转为pdf文件_java将doc文件转换为pdf文件的三种方法
  20. ENVI对GF-5高光谱数据进行FLAASH大气校正

热门文章

  1. DREAMWERVER CS5序列号反复验证 解决方法
  2. [BJWC2008]王之财宝
  3. 我的世界服务器修改怪物生成,《我的世界》禁止怪物生成代码 服务器禁止怪物...
  4. 计算机用户接入最快的,行测真题_2013-2017年固定互联网宽带接入用户数的年增长速度最快的年份是...
  5. 百度冰桶算法4.5更新:发力打击恶劣广告行为
  6. 实习面试感悟-阿里云
  7. 计算机教学楼起名,给教学楼起名字(富有诗意教学楼名字)
  8. python画出送花表情图编程_python画微信表情符的实例代码
  9. 怎么取消工作组计算机,windows10系统如何退出workgroup工作组 windows10系统退出workgroup工作组的操作方法...
  10. 如何确定今天是星期几