大家看了前面的那么多理论代码,相信都对框架里面的东西有一定的掌握了吧!下面我会带着大家一起来开发背包功能。
这里我说一下一般公司开发项目的简要流程哦!首先由策划根据用户等提出各种需求,然后在项目开始前,所有人员会开一个项目分析会,美术人员,策划人员,程序前后端人员。开完会以后,主程搭好框架,然后给我们。项目团队之间的交流一般用svn。然后明确你在框架中开发东西。比如,我们拿到的任务就是开发背包模块。
下面我们就背包模块进行开发:
拿到需求了!我们首先需要拼UI背包面板,拼好以后去存预制物。然后去看框架,看完以后。我们来开发。记住所有的开发都是从数据层入手的!那么我们来创建BagModule类。继承自框架中的BaseProxy 父类。
****************背包模块开发************************
父类没有什么好说的,自己看吧!具体功能在子类呢!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 所有数据的父类
/// </summary>
public class BaseProxy
{
/// <summary>
/// 初始化数据
/// </summary>
public virtual void Init()
{
}
/// <summary>
/// 数据接收完后
/// </summary>
public virtual void Logout()
{
}
/// <summary>
/// 注册侦听
/// </summary>
public virtual void RegisterListener()
{
}
/// <summary>
/// 移除侦听
/// </summary>
public virtual void RemoveListener()
{
}
}
下面我们开发子类,记好了哦!这是数据层的开发哦!
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 管理背包从从服务器接接收的数据和向服务器请求后,服务器做出回应的数据
/// </summary>
public class BagModule : BaseProxy
{
#region 单例模式
private static BagModule _instance;
public static BagModule GetInstance
{
get
{
if (_instance == null)
{
_instance = new BagModule();
}
return _instance;
}
}
#endregion
/// <summary>
/// 存放接收数据的列表
/// </summary>
private List<ItemData> bagList = new List<ItemData>();
/// <summary>
/// 构造函数
/// </summary>
public BagModule()
{
}
public override void Init()
{
this.RegisterListener();
}
public override void Logout()
{
this.RemoveListener();
}
/// <summary>
/// 侦听服务器发过来的数据
/// </summary>
public override void RegisterListener()
{
#region 侦听服务器层数据
//S2C_Bag_AddData告诉全部背包数据的
//服务器向我们发送信息
CEventDispatcher.GetInstance().AddEventListener(CEventType.S2C_Bag_SetAllData, OnSetAllData);
CEventDispatcher.GetInstance().AddEventListener(CEventType.S2C_Bag_RemoveData, OnRemoveData);
CEventDispatcher.GetInstance().AddEventListener(CEventType.S2C_Bag_AddData, OnSetAddData);
#endregion
#region 侦听显示层(View)数据
CEventDispatcher.GetInstance().AddEventListener(CEventType.Bag_UserItem, SendUseItem);
#endregion
}
/// <summary>
/// 移除侦听事件
/// </summary>
public override void RemoveListener()
{
#region 移除侦听服务器层数据
CEventDispatcher.GetInstance().RemoveEventListener(CEventType.S2C_Bag_SetAllData, OnSetAllData);
CEventDispatcher.GetInstance().RemoveEventListener(CEventType.S2C_Bag_RemoveData, OnRemoveData);
CEventDispatcher.GetInstance().RemoveEventListener(CEventType.S2C_Bag_AddData, OnSetAddData);
#endregion
#region 移除侦听显示层(View)数据
CEventDispatcher.GetInstance().RemoveEventListener(CEventType.Bag_UserItem, SendUseItem);
#endregion
}
#region 侦听事件的回调函数
/// <summary>
/// 设置所有背包数据
/// </summary>
/// <param name="evt"></param>
private void OnSetAllData(CBaseEvent evt)
{
while (bagList.Count > 0)
{
bagList.RemoveAt(0);
}
bagList = evt.Sender as List<ItemData>;
//拿到数据然后派发事件 让显示层去更新显示
CEventDispatcher.GetInstance().DispatchEvent(new CBaseEvent(CEventType.Bag_UpdataData, bagList));
}
/// <summary>
/// 移除数据
/// </summary>
/// <param name="evt"></param>
private void OnRemoveData(CBaseEvent evt)
{
for (int i = 0; i < bagList.Count; i++)
{
if (bagList[i].itemId == (evt.Sender as ItemData).itemId)
{
//bagList.Remove(bagList[i]);
bagList.RemoveAt(i);
break;
}
}
//更新数据以后派发事件 让显示层去更新显示
CEventDispatcher.GetInstance().DispatchEvent(new CBaseEvent(CEventType.Bag_UpdataData, bagList));
}
/// <summary>
/// 添加背包数据
/// </summary>
/// <param name="evt"></param>
private void OnSetAddData(CBaseEvent evt)
{
//背包中是否有数据了
bool isHas = false;
for (int i = 0; i < bagList.Count; i++)
{
//如果找到相等的直接覆盖之前的(注意:服务器推过来的对象ItemData 包含了各种id,num等信息)
if (bagList[i].itemId == (evt.Sender as ItemData).itemId)
{
bagList[i] = evt.Sender as ItemData;
isHas = true;
break;
}
}
if (!isHas)
{
//注意:服务器推过来的对象ItemData 包含了各种id,num等信息
bagList.Add(evt.Sender as ItemData);
}
//更新数据以后派发事件 让显示层去更新显示
CEventDispatcher.GetInstance().DispatchEvent(new CBaseEvent(CEventType.Bag_UpdataData, bagList));
}
#endregion
#region 向服务器发送的请求数据(发过去以后,由服务器去做侦听,我, 不需要管,而我们和后端通信的就是这些事件了)
public void SendGetAllData()
{
CEventDispatcher.GetInstance().DispatchEvent(new CBaseEvent(CEventType.C2S_Bag_GetAllData));
}
public void SendGetItem(CBaseEvent evt)
{
CEventDispatcher.GetInstance().DispatchEvent(new CBaseEvent(CEventType.C2S_Bag_AddItem, evt.Sender.ToString()));
}
public void SendUseItem(CBaseEvent evt)
{
CEventDispatcher.GetInstance().DispatchEvent(new CBaseEvent(CEventType.C2S_Bag_RemoveItem, evt.Sender.ToString()));
}
#endregion
}
数据层开发完了以后,我们的数据都有了。下面我们应该做显示层了吧!因为我们这个简单,所以我们呢!没有C控制层的。下面来看显示层(V)
那么我们一起来看这个六大子类中的背包类吧!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
using System;
using Newtonsoft.Json;
/// <summary>
/// 背包预制物panel管理类(我们的背包面板是要做成预制物的)
/// </summary>
public class BagPanel : BasePanel
{
private GameObject bagItem;
private CanvasGroup canvsGrounp;
private Button btnClose;
private Button btnReset;
private Transform content;
/// <summary>
/// 存放创建的BagItem
/// </summary>
private List<GameObject> bagItems = new List<GameObject>();
/// <summary>
/// 初始化方法
/// </summary>
void Awake()
{
LoadItem();
RegisterComponent();
RegiseterEvent();
}
private void RegisterComponent()
{
canvsGrounp = GetComponent<CanvasGroup>();
btnClose = transform.Find("CloseButton").GetComponent<Button>();
btnReset = transform.Find("ResetButton").GetComponent<Button>();
content = transform.Find("Scroll View/Viewport/Content");
}
/// <summary>
/// 加载背包里面小item的预制物的
/// </summary>
private void LoadItem()
{
bagItem = Resource.LoadPrefab("UI/BagItem");
}
void Start()
{
////添加侦听事件(背包更新数据事件)
//CEventDispatcher.GetInstance().AddEventListener(CEventType.Bag_UpdataData, RefreshData);
////派发使用item的事件
//CEventDispatcher.GetInstance().DispatchEvent(new CBaseEvent(CEventType.Bag_UserItem, "99"));
if (canvsGrounp == null)
{
//获取CanvasGroup组件
canvsGrounp = GetComponent<CanvasGroup>();
}
//向服务器主动请求数据的
BagModule.GetInstance.SendGetAllData();
}
/// <summary>
/// 注册侦听的
/// </summary>
private void RegiseterEvent()
{
btnClose.onClick.AddListener(delegate ()
{
UIManager.Instance.PopPanel();
});
btnReset.onClick.AddListener(delegate ()
{
});
//侦听一条更新数据的消息,然后做显示
CEventDispatcher.GetInstance().AddEventListener(CEventType.Bag_UpdataData, OnUpdataData);
}
/// <summary>
/// 处理发送过来的数据的方法
/// </summary>
/// <param name="evt"></param>
private void OnUpdataData(CBaseEvent evt)
{
List<ItemData> list = evt.Sender as List<ItemData>;
//先删除旧的显示对象 方法二:
//foreach (var item in bagItems)
//{
// Destroy(item.gameObject);
//}
for (int i = 0; i < bagItems.Count; i++)
{
Destroy(bagItems[i] as GameObject);
}
bagItems.Clear();
foreach (ItemData item in list)
{
//content设置父物体
//Instantiate有多个重载(预制物,父物体)
GameObject go = Instantiate(bagItem, content);
BagItem itemData = Util.Add<BagItem>(go);//添加脚本
itemData.SetData(item);//设置数据
bagItems.Add(go);//将所有的对象管理起来
}
}
/// <summary>
/// 复写的父类面板进入时的方法
/// </summary>
public override void OnEnter()
{
if (canvsGrounp == null)
{
canvsGrounp = GetComponent<CanvasGroup>();
canvsGrounp.alpha = 1;
canvsGrounp.blocksRaycasts = true;
}
else
{
canvsGrounp.alpha = 1;
canvsGrounp.blocksRaycasts = true;
}
//缓动动画(利用DoTween插件做的动画)
Vector3 temp = transform.localPosition;
temp.x = 600;
temp.y = 0;
transform.localPosition = temp;
transform.DOLocalMoveX(0, 0.5f);//缓动
}
/// <summary>
/// 覆写的父类面板进入时的方法
/// </summary>
public override void OnExit()
{
canvsGrounp.blocksRaycasts = false;
//OnComplete后面可以跟一个回调函数
transform.DOLocalMoveX(600, 0.5f).OnComplete(() => canvsGrounp.alpha = 0);
}
/// <summary>
/// 覆写的父类面板暂停时的方法
/// </summary>
public override void OnPause()
{
canvsGrounp.blocksRaycasts = false;
}
/// <summary>
/// 覆写的父类面板继续时的方法
/// </summary>
public override void OnResume()
{
canvsGrounp.blocksRaycasts = true;
}
}
由于我们的背包离里面有单个的小对象item吧,即背包里面的物品。我们需要再创建一个类。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 背包中临时Item(物品管理类)
/// </summary>
public class BagItem : MonoBehaviour
{
//item上面的引用
private ItemData itemData;
private Button btn;
private Text itemNum;
private Text itemName;
private Image itemIcon;
// Use this for initialization
void Awake()
{
RegisterComponent();
RegiseterEvent();
}
/// <summary>
/// 查找组件
/// </summary>
private void RegisterComponent()
{
itemIcon = transform.Find("itemIcon").GetComponent<Image>();
btn = transform.Find("itemButton").GetComponent<Button>();
itemName = transform.Find("itemName").GetComponent<Text>();
itemNum = transform.Find("itemNum").GetComponent<Text>();
}
/// <summary>
/// 移除侦听
/// </summary>
private void RegiseterEvent()
{
btn.onClick.AddListener(delegate ()
{
CEventDispatcher.GetInstance().DispatchEvent(new CBaseEvent(CEventType.Bag_UserItem, itemData.itemId));
});
}
/// <summary>
/// 设置数据
/// </summary>
/// <param name="data"></param>
public void SetData(ItemData data)
{
itemData = data;
RefreshView();
}
/// <summary>
/// 做显示的方法
/// </summary>
private void RefreshView()
{
//print("images/equip/" + itemData.itemIcon);
Sprite sprite = Resource.LoadSprite("images/equip/" + itemData.itemIcon);
if (sprite == null)
{
Debug.LogError("sprite is null !!!");
}
itemIcon.sprite = sprite;
itemName.text = itemData.itemName;
itemNum.text = itemData.itemNum;
btn.GetComponent<Image>().sprite = sprite;
}
}
小item上面的组件。
好了!这些就是实战开发背包模块了哦!不懂的话欢迎私聊QQ哦!
希望这些可以帮助到大家哦!
本篇小结:本篇主要想大家讲解了背包模块是如何开发出来的哦!这只是六大模块中的一个小部分模块哦!大家要是有时间的话,就去开发其他模块练练手嘛!如果没有策划的话,建议自己去体验当前比较火的手游王者荣耀哦!它里面的功能还是比较多的!还有一点,作为程序员的我们,有空一定要多多体验游戏,因为你体验的多了,才会有新的见识哦!好了,就写这么多吧!马上就要春节了,也是我们的休息时间了哦!最后感谢大家的阅读,祝大家新年快乐哦!不懂的地方欢迎私聊QQ哦!QQ在前面博客中有哦!