欢迎来到我的博客小站。  交流请加我微信好友: studyjava。  也欢迎关注同名公众号:Java学习之道

学Unity的猫之猫咪救济管理系统(十一)

  |   0 评论   |   0 浏览

11.1 山岗的星光

稀疏的星光,清辉洒地,流浪猫小花凝望着窗外,它没有想到一个月前它还是一只无家可归的流浪小猫,此时已经有了一个温暖的家。 事情要回到一个月前的那个夜晚,秋风瑟瑟,小花在路边蜷缩着身子,有个人类经过它的身旁,那个人站住了,嘴里发出蹩脚的喵喵声,慢慢想要靠近,小花见状立刻躲进了斜坡中的草丛里,那人停留片刻后便离开了。

两天后,小花又看到了那个人,而且还带着一只猫一台电脑,那只猫朝着小花挥手:“喂,过来这边,不要怕,我们不是坏人。”

小花不敢靠前,那只猫又喊道:“我叫皮皮,这个是我的铲屎官,这里有吃的,快过来。” 后来,小花不仅饱饱的吃了一餐,还得知了他们正在做一个猫咪救济管理系统,皮皮是项目的策划猫,它希望可以为那些流浪猫提供基础的保障,实名登记流浪猫,统一管理,调度资源,在设定的救济点投放食物和过冬物资,并与人类铲屎官合作,希望可以给流浪猫寻找合适的家。 每一只来到地球的喵星人都有一个唯一的编号,只要登记了这个编号,就可以随时随地通过猫电波进行通信,小花成为了救济系统的第一只猫。 很快便有人类来领养了小花,以前,小花总是坐在小斜坡上望着星星,它不知道自己从哪里来的,那里还有很多和它一样的猫,有的从来没见过,有的离开了又回来了,有的离开了就再也没有回来,只有星星一直陪着它。现在它有了家,它也想和皮皮它们一起,帮助流离失所的猫寻找温暖的家。 山岗的星光,愿你不再流浪,被世界温柔以待。

11.2 Unity猫咪救济管理系统

猫咪救济管理系统,模块设计如下:运行效果如下:

本工程使用的Unity版本为2020.1.14f1c1 (64-bit),工程已上传到GitHub,感兴趣的同学可以下载下来学习。GitHub地址:https://github.com/linxinfa/Unity-CatInfoSystem

11.3 设置UI摄像机

创建一个摄像机,重命名为UICamera设置Culling Mask只渲染UI层。设置视口Projection为正交视口Orthographic设置Main Camera不渲染UI层。

11.4 设置Canvas

创建Canvas,并设置Render ModeScreen Space -Camera,设置Render CameraUICamera,再把Canvas Scaler组件的UI Scale Mode设置为Scale With Screen Size

11.5 制作登录界面预设

LoginPanel.prefab两个Input Field组件,用来输入账号和密码(accountpassword),一个Button组件作为登录按钮(LoginButton)。

11.6 制作大厅界面预设

PlazaPanel.prefab一个Button组件作为登记按钮(AddButton),一个Scroll View组件作为拖拉列表,一个Item作为列表的项,一个Button组件作为退出登录按钮(LogoutButton)。其中,Item中使用多个Text组件作为信息显示。

11.7 制作信息界面预设

InfoPnel.prefab使用三个Button组件作为确定、删除、关闭按钮,使用多个Input Field组件和一个Drop Down组件作为信息输入。

11.8 UI界面管理器:UIManager

UI预设资源放在Resources目录中。封装一个UIManager类,用来加载界面预设资源和显示界面。

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

public class UIManager
{
    public void Init(Canvas canvas)
    {
        m_canvasTrans = canvas.transform;
    }

    
    
    
    
    
    public GameObject ShowPanel(string panelName)
    {
        GameObject prefabObj = null;
        if (m_panelRes.ContainsKey(panelName))
        {
            prefabObj = m_panelRes[panelName];
        }
        else
        {
            prefabObj = Resources.Load<GameObject>(panelName);
            m_panelRes[panelName] = prefabObj;
        }
        GameObject panelObj = Object.Instantiate(prefabObj);
        panelObj.transform.SetParent(m_canvasTrans, false);
        return panelObj;
    }

    private Transform m_canvasTrans;
    
    
    
    private Dictionary<string, GameObject> m_panelRes = new Dictionary<string, GameObject>();

    
    
    
    private static UIManager s_instance;
    public static UIManager Instance
    {
        get
        {
            if (null == s_instance)
                s_instance = new UIManager();
            return s_instance;
        }
    }
}




public class PanelName
{
    public const string LOGIN_PANEL = "LoginPanel";
    public const string PLAZA_PANEL = "PlazaPanel";
    public const string INFO_PANEL = "InfoPanel";
}

11.9 封装猫信息的类:CatInfo

猫的信息中有个uuid是系统生成的,id是猫星人的编号,由喵星人手动输入。

public class CatInfo 
{
    public CatInfo()
    {
        uuid = System.Guid.NewGuid().ToString("N");
    }


    
    
    
    public string uuid;
    
    
    
    public string id;
    
    
    
    public string nickname;
    
    
    
    public string kind;
    
    
    
    public string color;
    
    
    
    public int gender;
    
    
    
    public string birth;
    
    
    
    public string reason;
}

11.10 猫信息管理器:CatManager

封装一个猫信息的管理类,CatManager,负责数据加载和增删改查。

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

public class CatManager
{
    public void Init()
    {
        
        m_datas = CatDataBase.QueryDatas();
    }

    
    
    
    
    public void AddOrModify(CatInfo info)
    {
        CatDataBase.AddOrModify(info);
        
        EventDispatcher.instance.DispatchEvent(EventNameDef.EVENT_ADD_OR_MODIFY_CAT, info);
    }

    
    
    
    
    public void Del(string uuid)
    {
        CatDataBase.Del(uuid);
        
        EventDispatcher.instance.DispatchEvent(EventNameDef.EVENT_DEL_CAT, uuid);
    }

    public Dictionary<string, CatInfo> data
    {
        get { return m_datas; }
    }

    
    
    
    private Dictionary<string, CatInfo> m_datas = null;

    
    
    
    private static CatManager s_instance;
    public static CatManager Instance
    {
        get
        {
            if (null == s_instance)
                s_instance = new CatManager();
            return s_instance;
        }
    }
}

11.11 数据存储:CatDataBase

封装一个CatDataBase类,负责数据的本地写入和读取。

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




public class CatDataBase
{

    
    
    
    
    public static void AddOrModify(CatInfo info)
    {
        if (s_datas.ContainsKey(info.uuid))
        {
            s_datas[info.uuid] = info;
        }
        else
        {
            s_datas.Add(info.uuid, info);
        }
        
        SaveData();
    }

    
    
    
    
    public static void Del(string uuid)
    {
        if (!s_datas.ContainsKey(uuid)) return;
        s_datas.Remove(uuid);
        SaveData();
    }

    
    
    
    
    public static Dictionary<string, CatInfo> QueryDatas()
    {
        string jsonStr = PlayerPrefs.GetString("cats", null);
        if (string.IsNullOrEmpty(jsonStr))
        {
            s_datas = new Dictionary<string, CatInfo>();
        }
        else
        {
            s_datas = JsonMapper.ToObject<Dictionary<string, CatInfo>>(jsonStr);
        }
        return s_datas;
    }

    
    
    
    public static void SaveData()
    {
        string jsonStr = JsonMapper.ToJson(s_datas);
        PlayerPrefs.SetString("cats", jsonStr);
    }

    private static Dictionary<string, CatInfo> s_datas = new Dictionary<string, CatInfo>();
}

其中写入本地数据用到了Unity提供的PlayerPrefs类。 读取数据接口

public static string GetString(string key, string defaultValue);
1

写入数据接口

public static void SetString(string key, string value);
1

​11.12 Json库:LitJson

需要将数据序列号到本地文件中,采用Json的格式,所以需要导入一个Json库,从GitHub下载LitJson源码: https://github.com/LitJSON/litjson/releases/tag/0.15.0下载后将源码导入到工程中。使用时引入命名空间。

using LitJson;

主要用到JsonMapper的两个接口。objectjson字符串接口

public static string ToJson (object obj)

json字符串转object接口

public static T ToObject<T> (string json)

11.13 观察者模式

数据更新的时候要更新ui的显示,这里采用观察者模式,ui界面的代码监听事件,数据变化时抛出事件,从而实现ui的显示刷新。 封装一个事件订阅和发送的类:EventDispatcher

皮皮:“微信搜索公众号 [爱上游戏开发],回复 “资料”,免费领取 200G 学习资料!”

using UnityEngine;
using System.Collections.Generic;

public delegate void MyEventHandler(params object[] objs);

public class EventDispatcher
{
    
    
    
    
    
    public void Regist(string type, MyEventHandler handler)
    {
        if (handler == null)
            return;

        if (!listeners.ContainsKey(type))
        {
            listeners.Add(type, new Dictionary<int, MyEventHandler>());
        }
        var handlerDic = listeners[type];
        var handlerHash = handler.GetHashCode();
        if (handlerDic.ContainsKey(handlerHash))
        {
            handlerDic.Remove(handlerHash);
        }
        listeners[type].Add(handler.GetHashCode(), handler);
    }

    
    
    
    
    
    public void UnRegist(string type, MyEventHandler handler)
    {
        if (handler == null)
            return;

        if (listeners.ContainsKey(type))
        {
            listeners[type].Remove(handler.GetHashCode());
            if (null == listeners[type] || 0 == listeners[type].Count)
            {
                listeners.Remove(type);
            }
        }
    }

    
    
    
    
    
    public void DispatchEvent(string evt, params object[] objs)
    {
        if (listeners.ContainsKey(evt))
        {
            var handlerDic = listeners[evt];
            if (handlerDic != null && 0 < handlerDic.Count)
            {
                var dic = new Dictionary<int, MyEventHandler>(handlerDic);
                foreach (var f in dic.Values)
                {
                    try
                    {
                        f(objs);
                    }
                    catch (System.Exception ex)
                    {
                        Debug.LogErrorFormat(szErrorMessage, evt, ex.Message, ex.StackTrace);
                    }
                }
            }
        }
    }

    
    
    
    
    public void ClearEvents(string key)
    {
        if (listeners.ContainsKey(key))
        {
            listeners.Remove(key);
        }
    }

    
    
    
    private Dictionary<string, Dictionary<int, MyEventHandler>> listeners = new Dictionary<string, Dictionary<int, MyEventHandler>>();
    private readonly string szErrorMessage = "DispatchEvent Error, Event:{0}, Error:{1}, {2}";

    
    
    
    private static EventDispatcher s_instance;
    public static EventDispatcher instance
    {
        get
        {
            if (null == s_instance)
                s_instance = new EventDispatcher();
            return s_instance;
        }
    }
}

定义事件

public class EventNameDef 
{
    
    
    
    public const string EVENT_ADD_OR_MODIFY_CAT  = "EVENT_ADD_OR_MODIFY_CAT";

    
    
    
    public const string EVENT_DEL_CAT = "EVENT_DEL_CAT";
}

11.14 登录界面代码:LoginPanel

登录界面代码LoginPanel,挂在LoginPanel.prefab上。 简单判断下账号和密码,如果账号为admin且密码为123456则进入大厅界面。 (实际开发需要有账号注册,与服务器通信才能完成登录,这里只是演示效果)。

using UnityEngine;
using UnityEngine.UI;

public class LoginPanel : MonoBehaviour
{
    public InputField nameInput;
    public InputField pwdInput;

    public Button loginBtn;

    void Start()
    {
        loginBtn.onClick.AddListener(() =>
        {
            if ("admin" == nameInput.text && "123456" == pwdInput.text)
            {
                Destroy(gameObject);
                UIManager.Instance.ShowPanel(PanelName.PLAZA_PANEL);
            }
        });
    }
}

绑定ui对象

11.15 大厅界面代码:PlazaPanel

大厅界面代码PlazaPanel,挂在PlazaPanel.prefab上。

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

public class PlazaPanel : MonoBehaviour
{
    public Button logoutBtn;
    public Button signBtn;
    public GameObject catItemObj;

    private Transform listRoot;

    void Awake()
    {
        
        EventDispatcher.instance.Regist(EventNameDef.EVENT_ADD_OR_MODIFY_CAT, OnEventAddOrModifyCat);
        EventDispatcher.instance.Regist(EventNameDef.EVENT_DEL_CAT, OnEventDelCat);

        CatManager.Instance.Init();
        catItemObj.SetActive(false);
        listRoot = catItemObj.transform.parent;
    }

    void Start()
    {
        
        logoutBtn.onClick.AddListener(() =>
        {
            Destroy(gameObject);
            UIManager.Instance.ShowPanel(PanelName.LOGIN_PANEL);
        });

        
        signBtn.onClick.AddListener(() =>
        {
            UIManager.Instance.ShowPanel(PanelName.INFO_PANEL);
        });

        
        foreach (CatInfo catInfo in CatManager.Instance.data.Values)
        {
            CreateItem(catInfo);
        }

    }

    
    
    
    
    void CreateItem(CatInfo info)
    {
        var obj = Instantiate(catItemObj);
        obj.SetActive(true);
        obj.transform.SetParent(listRoot, false);
        var itemUi = obj.GetComponent<CatListItem>();
        
        itemUi.UpdateUi(info);
        
        m_catUiList[info.uuid] = itemUi;
    }

    
    
    
    
    void OnEventAddOrModifyCat(params object[] args)
    {
        var info = args[0] as CatInfo;
        if (m_catUiList.ContainsKey(info.uuid))
        {
            m_catUiList[info.uuid].UpdateUi(info);
        }
        else
        {
            
            CreateItem(info);
        }
    }

    
    
    
    
    void OnEventDelCat(params object[] args)
    {
        var uuid = (string)args[0];
        if (m_catUiList.ContainsKey(uuid))
        {
            var ui = m_catUiList[uuid];
            if(null != ui)
            {
                Destroy(ui.gameObject);
            }
            m_catUiList.Remove(uuid);
        }

    }

    
    
    
    private void OnDestroy()
    {
        
        EventDispatcher.instance.UnRegist(EventNameDef.EVENT_ADD_OR_MODIFY_CAT, OnEventAddOrModifyCat);
        EventDispatcher.instance.UnRegist(EventNameDef.EVENT_DEL_CAT, OnEventDelCat);
    }

    private Dictionary<string, CatListItem> m_catUiList = new Dictionary<string, CatListItem>();
}

绑定PlazaPanel组件的ui对象。其中,列表的行ui单独封装成一个组件CatListItem,挂在Item节点上。

using UnityEngine;
using UnityEngine.UI;




public class CatListItem : MonoBehaviour
{
    public Text idText;
    public Text nameText;
    public Text kindText;
    public Text colorText;
    public Text genderText;
    public Text birthText;
    public Text resonText;

    public Button itemBtn;

    public void Start()
    {
        
        itemBtn.onClick.AddListener(() => 
        {
            var panelObj =  UIManager.Instance.ShowPanel(PanelName.INFO_PANEL);
            var infoPanel = panelObj.GetComponent<InfoPanel>();
            infoPanel.Init(m_info);
        });
    }

    
    
    
    
    public void UpdateUi(CatInfo info)
    {
        m_info = info;
        idText.text = info.id;
        nameText.text = info.nickname;
        kindText.text = info.kind;
        colorText.text = info.color;
        genderText.text = 0 == info.gender ? "母" : "公";
        birthText.text = info.birth;
        resonText.text = info.reason;
    }

    private CatInfo m_info;
}
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647

绑定CatListItem组件的ui对象。

11.16 信息界面代码:InfoPanel

信息界面代码InfoPanel,挂在InfoPanel.prefab上。

using UnityEngine;
using UnityEngine.UI;

public class InfoPanel : MonoBehaviour
{
    public InputField idInput;
    public InputField kindInput;
    public InputField nameInput;
    public InputField colorInput;
    public Dropdown genderDropdown;
    public InputField birthInput;
    public InputField reasonInput;

    public Button okBtn;
    public Button delBtn;
    public Button closeBtn;

    public CatInfo m_catInfo;

    public void Init(CatInfo info)
    {
        m_catInfo = info;
        idInput.text = info.id;
        kindInput.text = info.kind;
        nameInput.text = info.nickname;
        colorInput.text = info.color;
        genderDropdown.value = info.gender;
        birthInput.text = info.birth;
        reasonInput.text = info.reason;
    }

    private CatInfo MakeCatInfo()
    {
        if (null == m_catInfo)
            m_catInfo = new CatInfo();
        m_catInfo.id = idInput.text;
        m_catInfo.kind = kindInput.text;
        m_catInfo.nickname = nameInput.text;
        m_catInfo.color = colorInput.text;
        m_catInfo.gender = genderDropdown.value;
        m_catInfo.birth = birthInput.text;
        m_catInfo.reason = reasonInput.text;
        return m_catInfo;
    }

    void Start()
    {
        okBtn.onClick.AddListener(() =>
        {
            
            CatManager.Instance.AddOrModify(MakeCatInfo());
            Destroy(gameObject);

        });
        delBtn.onClick.AddListener(() =>
        {
            
            if(null != m_catInfo)
            {
                CatManager.Instance.Del(m_catInfo.uuid);
            }
            
            Destroy(gameObject);
        });

        closeBtn.onClick.AddListener(() => 
        {
            Destroy(gameObject);
        });
    }
}

绑定ui对象。完成。 如果有任何疑问欢迎留言或私信。



标题:学Unity的猫之猫咪救济管理系统(十一)
作者:shirlnGame
地址:https://mmzsblog.cn/articles/2021/01/11/1610372464440.html
-----------------------------
如未加特殊说明,此网站文章均为原创。
网站转载须在文章起始位置标注作者及原文连接,否则保留追究法律责任的权利。
公众号转载请联系网站首页的微信号申请白名单!

个人微信公众号 ↓↓↓                 

微信搜一搜爱上游戏开发