【千锋合集】史上最全Unity3D全套教程|匠心之作_哔哩哔哩_bilibili
toggle group的添加
自己搭建UI和预设体
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UIFrame;public class LobbyFacade : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
UIManager.Instance.ShowUI("MainPanel");
UIManager.Instance.ShowUI("TopPanel");
}// Update is called once per frame
void Update()
{
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UIFrame;public class MainPanelController : UIControllerBase
{
protected override void ControllerStart()
{
base.ControllerStart();
Debug.Log("MainPanel Start!");
BindEvent();
}
protected void BindEvent()
{}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UIFrame;public class MainPanelModule : UIModuleBase
{
public override void Awake()
{
base.Awake();
//创建控制器
var controller = new MainPanelController();
//绑定控制
BindController(controller);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UIFrame;public class TopPanelController : UIControllerBase
{
protected override void ControllerStart()
{
base.ControllerStart();
Debug.Log("TopPanel Start!");
BindEvent();
}
protected void BindEvent() {}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UIFrame;public class TopPanelModule : UIModuleBase
{
public override void Awake()
{
base.Awake();
//创建控制器
var controller = new TopPanelController();
//绑定控制
BindController(controller);
}
}
--------------------------------------------------------------------------------------------------------------------------------
json文件
{
"AllData":[
{
"SceneName":"LobbyScene",
"Data": [
{ "PanelName":"TopPanel",
"PanelPath":"LobbyUIPanels/TopPanel" },
{ "PanelName":"MainPanel",
"PanelPath": "LobbyUIPanels/MainPanel" },
{"PanelName": "RoomPanel",
"PanelPath": "LobbyUIPanels/RoomPanel" },
{ "PanelName":"RoomListPanel",
"PanelPath": "LobbyUIPanels/RoomListPanel" }
]
}
]
}
所有代码汇总:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UIFrame;
public class TopPanelModule : UIModuleBase
{
public override void Awake()
{
base.Awake();
//创建控制器
var controller = new TopPanelController();
//绑定控制
BindController(controller);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollow : MonoBehaviour
{
[Header("跟随速度")]
public float moveSpeed = 3f;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (HumanGameManager.Instance.currentHero == null) {
return;
}
float Instance_x = HumanGameManager.Instance.currentHero.position.x;
float Instance_y = 15f;
float Instance_z = HumanGameManager.Instance.currentHero.position.z;
Vector3 followPosition = new Vector3(Instance_x, Instance_y, Instance_z);
transform.position = Vector3.Lerp(transform.position, followPosition,Time.deltaTime*moveSpeed);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;
using UIFrame;
using Hashtable = ExitGames.Client.Photon.Hashtable;
using ExitGames.Client.Photon;
using System;
public class GameController : MonoBehaviourPunCallbacks
{
public bool hasInit = false;
// Start is called before the first frame update
void Start()
{
//设置每秒发送包数
PhotonNetwork.SendRate = 30;
//PhotonNetwork.Instantiate(JsonDataManager.Instance.FindHeroPath(HumanGameManager.Instance.selectedHeroIndex),Vector3.zero,Quaternion.identity);
//设置玩家加载成功属性
SetPlayerLoaded();
//房主检测是否所有玩家都加载成功
//CheckAllPlayerLoaded();
//Test();
}
private void Test() {
if (!PhotonNetwork.IsMasterClient)
return;
//生产场景网络对象
PhotonNetwork.InstantiateSceneObject(JsonDataManager.Instance.FindHeroPath(0),Vector3.back,Quaternion.identity);
}
// Update is called once per frame
void Update()
{
}
/// <summary>
/// 设置当前玩家已经加载场景成功
/// </summary>
private void SetPlayerLoaded() {
Hashtable hashtable = new Hashtable();
//添加属性
hashtable.Add(GameConst.LOADED_PROPERTY,true);
//设置属性
PhotonNetwork.LocalPlayer.SetCustomProperties(hashtable);
}
/// <summary>
/// 检测所有玩家是否都已经加载场景成功
/// </summary>
private bool CheckAllPlayerLoaded() {
if (!PhotonNetwork.IsMasterClient)
return false;
for (int i = 0; i < PhotonNetwork.PlayerList.Length; i++) {
//是否加载
object isLoaded = false;
//尝试加载属性
PhotonNetwork.PlayerList[i].CustomProperties.TryGetValue(GameConst.LOADED_PROPERTY, out isLoaded);
//如果没有加载到或加载到了,值还为未加载场景成功
if (isLoaded == null || !(bool)isLoaded) {
return false;
}
}
Hashtable hashtable = new Hashtable();
//添加房间属性
hashtable.Add(GameConst.INITHERO_PROPERTY, true);
//设置房间属性
PhotonNetwork.CurrentRoom.SetCustomProperties(hashtable);
//表示所有玩家都已经加载场景成功
return true;
}
#region Photon Callbacks
public override void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged)
{
object canInit = false;
//尝试获取属性
propertiesThatChanged.TryGetValue(GameConst.INITHERO_PROPERTY,out canInit);
if (canInit == null) {
canInit = false;
}
//属性获取到,且值为True
if ((bool)canInit&&!hasInit) {
//每个玩家生成各自的英雄
InitHero();
}
}
private void InitHero()
{
//标记已经创建好了英雄
hasInit = true;
PhotonNetwork.Instantiate(JsonDataManager.Instance.FindHeroPath(HumanGameManager.Instance.selectedHeroIndex),new Vector3(PhotonNetwork.LocalPlayer.ActorNumber*3-3,0,0),Quaternion.identity);
}
public override void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps)
{
//房主检测是否所有玩家都加载成功
CheckAllPlayerLoaded();
}
#endregion
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using UIFrame;
using UnityEngine.AI;
using System;
public class HeroController : MonoBehaviourPunCallbacks,IPunObservable
{
[Header("攻击范围")]
public float attackRange = 2f;
[Header("移动速度")]
public float moveSpeed = 3f;
[Header("转身速度")]
public float turnSpeed;
//射线碰撞检测器
private RaycastHit hit;
private NavMeshAgent nav;
private Animator ani;
private PhotonAnimatorView aniView;
//导航去找英雄
private bool gotoHero = false;
//目标英雄
private PhotonView targetHero;
//攻击特效脚本
private TriggerProjectile _triggerProjectile;
private void Awake()
{
nav = GetComponent<NavMeshAgent>();
ani = GetComponent<Animator>();
aniView = GetComponent<PhotonAnimatorView>();
_triggerProjectile = GetComponent<TriggerProjectile>();
}
private void Start() {
//设置制动距离
nav.stoppingDistance = 0;
//设置移动速度
nav.speed = moveSpeed;
if (photonView.IsMine) {
//标记当前英雄
HumanGameManager.Instance.currentHero = transform;
}
}
private void Update()
{
if (!photonView.IsMine)
return;
//if (photonView.Owner == null)
//return;
CheckArrive();
HeroInput();
CheckTargetHeroInRange();
}
/// <summary>
/// 检测目标英雄是否脱离攻击范围
/// </summary>
private void CheckTargetHeroInRange() {
if (targetHero == null)
return;
//如果对方已经走远
if (Vector3.Distance(targetHero.transform.position, transform.position) > attackRange) {
//停止攻击
ani.SetBool(GameConst.PLAYERATTACK_PARA, false);
//导航去目标角色
SetHeroDestination(targetHero.transform.position);
}
}
/// <summary>
/// 检测当前英雄是否到达导航目标
/// </summary>
private void CheckArrive() {
//到达目标
if (nav.remainingDistance - nav.stoppingDistance <= 0.05f) {
ani.SetFloat(GameConst.SPEED_PARA, 0);
if (targetHero!=null)
{
//转向目标
RotateTo(targetHero.transform.position);
//攻击
ani.SetBool(GameConst.PLAYERATTACK_PARA, true);
}
else
{
//停止攻击
ani.SetBool(GameConst.PLAYERATTACK_PARA, false);
}
}
}
/// <summary>
/// 转向目标
/// </summary>
/// <param name="target"></param>
private void RotateTo(Vector3 target) {
//方向向量
Vector3 dir = target - transform.position;
//转成四元数
Quaternion targetQua = Quaternion.LookRotation(dir);
//Lerp
transform.rotation = Quaternion.Lerp(transform.rotation, targetQua, Time.deltaTime * turnSpeed);
}
/// <summary>
/// 英雄操作输入检测
/// </summary>
private void HeroInput() {
if (Input.GetButtonDown("HeroMove"))
{
//将鼠标位置转换为物理射线
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit, 100, 1 << 8 | 1 << 9))
{
//如果点击的是当前英雄
if (hit.collider.gameObject == gameObject)
return;
//设置位置
//如果点击的是地面
if (hit.collider.gameObject.layer == LayerMask.NameToLayer("Ground"))
{
nav.stoppingDistance = 0;
//标记目标丢失
targetHero = null;
//生成对象
GameObject tempParticle = Instantiate(AssetsManager.Instance.GetAsset(SystemDefine.ClickParticlePath)) as GameObject;
//设置位置
tempParticle.transform.position = hit.point;
//定时销毁
Destroy(tempParticle, 2);
}
else {
nav.stoppingDistance = attackRange;
//获取目标英雄
targetHero = hit.collider.GetComponent<PhotonView>();
//同步给其他玩家
photonView.RPC("SendTarget",RpcTarget.All,targetHero.ViewID);
}
//设置导航目标
nav.SetDestination(hit.point);
nav.velocity = Vector3.zero;
//设置导航目标
SetHeroDestination(hit.point);
}
}
}
[PunRPC]
public void SendTarget(int viewID) {
_triggerProjectile.targetPoint=PhotonView.Find(viewID).transform;
}
private void SetHeroDestination(Vector3 target) {
//设置动画参数
ani.SetFloat(GameConst.SPEED_PARA, 1.5f);
//当前玩家指向目标的方向向量
Vector3 dir=target - transform.position;
//计算夹角
float angle=Vector3.Angle(dir, transform.forward);
if (angle > 80) {
nav.velocity = Vector3.zero;
}
nav.velocity = Vector3.zero;
//设置导航目标
nav.SetDestination(target);
}
public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
{
return;
if (stream.IsWriting)
{
if (targetHero != null)
{
//写入ViewID
stream.SendNext(targetHero.ViewID);
//设置特效目标
_triggerProjectile.targetPoint = targetHero.transform;
}
}
else if(stream.IsReading)
{
try {
//读取ViewID
int viewID = (int)stream.ReceiveNext();
//通过ViewID拿到PhotonView
_triggerProjectile.targetPoint = PhotonView.Find(viewID).transform;
}
catch (Exception e)
{
Debug.LogWarning(e);
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HumanGameManager : MonoBehaviour
{
public static HumanGameManager Instance;
/// <summary>
/// 选择英雄编号
/// </summary>
public byte selectedHeroIndex = 1;
/// <summary>
/// 当前英雄
/// </summary>
public Transform currentHero;
private void Awake()
{
Instance = this;
//过渡场景时,不要销毁
DontDestroyOnLoad(gameObject);
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TriggerProjectile : MonoBehaviour
{
public GameObject projectile;
public Transform shootPoint;
public Transform targetPoint;
private GameObject magicMissile;
public float attackCostTime=1;
public float attackHeight = 12;
public GameObject hitEffect;
public void shoot() {
magicMissile = Instantiate(projectile, shootPoint.position,transform.rotation);
StartCoroutine(lerpyLoop(magicMissile));
}
//shoot loop
public IEnumerator lerpyLoop(GameObject projectileInstance) {
float progress = 0;
float timeScale = 1.0f / attackCostTime;
Vector3 origin = projectileInstance.transform.position;
if (targetPoint == null)
yield break;
while (progress < 1) {
if (projectileInstance && targetPoint) {
progress += timeScale * Time.deltaTime;
float ypos = (progress-Mathf.Pow(progress,2)) * attackHeight;
float ypos_b = ((progress+0.1f)-Mathf.Pow(progress+0.1f,2))*attackHeight;
projectileInstance.transform.position = Vector3.Lerp(origin,targetPoint.position,progress);
if (progress < 0.9f) {
projectileInstance.transform.LookAt(Vector3.Lerp(origin,targetPoint.position,progress+0.1f)+new Vector3(0,ypos_b,0));
}
yield return null;
}
}
}
public void clearProjectiles() {
if (magicMissile)
Destroy(magicMissile);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UIFrame;
using Photon.Pun;
using Photon.Realtime;
using Photon;
public class RoomPanelModule:UIModuleBase
{
//创建控制器
RoomPanelController controller;
public override void Awake()
{
base.Awake();
//创建控制器
controller = new RoomPanelController();
//绑定控制
BindController(controller);
}
/// <summary>
/// 更新玩家UI的显示
/// </summary>
public void UpdatePlayerUIMsg() {
controller.UpdatePlayerMsg();
}
//【新】
public void SetPlayerReadyStateHash(int playerID, bool isReady) {
controller.SetPlayerReadyStateHash(playerID, isReady);
}
/// <summary>
/// 设置玩家准备状态
/// </summary>
/// <param name="playerID"></param>
/// <param name="isReady"></param>
public void SetPlayerReadyState(int playerID, bool isReady) {
controller.SetPlayerReadyState(playerID,isReady);
}
public void ShowStartGameBtn() {
controller.ShowStartGameBtn();
}
public override void OnEnter()
{
base.OnEnter();
_canvasGroup.alpha = 1;
UpdatePlayerUIMsg();
}
public override void OnPause()
{
base.OnPause();
_canvasGroup.alpha = 0;
}
public override void OnResume()
{
base.OnResume();
_canvasGroup.alpha = 1;
}
public override void OnExit()
{
base.OnExit();
_canvasGroup.alpha = 0;
controller.ClearPlayerUIList();
//离开房间时,取消当前玩家的准备状态(新)
SetPlayerReadyState(PhotonNetwork.LocalPlayer.ActorNumber, false);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UIFrame;
using Photon.Pun;
using Photon.Realtime;
public class RoomListPanelModule : UIModuleBase
{
//对应的控制器
private RoomListPanelController controller;
public override void Awake()
{
base.Awake();
//创建控制器
controller = new RoomListPanelController();
//绑定控制
BindController(controller);
}
/// <summary>
/// 设置房间信息列表
/// </summary>
/// <param name="roomInfos"></param>
public void SetRoomInfos(List<RoomInfo> roomInfos) {
//设置房间信息列表
controller.UpdateRoomList(roomInfos);
}
public override void OnEnter()
{
base.OnEnter();
_canvasGroup.alpha = 1;
controller.UpdateRoomListUI();
}
public override void OnPause()
{
base.OnPause();
_canvasGroup.alpha = 0;
}
public override void OnResume()
{
base.OnResume();
_canvasGroup.alpha = 1;
if (!PhotonNetwork.InLobby) {
PhotonNetwork.JoinLobby();
}
controller.UpdateRoomListUI();
}
public override void OnExit()
{
base.OnExit();
_canvasGroup.alpha = 0;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UIFrame;
public class InfoPanelModule : UIModuleBase
{
//创建控制器
private InfoPanelController controller;
public override void Awake()
{
base.Awake();
//创建控制器
controller = new InfoPanelController();
//绑定控制
BindController(controller);
}
public override void OnEnter()
{
base.OnEnter();
_canvasGroup.alpha = 1;
controller.SetInfoText(LobbyManager.Instance.infoMessage);
}
public override void OnPause()
{
base.OnPause();
_canvasGroup.alpha = 0;
}
public override void OnResume()
{
base.OnResume();
_canvasGroup.alpha = 1;
}
public override void OnExit()
{
base.OnExit();
_canvasGroup.alpha = 0;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using UIInterface;
using TMPro;
namespace UIInterface
{
public class UIMono : MonoBehaviour, IRectTransform, IText, IImage, IRawImage, IButton, IInputField, ItmpTextPro, ITMP_InputFIeld,IGameObject
{
#region Component
private RectTransform _rectTransform;
private Text _text;
private Image _image;
private RawImage _rawImage;
private Button _button;
private InputField _inputField;
private TMP_Text _textmesh;
private TMP_InputField _tmpinputField;
#endregion
#region Mono Callback
protected virtual void Awake() {
_rectTransform = GetComponent<RectTransform>();
_text = GetComponent<Text>();
_image = GetComponent<Image>();
_rawImage = GetComponent<RawImage>();
_button = GetComponent<Button>();
_inputField = GetComponent<InputField>();
_textmesh=GetComponent<TMP_Text>();
_tmpinputField = GetComponent<TMP_InputField>();
}
#endregion
public virtual void AddOnClickListener(UnityAction action)
{
_button.onClick.AddListener(action);
}
public virtual void AddOnValueChangeListener(UnityAction<string> action)
{
_inputField.onValueChanged.AddListener(action);
}
public virtual Color GetImageColor()
{
return _image.color;
}
public virtual string GetInputFieldText()
{
return _inputField.text;
}
public virtual Sprite GetSprite()
{
return _image.sprite;
}
public virtual void SetImageColor(Color color)
{
_image.color = color;
}
public virtual void SetInputFieldText(string text)
{
_inputField.text = text;
}
public virtual void SetSprite(Sprite sprite)
{
_image.sprite = sprite;
}
public virtual void SetTextColor(Color color)
{
_text.color = color;
}
public virtual void SetTextText(string text)
{
_text.text = text;
}
public virtual string GetTextText()
{
return _text.text;
}
public void SetParent(Transform parent)
{
transform.SetParent(parent);
}
public void SetParent(Transform parent, bool stayWorldPos)
{
transform.SetParent(parent,stayWorldPos);
}
public void tmpSetTextText(string text)
{
_textmesh.text = text;
}
public string tmpGetText()
{
return _textmesh.text;
}
public void tmpSetColor(Color color)
{
_textmesh.color = color;
}
public void tmpAddOnValueChangeListener(UnityAction<string> action)
{
_tmpinputField.onValueChanged.AddListener(action);
}
public string tmpGetInputFieldText()
{
return _tmpinputField.text;
}
public void tmpSetInputFieldText(string text)
{
_tmpinputField.text = text;
}
public void SetGameObjectActive(bool active)
{
gameObject.SetActive(active);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace UIInterface {
public interface ItmpTextPro {
void tmpSetTextText(string text);
string tmpGetText();
void tmpSetColor(Color color);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.Events;
namespace UIInterface {
public interface ITMP_InputFIeld {
void tmpAddOnValueChangeListener(UnityAction<string> action);
string tmpGetInputFieldText();
void tmpSetInputFieldText(string text);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace UIInterface {
public interface IText {
void SetTextText(string text);
string GetTextText();
void SetTextColor(Color color);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace UIInterface
{
public interface IRectTransform
{
void SetParent(Transform parent);
void SetParent(Transform parent,bool stayWorldPos);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UIFrame;
public class MainPanelModule : UIModuleBase
{
public override void Awake()
{
base.Awake();
//创建控制器
var controller = new MainPanelController();
//绑定控制
BindController(controller);
}
public override void OnEnter()
{
base.OnEnter();
_canvasGroup.interactable = false;
}
public void ResumePanelInteractable() {
_canvasGroup.interactable = true;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
namespace UIInterface
{
public interface IInputField
{
void AddOnValueChangeListener(UnityAction<string> action);
string GetInputFieldText();
void SetInputFieldText(string text);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace UIInterface
{
public interface IImage
{
void SetSprite(Sprite sprite);
Sprite GetSprite();
void SetImageColor(Color color);
Color GetImageColor();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace UIInterface {
public interface IGameObject {
void SetGameObjectActive(bool active);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
namespace UIInterface
{
public interface IButton
{
void AddOnClickListener(UnityAction action);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Reflection;
using System;
namespace UIFrame {
public class Singleton<T> where T:class {
//单例对象
private static T _singleton;
//获取单例
public static T Instance {
get {
if (_singleton == null) {
//如果这样写,那么该类型T必有一个public的构造函数
//_singleton = new T();
//通过反射的方式,去实例化一个对象出来
//派生的单例类中必须要有一个私有的无参构造
_singleton=(T)Activator.CreateInstance(typeof(T), nonPublic: true);
}
return _singleton;
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UIFrame;
using System;
namespace UIFrame {
public class JsonDataManager : Singleton<JsonDataManager>
{
private JsonDataManager()
{
//Json解析【Json文件orJsonString】
//private void JsonUtilityTest<T>(string json) {
//T result=JsonUtility.FromJson<T>("json");
panelDataDic = new Dictionary<int, Dictionary<string, string>>();
widgetDataDic = new Dictionary<int, Dictionary<string, string>>();
widgetData = new JsonWidgetsModel();
heroDataDic = new Dictionary<int, Dictionary<int, string>>();
ParsePanelData();
ParseWidgetData();
ParseHeroData();
}
/// <summary>
/// 解吸英雄数据
/// </summary>
private void ParseHeroData()
{
//获取配置文本资源
TextAsset heroConfig = AssetsManager.Instance.GetAsset(SystemDefine.HeroConfigPath) as TextAsset;
//将widget的配置文件进行解析
heroData = JsonUtility.FromJson<JsonHeroModel>(heroConfig.text);
//将Widget转换为方便检索的字典
for (int i = 0; i < heroData.AllData.Length; i++)
{
//创建一个字典
Dictionary<int, string> crtDic = new Dictionary<int, string>();
//添加一个场景ID和一个字典
heroDataDic.Add(i, crtDic);
//遍历当前场景内所有Panel路径资源
for (int j = 0; j < heroData.AllData[i].Data.Length; j++)
{
//以PanelName为Key,以PanelPath为value进行存储
crtDic.Add(heroData.AllData[i].Data[j].HeroIndex, heroData.AllData[i].Data[j].HeroPath);
}
}
}
#region Json Parse
/// <summary>
/// 解析动态元件数据
/// </summary>
private void ParseWidgetData()
{
//获取配置文本资源
TextAsset widgetConfig = AssetsManager.Instance.GetAsset(SystemDefine.WidgetConfigPath) as TextAsset;
//将widget的配置文件进行解析
widgetData = JsonUtility.FromJson<JsonWidgetsModel>(widgetConfig.text);
//将Widget转换为方便检索的字典
for (int i = 0; i < widgetData.AllData.Length; i++)
{
//创建一个字典
Dictionary<string, string> crtDic = new Dictionary<string, string>();
//添加一个场景ID和一个字典
widgetDataDic.Add(i, crtDic);
//遍历当前场景内所有Panel路径资源
for (int j = 0; j < widgetData.AllData[i].Data.Length; j++)
{
//以PanelName为Key,以PanelPath为value进行存储
crtDic.Add(widgetData.AllData[i].Data[j].WidgetName, widgetData.AllData[i].Data[j].WidgetPath);
}
}
}
#endregion
#region Saved Structure
//Panel解析后的数据
JsonPanelsModel panelData;
//Panel解析后的数据【字典版】
private Dictionary<int,Dictionary<string, string>> panelDataDic;
//Widget解析后的数据
JsonWidgetsModel widgetData;
//Widget解析后的数据【字典版】
private Dictionary<int, Dictionary<string, string>> widgetDataDic;
//Hero解析后的数据
JsonHeroModel heroData;
//Hero解析后的数据【字典版】
private Dictionary<int, Dictionary<int, string>>heroDataDic;
#endregion
#region DataFind
//Json解析【Json文件orJsonString】
private void ParsePanelData() {
//获取配置文本资源
TextAsset panelConfig = AssetsManager.Instance.GetAsset(SystemDefine.PanelConfigPath) as TextAsset;
//将Panel的配置文件进行解析
panelData= JsonUtility.FromJson<JsonPanelsModel>(panelConfig.text);
//将PanelData转换为方便检索的字典
for (int i=0;i<panelData.AllData.Length;i++) {
//创建一个字典
Dictionary<string, string> crtDic = new Dictionary<string, string>();
//添加一个场景ID和一个字典
panelDataDic.Add(i,crtDic);
//遍历当前场景内所有Panel路径资源
for (int j=0;j<panelData.AllData[i].Data.Length;j++) {
//以PanelName为Key,以PanelPath为value进行存储
crtDic.Add(panelData.AllData[i].Data[j].PanelName, panelData.AllData[i].Data[j].PanelPath);
}
}
}
/// <summary>
/// 通过Panel名称返回Panel的资源路径
/// </summary>
/// <param name="panelName"></param>
/// <returns></returns>
public string FindPanelPath(string panelName, int sceneID = (int)SystemDefine.SceneID.MainScene) {
if (!panelDataDic.ContainsKey(sceneID))
return null;
if (!panelDataDic[sceneID].ContainsKey(panelName))
return null;
//如果ID和Panel在字典中都存在,则直接返回
return panelDataDic[sceneID][panelName];
}
/// <summary>
/// 通过元件名称找到其对应的路径
/// </summary>
/// <param name="panelName"></param>
/// <returns></returns>
public string FindWidgetPath(string widgetName, int sceneID = (int)SystemDefine.SceneID.MainScene)
{
if (!widgetDataDic.ContainsKey(sceneID))
return null;
if (!widgetDataDic[sceneID].ContainsKey(widgetName))
return null;
//如果ID和Widget在字典中都存在,则直接返回
return widgetDataDic[sceneID][widgetName];
}
/// <summary>
/// 通过英雄ID获取资源路径
/// </summary>
/// <param name="heroIndex"></param>
/// <param name="sceneID"></param>
/// <returns></returns>
public string FindHeroPath(int heroIndex, int sceneID = (int)SystemDefine.SceneID.MainScene)
{
if (!heroDataDic.ContainsKey(sceneID))
return null;
if (!heroDataDic[sceneID].ContainsKey(heroIndex))
return null;
//如果ID和Widget在字典中都存在,则直接返回
return heroDataDic[sceneID][heroIndex];
}
#endregion
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace UIFrame
{
public class AssetsManager : Singleton<AssetsManager>
{
//私有构造
private AssetsManager() {
assetsCache = new Dictionary<string, Object>();
}
/// <summary>
/// 资源缓存
/// </summary>
private Dictionary<string, Object> assetsCache;
/// <summary>
/// 获取资源
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="path">资源路径</param>
/// <returns></returns>
public Object OldGetAsset<T>(string path)
{
//要返回的资源
Object assetObj = null;
//如果缓存中没有该资源
if (!assetsCache.ContainsKey(path))
{
//通过resources加载资源
assetObj = Resources.Load(path);
//将资源存进缓存
assetsCache.Add(path, assetObj);
}
else {
//如果缓存中有,则直接从缓存中拿
assetObj = assetsCache[path];
}
return assetObj;
}
///新方法---获取资源
public Object GetAsset(string path) {
//要返回的资源
Object assetObj = null;
//尝试从字典中获取该路径所对应的资源
if (!assetsCache.TryGetValue(path,out assetObj))
{
//通过resources加载资源
assetObj = Resources.Load(path);
//将资源存进缓存
assetsCache.Add(path, assetObj);
}
return assetObj;
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UIFrame;
using UIInterface;
namespace UIFrame
{
public class UIWidgetBase : UIMono
{
//当前元件所处的模块
private UIModuleBase currentModule;
//临时参数
private ArrayList tempParameters;
/// <summary>
/// 设置临时参数
/// </summary>
/// <param name="para"></param>
public void SetTemParamters(object para) {
if (tempParameters == null) {
tempParameters = new ArrayList();
}
if (!tempParameters.Contains(para)) {
tempParameters.Add(para);
}
}
/// <summary>
/// 获取临时参数
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public object GetTempParamter(int index) {
return tempParameters[index];
}
public void UIWidgetInit(UIModuleBase uiModuleBase) {
//设置当前所属模块
currentModule = uiModuleBase;
//将当前元件,添加到UIManager的字典中
UIManager.Instance.addUIWidget(currentModule.name, widgetName: name, uiWidget: this);
}
protected virtual void OnDestroy()
{
将当前元件,从UIManager的字典中移除
UIManager.Instance.RemoveUIWidget(currentModule.name, widgetName: name);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UIType {
public string Name { get; set; }
public string Path { get; set; }
public UIType(string path) {
Path = path;
//eg.Panels/MainScene/MainPanel
//MainPanel
//Substring(17,3) 17以后的3个字母
//通过Path的字符串拿到其中名字
//最后一个斜杠后面的就是Path所对应的名字
Name = path.Substring(path.LastIndexOf("/")+1);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace UIFrame
{
public static class SystemDefine
{
#region Configuration Path
public const string PanelConfigPath = "Configuration/UIPanelConfig";
public const string WidgetConfigPath = "Configuration/UIWidgetConfig";
public const string HeroConfigPath = "Configuration/HeroConfig";
public const string ClickParticlePath = "Particles/Fire";
#endregion
#region Scene ID
public enum SceneID {
MainScene=0,
FightScene=1
}
#endregion
#region Widget Token
public static string[] WIDGET_TOKENS = new string[] { "_F","_S","_T"};
#endregion
#region PlayerColors
public static Color[] PLAYER_COLORS;
#endregion
#region Static Constructor
static SystemDefine() {
PLAYER_COLORS = new[] {
Color.red,
Color.blue,
Color.gray,
Color.green,
Color.cyan
};
}
#endregion
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UIFrame;
namespace UIFrame {
/// <summary>
/// 子类挂载在每一个Panel模块上
/// </summary>
/// 当前模块组件依赖于CanvasGroup
[RequireComponent(typeof(CanvasGroup))]
public class UIModuleBase : MonoBehaviour
{
protected CanvasGroup _canvasGroup;
/// <summary>
/// 所有的子对象
/// </summary>
private Transform[] allChild;
public virtual void Awake() {
_canvasGroup = GetComponent<CanvasGroup>();
//获取当前模块的所有子对象
allChild = GetComponentsInChildren<Transform>();
//修改当前模块的名称[去掉Clone]
gameObject.name = gameObject.name.Remove(gameObject.name.Length-"(Clone)".Length);
//给所有可用的UI元件添加行为
AddWidgetBehaviour();
}
#region Controller Bind
protected void BindController(UIControllerBase controllerBase) {
controllerBase.ControllerInit(this);
}
#endregion
#region Set Widgets
private void AddWidgetBehaviour() {
//遍历所有的子对象
for (int i=0;i<allChild.Length;i++) {
//遍历所有标记Token
for (int j = 0; j < SystemDefine.WIDGET_TOKENS.Length; j++) {
//判断当前元件对象是否以该标记作为名称结尾的
if (allChild[i].name.EndsWith(SystemDefine.WIDGET_TOKENS[j])) {
//添加组件
AddComponentForWidget(i);
}
}
}
}
protected virtual void AddComponentForWidget(int index) {
//给该元件添加UIWidgetBase组件
UIWidgetBase uiWidgetBase=allChild[index].gameObject.AddComponent<UIWidgetBase>();
//设置该元件的模块是this
uiWidgetBase.UIWidgetInit(uiModuleBase:this);
}
#endregion
#region Find Widget
public UIWidgetBase FindCurrentModuleWidget(string widgetName) {
return UIManager.Instance.FindWidget(moduleName:name,widgetName:widgetName);
}
#endregion
/// <summary>
/// 进入当前模块执行该函数
/// </summary>
public virtual void OnEnter() {
_canvasGroup.blocksRaycasts = true;
//当前窗口在Canvas中的最后一个位置,保证显示最前面
transform.SetSiblingIndex(transform.parent.childCount-1);
}
/// <summary>
/// 离开当前模块执行该函数
/// </summary>
public virtual void OnExit() {
_canvasGroup.blocksRaycasts = false;
}
/// <summary>
/// 暂离当前模块执行该函数
/// </summary>
public virtual void OnPause() {
_canvasGroup.blocksRaycasts = false;
}
/// <summary>
/// 恢复当前模块执行该函数
/// </summary>
public virtual void OnResume() {
_canvasGroup.blocksRaycasts = true;
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UIFrame;
namespace UIFrame
{
/// <summary>
/// 专注于写UI中的业务逻辑
/// </summary>
public class UIControllerBase
{
//当前所处模块
public UIModuleBase crtModule;
public void ControllerInit(UIModuleBase moduleBase) {
crtModule = moduleBase;
//启动
ControllerStart();
}
protected virtual void ControllerStart() {
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace UIFrame {
[System.Serializable]
public class JsonWidgetsModel{
public SceneWidgetDataModel[] AllData;
}
[System.Serializable]
public class SceneWidgetDataModel {
public string SceneName;
public WidgetDataModel[] Data;
}
[System.Serializable]
public class WidgetDataModel {
public string WidgetName;
public string WidgetPath;
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace UIFrame {
[System.Serializable]
public class JsonPanelsModel{
public SceneDataModel[] AllData;
public static implicit operator JsonPanelsModel(JsonWidgetsModel v)
{
throw new NotImplementedException();
}
}
[System.Serializable]
public class SceneDataModel {
public string SceneName;
public PanelDataModel[] Data;
}
[System.Serializable]
public class PanelDataModel {
public string PanelName;
public string PanelPath;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace UIFrame
{
[System.Serializable]
public class JsonHeroModel
{
public SceneHeroDataModel[] AllData;
}
[System.Serializable]
public class SceneHeroDataModel
{
public string SceneName;
public HeroDataModel[] Data;
}
[System.Serializable]
public class HeroDataModel
{
public int HeroIndex;
public string HeroPath;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UIFrame;
namespace UIFrame
{
public class UITypeManager : Singleton<UITypeManager>
{
private UITypeManager() {
_uiTypes = new Dictionary<string, UIType>();
}
//UIType的缓冲池
private Dictionary<string, UIType> _uiTypes;
/// <summary>
/// 通过UIPanelName名称,获取其UIType
/// </summary>
/// <param name="uiPanelName"></param>
public UIType GetUIType(string uiPanelName) {
//要返回的UITYPE
UIType uiType = null;
//如果缓存池内没有该Key
if (!_uiTypes.TryGetValue(uiPanelName, out uiType)) {
//实例化一个新的UIType
uiType = new UIType(
JsonDataManager.Instance.FindPanelPath(uiPanelName)
);
//添加到字典
_uiTypes.Add(uiPanelName,uiType);
}
return uiType;
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UIFrame;
namespace UIFrame {
public class UIManager:Singleton<UIManager> {
private UIManager() {
uiModuleList = new List<UIModuleBase>();
uiModules = new Dictionary<UIType, UIModuleBase>();
_canvas = GameObject.Find("Canvas").transform;
uiModuleStack = new Stack<UIModuleBase>();
uiWidgets=new Dictionary<string, Dictionary<string, UIWidgetBase>>();
}
//UI模块的栈存储
private Stack<UIModuleBase> uiModuleStack;
//UIType.Path--->GameObject里的UIModule组件
//管理当前场景的所有UI模块
private Dictionary<UIType, UIModuleBase> uiModules;
//管理当前场景的所有UI元件
private Dictionary<string,Dictionary<string,UIWidgetBase>> uiWidgets;
//当前场景中的画布
private Transform _canvas;
//UI模块的列表存储
private List<UIModuleBase> uiModuleList;
#region UI Module GameObject
/// <summary>
/// 通过名字去获取模块
/// </summary>
/// <param name="uiPanelName"></param>
/// <returns></returns>
public UIModuleBase GetUIModuleByName(string uiPanelName) {
//获取UIType
UIType _uiType = UITypeManager.Instance.GetUIType(uiPanelName);
//获取UIModuleBase
return GetUIModule(_uiType);
}
/// <summary>
/// 通过UIType获取该Type所对应的模块游戏对象身上的UIModuleBase
/// </summary>
/// <param name="uiType"></param>
/// <returns></returns>
private UIModuleBase GetUIModule(UIType uiType) {
//当前要返回的模块
UIModuleBase crtModule = null;
//如果字典中没有该模块
if (!uiModules.TryGetValue(uiType, out crtModule))
{
//Instantiate生成该模块
crtModule= InstantiateUIModule(prefab: AssetsManager.Instance.GetAsset(uiType.Path) as GameObject);
//将该模块添加到字典中
uiModules.Add(uiType,crtModule);
}
else if(uiModules[uiType]==null) {
//Instantiate生成该模块
crtModule = InstantiateUIModule(prefab: AssetsManager.Instance.GetAsset(uiType.Path) as GameObject);
//将该模块更新到字典中
uiModules[uiType]=crtModule;
}
return crtModule;
}
private UIModuleBase InstantiateUIModule(GameObject prefab) {
//生成当前模块
GameObject crtModuleObj=GameObject.Instantiate(prefab);
//设置父物体为画布
crtModuleObj.transform.SetParent(_canvas, worldPositionStays: false);
//等价于crtModuleObj.transform.localPosition = Vector3.zero;
//返回组件
return crtModuleObj.GetComponent<UIModuleBase>();
}
#endregion
/// <summary>
/// 通过PanelName获取模块对象并压栈
/// </summary>
/// <param name="uiPanelName"></param>
#region UI Module Stack
public void PushUI(string uiPanelName) {
//获取UIType
UIType _uiType=UITypeManager.Instance.GetUIType(uiPanelName);
//获取UIModuleBase
UIModuleBase crtModuleBase=GetUIModule(_uiType);
//如果栈里面有元素
if (uiModuleStack.Count!=0) {
//此时栈顶的窗口进入暂停状态
uiModuleStack.Peek().OnPause();
}
//进入窗口压栈
uiModuleStack.Push(crtModuleBase);
//新窗口执行Enter
crtModuleBase.OnEnter();
}
/// <summary>
/// 栈顶元素出栈
/// </summary>
public void PopUI() {
if (uiModuleStack.Count != 0)
{
//当前栈顶元素出栈,并执行离开的回调方法
uiModuleStack.Pop().OnExit();
}
else {
Debug.LogWarning(message:"UI栈中没有元素,无法出栈!");
}
//栈顶元素出栈后,栈内还有没有元素
if (uiModuleStack.Count!=0) {
uiModuleStack.Peek().OnResume();
}
}
#endregion
#region UI Module list
public void ShowUI(string uiPanelName)
{
//获取UIType
UIType _uiType = UITypeManager.Instance.GetUIType(uiPanelName);
//获取UIModuleBase
UIModuleBase crtModuleBase = GetUIModule(_uiType);
if (!uiModuleList.Contains(crtModuleBase)) {
//添加到列表
uiModuleList.Add(crtModuleBase);
}
//新窗口执行Enter
crtModuleBase.OnEnter();
}
#endregion
/// <summary>
/// 注册UI模块
/// </summary>
/// <param name="moduleName">模块名称</param>
#region UI Widgets->Module (Un)Register
private void RegisterUIModuleToUIWidgets(string moduleName) {
if (!uiWidgets.ContainsKey(moduleName))
{
//向字典添加元素
uiWidgets.Add(moduleName, new Dictionary<string, UIWidgetBase>());
}
else {
//Debug.Log(message:"该模块已经存在!");
}
}
/// <summary>
/// 取消注册UI模块
/// </summary>
/// <param name="moduleName"></param>
public void UnRegisterUiModuleFromUIWidgets(string moduleName) {
if (uiWidgets.ContainsKey(moduleName))
{
//从字典中移除该元素
uiWidgets.Remove(moduleName);
}
else {
Debug.LogWarning(message:"无法取消注册该模块,因为无该模块。");
}
}
#endregion
#region UI Widgets Add/Remove
/// <summary>
/// 添加元件
/// </summary>
/// <param name="moduleName">模块名称</param>
/// <param name="widgetName">元件名称</param>
/// <param name="uiWidgetBase">元件对象</param>
public void addUIWidget(string moduleName,string widgetName,UIWidgetBase uiWidget) {
//如果模块不存在,添加模块
RegisterUIModuleToUIWidgets(moduleName);
//如果字典中已经存在该元件
if (uiWidgets[moduleName].ContainsKey(widgetName))
{
Debug.LogWarning(message: "该元件已经再字典中存在,无需再添加...");
}
else {
uiWidgets[moduleName].Add(widgetName,uiWidget);
}
}
/// <summary>
/// 移除元件
/// </summary>
/// <param name="moduleName">模块名称</param>
/// <param name="widgetName">元件名称</param>
public void RemoveUIWidget(string moduleName,string widgetName) {
if (uiWidgets[moduleName].ContainsKey(widgetName))
{
//移除该元件
uiWidgets[moduleName].Remove(widgetName);
}
else {
Debug.LogWarning(message:"该元件在字典中不存在...");
}
}
#endregion
/// <summary>
/// 获取某个模块的某个元件
/// </summary>
/// <param name="moduleName">模块</param>
/// <param name="widgetName">元件</param>
/// <returns></returns>
#region Find Widget
public UIWidgetBase FindWidget(string moduleName,string widgetName) {
//如果模块不存在,注册模块
RegisterUIModuleToUIWidgets(moduleName);
//要返回的UIModle
UIWidgetBase uiWidget =null;
//尝试获取该元件,如果没有获取到,返回Null
uiWidgets[moduleName].TryGetValue(widgetName, out uiWidget);
return uiWidget;
}
#endregion
#region Dynamic Widget Instantiate
public GameObject CreateDynamicWidget(string widgetName) {
//获取元件的资源路径
string widgetPath=JsonDataManager.Instance.FindWidgetPath(widgetName);
//获取预设体
GameObject prefab=AssetsManager.Instance.GetAsset(widgetPath) as GameObject;
//创建对象
return GameObject.Instantiate(prefab);
}
/// <summary>
/// 创建动态元件,并设置父物体
/// </summary>
/// <param name="widgetName"></param>
/// <param name="parent"></param>
/// <param name="worldPosStays"></param>
/// <returns></returns>
public GameObject CreateDynamicWidget(string widgetName,Transform parent, bool worldPosStays) {
//创建对象
GameObject obj=CreateDynamicWidget(widgetName);
//Debug.Log("CreateDynamicWidget"+obj);
//设置父物体
obj.transform.SetParent(parent,worldPosStays);
return obj;
}
#endregion
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UIFrame;
public class GameFacade : MonoBehaviour {
private void Start()
{
//启动游戏
UIManager.Instance.PushUI("MainPanel");
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UIFrame;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine.UI;
public class TopPanelController : UIControllerBase
{
protected override void ControllerStart()
{
base.ControllerStart();
Debug.Log("TopPanel Start!");
BindEvent();
}
protected void BindEvent() {
//crtModule
crtModule.FindCurrentModuleWidget("BackButton_F").AddOnClickListener(()=> {
//离开房间和大厅
if (PhotonNetwork.InLobby)
{
PhotonNetwork.LeaveLobby();
}
else if (PhotonNetwork.InRoom) {
PhotonNetwork.LeaveRoom();
}
//暂时
UIManager.Instance.PopUI();
UIManager.Instance.PopUI();
});
Debug.Log(PhotonNetwork.NetworkClientState);
MonoHelper.Instance.InvokeRepeat(method:()=> { crtModule.FindCurrentModuleWidget("StatusInfo_F").SetTextText("Status: " + PhotonNetwork.NetworkClientState); },0,()=> { return false; });
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UIFrame;
using Photon.Pun;
using Photon.Realtime;
public class RoomPanelController : UIControllerBase
{
/// <summary>
/// 当前房间的所有玩家
/// </summary>
Dictionary<int, GameObject> roomPlayers;
protected override void ControllerStart()
{
base.ControllerStart();
roomPlayers = new Dictionary<int, GameObject>();
crtModule.FindCurrentModuleWidget("StartGameButton_F").AddOnClickListener(() =>
{
//加载进入游戏场景
PhotonNetwork.LoadLevel("CompleteMainScene");
}
);
}
private void BindEvent() {
}
/// <summary>
/// 清空玩家列表
/// </summary>
public void ClearPlayerUIList() {
foreach (var item in roomPlayers) {
//销毁游戏对象
GameObject.Destroy(item.Value);
}
//清理
roomPlayers.Clear();
}
private void GeneratePlayerUIList() {
Transform parent = crtModule.FindCurrentModuleWidget("PlayerList_F").transform;
for (int i = 0; i < PhotonNetwork.PlayerList.Length; i++) {
//生成一个玩家
GameObject tempPlayer=UIManager.Instance.CreateDynamicWidget("PlayerInfo",parent,false);
//执行玩家初始化
tempPlayer.GetComponent<PlayerBehaviour>().PlayerInit(PhotonNetwork.PlayerList[i]);
//添加到字典
roomPlayers.Add(PhotonNetwork.PlayerList[i].ActorNumber, tempPlayer);
}
}
//更新玩家信息
public void UpdatePlayerMsg() {
ClearPlayerUIList();
GeneratePlayerUIList();
}
/// <summary>
/// 设置玩家准备状态
/// </summary>
/// <param name="playerID"></param>
/// <param name="isReady"></param>
public void SetPlayerReadyState(int playerID,bool isReady) {
if (!roomPlayers.ContainsKey(playerID))
return;
roomPlayers[playerID].GetComponent<PlayerBehaviour>().SetReadyStateUI(isReady);
}
//新
public void SetPlayerReadyStateHash(int playerID, bool isReady) {
if (!roomPlayers.ContainsKey(playerID))
return;
roomPlayers[playerID].GetComponent<PlayerBehaviour>().SetPlayerReadyState(isReady);
}
/// <summary>
/// 显示游戏开始按钮
/// </summary>
public void ShowStartGameBtn() {
//1.当前玩家是主客户端
//2:房间里的所有玩家都已经准备
crtModule.FindCurrentModuleWidget("StartGameButton_F").SetGameObjectActive(PhotonNetwork.IsMasterClient&&AllPlayerHasReady());
}
/// <summary>
/// 是否所有玩家都已经准备
/// </summary>
/// <returns></returns>
private bool AllPlayerHasReady() {
foreach (var item in roomPlayers) {
//如果遍历到任意一个玩家没有准备,则不能开始游戏
if (!item.Value.GetComponent<PlayerBehaviour>().isReady) {
return false;
}
}
//能运行到此处,说明所有玩家都已经准备
return true;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using UIFrame;
using Photon.Realtime;
public class RoomListPanelController : UIControllerBase
{
//房间信息
public List<RoomInfo> roomInfos;
//所有的房间
Dictionary<string, RoomBehaviour> rooms;
protected override void ControllerStart()
{
base.ControllerStart();
roomInfos = new List<RoomInfo>();
rooms = new Dictionary<string, RoomBehaviour>();
}
public void UpdateRoomList(List<RoomInfo> roomInfos) {
this.roomInfos = roomInfos;
UpdateRoomListUI();
}
void ClearRoomListUI() {
foreach (var item in rooms) {
//销毁房间信息的游戏对象
GameObject.Destroy(item.Value.gameObject);
}
//清除
rooms.Clear();
}
private void ShowRoomListUI() {
//找到父对象
Transform parent = crtModule.FindCurrentModuleWidget("RoomList_F").transform;
//遍历RoomInfos
foreach (var item in roomInfos) {
if (!item.IsOpen)
continue;
if (!item.IsVisible)
continue;
if (item.MaxPlayers == 0)
continue;
//生成一个房间
GameObject tempRoom = UIManager.Instance.CreateDynamicWidget("RoomInfo", parent, false);
//执行房间初始化
tempRoom.GetComponent<RoomBehaviour>().RoomInit(item);
//添加到字典
rooms.Add(item.Name, tempRoom.GetComponent<RoomBehaviour>());
}
}
public void UpdateRoomListUI() {
ClearRoomListUI();
ShowRoomListUI();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UIFrame;
public class InfoPanelController : UIControllerBase
{
protected override void ControllerStart()
{
base.ControllerStart();
crtModule.FindCurrentModuleWidget("CancelButton_F").AddOnClickListener(()=> { UIManager.Instance.PopUI(); });
BindEvent();
}
private void BindEvent()
{
}
public void SetInfoText(string text) {
crtModule.FindCurrentModuleWidget("Text _F").tmpSetTextText(text);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using UnityEngine.UI;
public class RoomBehaviour : MonoBehaviour
{
private RoomInfo _roomInfo;
#region UI Field
private TMP_Text roomNameText;
private TMP_Text slotsText;
private Button joinButton;
#endregion
private void Awake()
{
roomNameText = transform.GetChild(0).GetComponent<TMP_Text>();
slotsText = transform.GetChild(1).GetComponent<TMP_Text>();
joinButton = transform.GetChild(2).GetComponent<Button>();
}
public void RoomInit(RoomInfo roomInfo)
{
_roomInfo = roomInfo;
roomNameText.text = roomInfo.Name;
joinButton.onClick.AddListener(
() => {
//离开大厅
PhotonNetwork.LeaveLobby();
//进入房间
PhotonNetwork.JoinRoom(roomInfo.Name);
}
);
}
private void Update()
{
slotsText.text = _roomInfo.PlayerCount + "/" + _roomInfo.MaxPlayers;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine.UI;
using UIFrame;
using TMPro;
using UIInterface;
using UnityEngine.Events;
using ExitGames.Client.Photon;
namespace UIFrame
{
public class PlayerBehaviour : MonoBehaviour, IButton
{
//当前玩家
private Player _player;
#region UI Field
private Image color;
private TMP_Text playerName;
private Button readyButton;
private Button notReadyButton;
private GameObject hasReadySign;
#endregion
//当前玩家是否准备
public bool isReady = false;
private void Awake()
{
color = transform.Find("Color").GetComponent<Image>();
playerName = transform.Find("PlayerName").GetComponent<TMP_Text>();
readyButton = transform.Find("ReadyButton").GetComponent<Button>();
//标记玩家是否已经准备
hasReadySign = readyButton.transform.Find("isReadySign").gameObject;
notReadyButton = transform.Find("NonReadyButton").GetComponent<Button>();
//绑定点击事件
readyButton.onClick.AddListener(OnReadyButtonClick);
}
private void OnReadyButtonClick()
{
if (!_player.IsLocal)
return;
bool crtReadyState = GetPlayerReadyState();
//设置当前玩家准备状态【新】
SetPlayerReadyState(!crtReadyState);
}
/// <summary>
/// 设置当前玩家准备状态【新】
/// </summary>
/// <param name="isReady"></param>
public void SetPlayerReadyState(bool isReady)
{
ExitGames.Client.Photon.Hashtable hashtable = new ExitGames.Client.Photon.Hashtable();
hashtable.Add(GameConst.READY_PROPERTY, isReady);
//设置
_player.SetCustomProperties(hashtable);
//触发自己的UI变化
SetReadyStateUI(isReady);
//readyButton.gameObject.SetActive(!isReady);
// notReadyButton.gameObject.SetActive(isReady);
}
/// <summary>
/// 玩家初始化
/// </summary>
/// <param name="player"></param>
public void PlayerInit(Player player)
{
_player = player;
playerName.text = player.NickName;
//设置玩家编号所对应的颜色显示
color.color = GameConst.PLAYER_COLORS[(player.ActorNumber - 1) % GameConst.PLAYER_COLORS.Length];
if (player.IsLocal)
{
readyButton.gameObject.SetActive(true);
notReadyButton.gameObject.SetActive(false);
}
else
{
readyButton.gameObject.SetActive(false);
notReadyButton.gameObject.SetActive(true);
}
//关于准备状态
SetReadyStateUI((GetPlayerReadyState()));
}
public void AddOnClickListener(UnityAction action)
{
throw new System.NotImplementedException();
}
/// <summary>
/// 获取玩家的准备状态
/// </summary>
/// <returns></returns>
private bool GetPlayerReadyState()
{
//结果
object result = null;
//尝试获取准备属性
_player.CustomProperties.TryGetValue(GameConst.READY_PROPERTY, out result);
if (result == null)
return false;
return (bool)result;
}
/// <summary>
/// 设置当前玩家的准备状态UI
/// </summary>
public void SetReadyStateUI(bool isReady)
{
this.isReady = isReady;
hasReadySign.SetActive(isReady);
//如果玩家不是“自己”,准备按钮要看准备的状态
if (!_player.IsLocal)
{
readyButton.gameObject.SetActive(isReady);
readyButton.interactable = false;
notReadyButton.gameObject.SetActive(!isReady);
}
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
public class MonoHelper : MonoBehaviour
{
public static MonoHelper Instance;
private void Awake()
{
Instance = this;
}
/// <summary>
/// 持续执行某个函数
/// </summary>
/// <param name="method"></param>
/// <param name="interval"></param>
/// <param name="endCondition"></param>
public void InvokeRepeat(Action method,float interval,Func<bool> endCondition) {
StartCoroutine(RepeatCRT(method, interval, endCondition));
}
IEnumerator RepeatCRT(Action method, float interval, Func<bool> endCondition) {
while (true) {
if (interval <= 0) { yield return 0; }
else { yield return new WaitForSeconds(interval); }
//执行事件
method();
//判断结束条件是否达成
if (endCondition())
yield break;
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using UIFrame;
using Photon.Realtime;
using ExitGames.Client.Photon;
public class LobbyManager : MonoBehaviourPunCallbacks
{
public static LobbyManager Instance;
public string infoMessage="";
//获取房间模块
//private RoomPanelModule roomPanel;
//获取大厅模块
private RoomListPanelModule roomListPannel;
private void Awake()
{
Instance = this;
//设置为当前对象在过渡场景时不要销毁
//DontDestroyOnLoad(gameObject);
//支持后台运行
Application.runInBackground = true;
//机制网络场景同步
PhotonNetwork.AutomaticallySyncScene = true;
//实例化房间列表
//rooms = new List<RoomInfo>();
}
// Start is called before the first frame update
void Start()
{
//连接云服务器
PhotonNetwork.ConnectUsingSettings();
//roomPanel = UIManager.Instance.GetUIModuleByName("RoomPanel") as RoomPanelModule;
//roomListPannel = UIManager.Instance.GetUIModuleByName("RoomListPanel") as RoomListPanelModule;
}
public override void OnConnectedToMaster()
{
base.OnConnectedToMaster();
//恢复主模块的可交互性
MainPanelModule mainPanel =UIManager.Instance.GetUIModuleByName("MainPanel") as MainPanelModule;
mainPanel.ResumePanelInteractable();
}
public override void OnJoinedRoom()
{
//进入房间界面
UIManager.Instance.PushUI("RoomPanel");
//roomPanel.SetPlayerReadyState(PhotonNetwork.LocalPlayer.ActorNumber, false);【旧】
//更新房间时,取消当前玩家的准备状态[新]
RoomPanelModule roomPanel = UIManager.Instance.GetUIModuleByName("RoomPanel") as RoomPanelModule;
roomPanel.SetPlayerReadyStateHash(PhotonNetwork.LocalPlayer.ActorNumber, false);
}
public override void OnJoinRandomFailed(short returnCode, string message)
{
//储存失败原因信息
infoMessage =message;
//显示提示框
UIManager.Instance.PushUI("InfoPanel");
}
public override void OnJoinedLobby()
{
base.OnJoinedLobby();
//进入大厅界面
UIManager.Instance.PushUI("RoomListPanel");
}
public override void OnPlayerEnteredRoom(Player newPlayer)
{
base.OnPlayerEnteredRoom(newPlayer);
RoomPanelModule roomPanel = UIManager.Instance.GetUIModuleByName("RoomPanel") as RoomPanelModule;
//更新玩家列表
roomPanel.UpdatePlayerUIMsg();
//设置是否显示启动游戏按钮
roomPanel.ShowStartGameBtn();
}
public override void OnPlayerLeftRoom(Player otherPlayer)
{
base.OnPlayerLeftRoom(otherPlayer);
RoomPanelModule roomPanel = UIManager.Instance.GetUIModuleByName("RoomPanel") as RoomPanelModule;
//更新玩家列表
roomPanel.UpdatePlayerUIMsg();
//设置是否显示启动游戏按钮
roomPanel.ShowStartGameBtn();
}
public override void OnCreateRoomFailed(short returnCode, string message)
{
//储存失败原因信息
infoMessage = message;
//显示提示框
UIManager.Instance.PushUI("InfoPanel");
}
public override void OnPlayerPropertiesUpdate(Player targetPlayer, ExitGames.Client.Photon.Hashtable changedProps)
{
object result = null;
//获取准备状态
changedProps.TryGetValue(GameConst.READY_PROPERTY, out result);
if (result == null) {
result = false;
}
RoomPanelModule roomPanel = UIManager.Instance.GetUIModuleByName("RoomPanel") as RoomPanelModule;
//调用房间模块方法
roomPanel.SetPlayerReadyState(targetPlayer.ActorNumber,(bool)result);
//设置是否显示启动游戏按钮
roomPanel.ShowStartGameBtn();
}
public override void OnRoomListUpdate(List<RoomInfo> roomList)
{
base.OnRoomListUpdate(roomList);
roomListPannel = UIManager.Instance.GetUIModuleByName("RoomListPanel") as RoomListPanelModule;
//临时存储当前的所有房间信息
roomListPannel.SetRoomInfos(roomList);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UIFrame;
using Photon.Pun;
using Photon.Realtime;
using Photon;
using UnityEngine.Events;
using Hashtable = ExitGames.Client.Photon.Hashtable;
public class MainPanelController : UIControllerBase
{
protected override void ControllerStart()
{
base.ControllerStart();
Debug.Log("MainPanel Start!");
BindEvent();
BaseMsgInit();
}
private void BaseMsgInit() {
//随机玩家昵称
crtModule.FindCurrentModuleWidget("PlayerNameInputField_F").tmpSetInputFieldText("Player"+Random.Range(101,999));
//随机房间名称
crtModule.FindCurrentModuleWidget("RoomNameInputField_F").tmpSetInputFieldText("Room" + Random.Range(101, 999));
//设置默认的最大人数
crtModule.FindCurrentModuleWidget("RoomMaxCountInputFIeld_F").tmpSetInputFieldText("5");
}
protected void BindEvent()
{
//Hero点击事件绑定
crtModule.FindCurrentModuleWidget("Hero01Button_F").AddOnClickListener(()=> {
//父物体
Transform parent = crtModule.FindCurrentModuleWidget("Hero01Button_F").transform;
//设置选择框到当前模块
crtModule.FindCurrentModuleWidget("Select_F").SetParent(parent, false);
//标记当前选择英雄的编号
HumanGameManager.Instance.selectedHeroIndex = 1;
});
//Hero点击事件绑定
crtModule.FindCurrentModuleWidget("Hero02Button_F").AddOnClickListener(() => {
//父物体
Transform parent = crtModule.FindCurrentModuleWidget("Hero02Button_F").transform;
//设置选择框到当前模块
crtModule.FindCurrentModuleWidget("Select_F").SetParent(parent, false);
//标记当前选择英雄的编号
HumanGameManager.Instance.selectedHeroIndex = 2;
});
//Hero点击事件绑定
crtModule.FindCurrentModuleWidget("Hero03Button_F").AddOnClickListener(() => {
//父物体
Transform parent = crtModule.FindCurrentModuleWidget("Hero03Button_F").transform;
//设置选择框到当前模块
crtModule.FindCurrentModuleWidget("Select_F").SetParent(parent, false);
//标记当前选择英雄的编号
HumanGameManager.Instance.selectedHeroIndex = 3;
});
//绑定创建房间按钮事件CreateButton_F
crtModule.FindCurrentModuleWidget("CreateButton_F").AddOnClickListener(CreateRoomBtnClick);
//crtModule.FindCurrentModuleWidget("CreateButton_F").AddOnClickListener(test);
//随机加入房间按钮事件CreateButton_F
crtModule.FindCurrentModuleWidget("RandomRoomButton_F").AddOnClickListener(JoinRandomRoom);
//绑定进入游戏大厅按钮事件CreateButton_F
crtModule.FindCurrentModuleWidget("ListServerButton_F").AddOnClickListener(JoinLobby);
}
private void test() {
string playerName = crtModule.FindCurrentModuleWidget("PlayerNameInputField_F").tmpGetInputFieldText();
Debug.Log("Player" + Random.Range(101, 999));
}
private void CreateRoomBtnClick() {
//已经进入房间,不能再创建房间
if (PhotonNetwork.NetworkClientState == ClientState.Joined)
return;
string playerName= crtModule.FindCurrentModuleWidget("PlayerNameInputField_F").tmpGetInputFieldText();
string roomName = crtModule.FindCurrentModuleWidget("RoomNameInputField_F").tmpGetInputFieldText();
string roomPwd = crtModule.FindCurrentModuleWidget("RoomPasswordInputField_F").tmpGetInputFieldText();
string roomMaxCount = crtModule.FindCurrentModuleWidget("RoomMaxCountInputFIeld_F").tmpGetInputFieldText();
if (playerName == "") {
playerName = "Player" + Random.Range(101, 999);
}
if (roomName == "")
{
roomName = "Room" + Random.Range(101, 999);
}
if (roomMaxCount == "")
{
roomMaxCount = "5";
}
//设置玩家昵称
PhotonNetwork.NickName = playerName;
//Debug.Log(PhotonNetwork.NickName);
//创建房间选项对象
RoomOptions roomOptions = new RoomOptions();
//设置最大人数
roomOptions.MaxPlayers = byte.Parse(roomMaxCount);
if (roomPwd != "") {
//添加房间密码
//如果hashtable为空
if (roomOptions.CustomRoomProperties == null) {
//实例化
roomOptions.CustomRoomProperties = new Hashtable();
}
roomOptions.CustomRoomProperties.Add("Password", roomPwd);
}
//创建房间
PhotonNetwork.CreateRoom(roomName, roomOptions);
}
private void JoinRandomRoom() {
//已经进入房间,不能再创建房间
if (PhotonNetwork.NetworkClientState == ClientState.Joined)
return;
string playerName = crtModule.FindCurrentModuleWidget("PlayerNameInputField_F").tmpGetInputFieldText();
if (playerName == "")
{
playerName = "Player" + Random.Range(101, 999);
}
//设置玩家昵称
PhotonNetwork.NickName = playerName;
//随机加入房间
PhotonNetwork.JoinRandomRoom();
}
private void JoinLobby() {
string playerName = crtModule.FindCurrentModuleWidget("PlayerNameInputField_F").tmpGetInputFieldText();
if (playerName == "")
{
playerName = "Player" + Random.Range(101, 999);
}
PhotonNetwork.NickName = playerName;
if (!PhotonNetwork.InLobby)
//加入大厅
PhotonNetwork.JoinLobby();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UIFrame;
public class LobbyFacade : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
UIManager.Instance.ShowUI("TopPanel");
UIManager.Instance.ShowUI("MainPanel");
}
// Update is called once per frame
void Update()
{
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public static class GameConst
{
#region Player Custom Properties
public const string READY_PROPERTY = "Ready";
public const string LOADED_PROPERTY = "Loaded";
#endregion
#region Room Custom Properties
public const string INITHERO_PROPERTY = "InitHero";
#endregion
#region PlayerColors
public static Color[] PLAYER_COLORS;
#endregion
#region Virtual Axis & Button
public const string HEROMOVE = "HeroMove";
#endregion
#region Animator Paramters
public static int SPEED_PARA;
public static int PLAYERATTACK_PARA;
#endregion
#region Custom Properties
static GameConst()
{
PLAYER_COLORS = new[] {
Color.red,
Color.blue,
Color.gray,
Color.green,
Color.cyan
};
SPEED_PARA = Animator.StringToHash("Speed");
PLAYERATTACK_PARA = Animator.StringToHash("PlayerAttack");
}
#endregion
}
{
"AllData":[
{
"SceneName":"HeroScene",
"Data": [
{ "HeroIndex":1,
"HeroPath":"PlayerPrefabs/char_ethan" },
{ "HeroIndex":2,
"HeroPath": "PlayerPrefabs/char_robotGuard" },
{ "HeroIndex":3,
"HeroPath": "PlayerPrefabs/dragon" }
]
}
]
}
{
"AllData":[
{
"SceneName":"LobbyScene",
"Data": [
{ "PanelName":"TopPanel",
"PanelPath":"LobbyUIPanels/TopPanel" },
{ "PanelName":"MainPanel",
"PanelPath": "LobbyUIPanels/MainPanel" },
{"PanelName": "RoomPanel",
"PanelPath": "LobbyUIPanels/RoomPanel" },
{ "PanelName":"RoomListPanel",
"PanelPath": "LobbyUIPanels/RoomListPanel" },
{ "PanelName":"InfoPanel",
"PanelPath": "LobbyUIPanels/InfoPanel" }
]
}
]
}
{
"AllData":[
{
"SceneName":"LobbyScene",
"Data": [
{ "WidgetName":"RoomInfo",
"WidgetPath":"LobbyPrefabs/RoomInfo" },
{ "WidgetName":"PlayerInfo",
"WidgetPath": "LobbyPrefabs/PlayerInfo" }
]
}
]
}