unity网络游戏开发

【千锋合集】史上最全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++)

                {

                    //PanelNameKey,以PanelPathvalue进行存储

                    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++)

                {

                    //PanelNameKey,以PanelPathvalue进行存储

                    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++) {

                    //PanelNameKey,以PanelPathvalue进行存储

                    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;

            //如果IDPanel在字典中都存在,则直接返回

            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;

            //如果IDWidget在字典中都存在,则直接返回

            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;

            //如果IDWidget在字典中都存在,则直接返回

            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" }   

         ]

         }

  ]

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/62073.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

3D游戏开发套件指南(入门篇,转自Unity官方平台公众号)

原文地址: https://mp.weixin.qq.com/s?__bizMzU5MjQ1NTEwOA&mid2247493655&idx1&sn090dd09b2e3845e35fdf97be4e71ce6e&chksmfe1ddcbcc96a55aa1581dfdb23831d24eb4b0c64795c5bcb92eea5faa25ebe32d97bed803cba&mpshare1&scene1&srcid07102tXxX6HN…

【Unity】Unity 2D游戏开发(三)2D游戏常用功能及插件

377节附近开始的2D游戏实例&#xff0c;基础的功能开发可以参考。 碰撞忽略 private void Start() {// 让第八层和第九层忽略碰撞&#xff0c;此段代码可以写在通用脚本内Physics2D.IgnoreLayerCollision(8, 9); }Easy Touch插件 可以用来做摇杆&#xff0c;功能简单&#x…

Unity3D ——强大的跨平台3D游戏开发工具(一)

众所周知&#xff0c;Unity3D是一个能够实现轻松创作的多平台的游戏开发工具&#xff0c;是一个全面整合的专业游戏引擎。在现有的版本中&#xff0c;其强大的游戏制作功能已经达到让人瞠目结舌的地步。尤其是它在3.0版本里面制作的那款第一人称战争游戏&#xff0c;画质效果丝…

现有Unity转微信小游戏

关于微信小游戏开发的内容在《Unity WebGL 微信小游戏适配方案》中有详细&#xff0c;这里会忽略大部分更深入的细节&#xff0c;大家可以自行在下面的地址中找到答案。 此篇文章的目的是带着大家快速的把自己已有的游戏转成微信小游戏。 《Unity WebGL 微信小游戏适配方案》…

《Unity 2D与3D手机游戏开发实战》简介

#好书推荐##好书奇遇季#《Unity 2D与3D手机游戏开发实战》&#xff0c;京东当当天猫都有发售。彩色印制&#xff0c;定价89元&#xff0c;网店打折销售更便宜。本书配套源码、PPT课件&#xff0c;适合Unity游戏开发初学者&#xff0c;以及高校相关专业游戏开发课程的师生。 本书…

游戏开发经验-UnityADS接入

如果在Service里无法打开ads就去资源管理里去下载 //如果该平台&#xff08;手机&#xff09;支持Unity广告if (Advertisement.isSupported){ //初始化广告。&#xff08;参数&#xff1a;游戏ID&#xff0c;是否是测试模式&#xff09;Advertisement.Initialize("44…

unity3d开发传奇类游戏3D

传奇开发类游戏开发精讲 先上效果 技能治疗 技能伤害 近战 地图数据&#xff1a; vector2 数组。N行N列&#xff0c;描述地图大小。通过数据结构算法得出每个单元格的坐标 [x,y][x,y][x,y] [x,y][x,y][x,y] [x,y][x,y][x,y]对象移动 player{x0,y0} 右移动x1 左移动x-1 …

3D游戏编程与设计-Unity ch02

简答题 一、游戏对象&#xff08;GameObjects&#xff09;和资源&#xff08;Assets&#xff09;的区别与联系 游戏对象&#xff08;GameObjects&#xff09;是能容纳实际实现功能的组件&#xff0c;是Unity中代表人物、场景或道具的基本对象&#xff0c;简单来讲GameObjects也…

Unity游戏开发——新发教你做游戏(一):打开游戏开发新世界的大门

文章目录 一、前言二、制作思路三、提出问题四、具体实现 一、前言 嗨&#xff0c;大家好&#xff0c;我是新发&#xff0c;如下&#xff0c;我做了个简单的Demo&#xff0c;接下来我会详细介绍如何一步步制作&#xff0c;Demo工程我已上传到GitHub&#xff0c;感兴趣的同学可…

基于Unity的2d动画游戏-------------------c#开发

基于unity的2d动画制作----基于c#语言开发&#xff0c;类似于《DNF》的2d界面&#xff0c;目前只有一个游戏场景。成果图UI如下图所示 游戏成果视频已经上传B站&#xff1a; 2dAnimation游戏 游戏开发主要步骤&#xff1a; 1.素材收集&#xff08;来自Unity的Asset Store&…

【项目展示】基于Unity开发的3DRPG游戏

介绍 项目为大四毕业设计的游戏内容部分&#xff0c;使用Unity3D开发&#xff0c;总代码6000行&#xff0c;全部为自己实现&#xff0c;主要是一套简单的代码框架&#xff0c;具备一定的扩展性。游戏中填充了第一关的内容以展示功能。&#xff08;仍然有许多改进空间&#xff…

【游戏开发】2D RPG游戏

前言 通过对游戏《原神》的功能复刻来学习游戏开发 截止到10月&#xff0c;本项目已经开发的差不多了&#xff0c;不是开发的完善了&#xff0c;而是通过这个项目已经学会了Unity开发游戏的技巧&#xff0c;就不继续开发了。 这里展示一下目前的成果&#xff0c;并简述一下各…

Unity 3D 游戏与编程

3D 游戏与编程——作业二 1、简答题 1&#xff09;解释 游戏对象&#xff08;GameObject&#xff09;和 资源&#xff08;Assets&#xff09;的区别和联系 Assets 是游戏中具体的资源&#xff0c;比如 texture&#xff0c;mesh&#xff0c;material&#xff0c;shader&#x…

unity3d开发微信小游戏2

文章目录 前言一、开发的一些记录二、最终截图总结 前言 最开使用unity3d开发微信小游戏&#xff0c;遇到了一些问题&#xff0c;记录一下&#xff0c; 同时创建了一个交流群QQ 641029627&#xff0c;现在应该没人&#xff0c;有需要的可以加入一起讨论&#xff0c;广告哥远离…

Unity简单2D游戏开发

Unity简单2D游戏开发 前言&#xff1a; 近日比较无聊&#xff0c;在b站找了一个up主&#xff0c;跟着他的教程来做游戏——开发一个简单的2D游戏 用 Tilemap 绘制场景 新建一个2D项目&#xff0c;在Unity Asset Store中搜索下载 “Pixel Adventure ”&#xff0c;第一个就是…

Unity 开发微信小游戏初探

前言 最近因项目需要开始研究Unity开发微信小游戏相关的知识。期间遇到各种坑&#xff0c;网上查阅的资料基本类似&#xff0c;无法解决自己遇到的问题。特用本文记录下过程&#xff0c;方便其他人遇到同样的问题时能够参考。 开发环境 Unity 版本 根据微信小游戏插件文档推荐…

UNITY3D对接QQGame(PC)开发教程(2022)

效果 目标&#xff1a;能在UNITY3D里通过qqgame充值 因为目前还没有这类文章&#xff0c;所以填补这下块空白 文章包含 QQGame登录器的制作 QQGAME和UNITY3D的交互 QQGame平台用户信息的读取 支付规则&#xff0c;后台搭建。 和常见问题。 对接参考腾讯开发者有文档 https:/…

《Unity 2D与3D手机游戏开发实战》上架了。

新书上架了。 这本书主要是Unity开发的入门&#xff0c;附带了一个简单的2D例子&#xff0c;一个3D RPG的简单例子和一个尽可能用插件实现的射击游戏的例子。 书很薄&#xff0c;不过因为是彩页印刷&#xff0c;价钱不是那么实惠。不过说实话&#xff0c;因为这类书里面有很多…

Unity游戏开发 3D RPG(1-4)

如何将普通的3D项目升级到URP 在Package Manner 里的Unity Registry 里搜索 Universal RP ( 通用渲染管线Universal Render Pileline). 随后在Assets 新建Rendering ——URP Assets (with Universal Renderer) Edit -project setting -graphics,在Render pileline setting里…

Unity游戏开发:对话系统的实现

在解谜类游戏中&#xff0c;与npc的对话是一个基础且常用的功能。通常来说&#xff0c;在与npc的对话中玩家可以获取一些有价值的信息并对之后的游戏有一定的导向作用。此外&#xff0c;在玩家获取对应物品前后&#xff0c;与npc的对话内容也会发生相应改变。因此&#xff0c;我…