UI搭建:
————————————————————————————————
代码:
装备共有属性类:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum ArticleType//装备种类
{
Weapon,
Drag,
Collect,
Pick
}
public class Article //装备属性类(装备共有参数)
{
public string name;//装备名称
public string spritPath;//装备UI图路径
public ArticleType articleType;//装备类型
public int count;//装备数量
//构造函数
public Article(string name,string spritPath,ArticleType articleType,int count)
{
this.name = name;
this.spritPath = spritPath;
this.articleType = articleType;
this.count = count;
}
}
——————————————————————————————
装备“物品”类
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ArticleItem : MonoBehaviour
{
private Image articleSprit;
private Text count;
public Article article;
private UIDrag UIDrag;//实现拖拽的类
private Canvas canvas;//物体上的Canvas组件,用于物体显示在上层
//private CanvasGroup canvasGroup;//拖拽此物体是取消其射线检测,代替事件渗透
private int defortSort;
//private Transform Origentparent;
private Vector3 currentLocalPosition;
private float moveTimer;
public float moveTime = 0.2f;
private bool isMoving = false;
private Action onMoveEnd;
// Start is called before the first frame update
void Awake()
{
articleSprit = transform.GetComponent<Image>();
count = transform.Find("ItemCount").GetComponent<Text>();
//将对应拖拽状态时要掉用的方法注册到拖拽类的委托链
UIDrag = transform.GetComponent<UIDrag>();
UIDrag.onStartDrag += OnStartDrag;
UIDrag.onDrag += OnDrag;
UIDrag.onEndDrag += OnEndDrag;
canvas = transform.GetComponent<Canvas>();
defortSort = canvas.sortingOrder;
//canvasGroup = transform.GetComponent<CanvasGroup>();
//currentLocalPosition = transform.localPosition;
}
private void Start()
{
transform.localPosition = Vector3.zero;
currentLocalPosition = transform.localPosition;
}
private void Update()
{
MoveBack();
}
//Lerpg固定时间内完成执行
private void MoveBack()
{
if (isMoving)
{
moveTimer += Time.deltaTime * (1 / moveTime);//0.2秒后为1
transform.localPosition = Vector3.Lerp(currentLocalPosition, Vector3.zero, moveTimer);
if (moveTimer >= 1)
{
isMoving = false;
//MoveToOrigin方法导致的事件完成后执行自身委托
onMoveEnd?.Invoke();
}
}
}
//执行Lerp
public void MoveToOrigin(Action onMoveEnd)
{
isMoving = true;
moveTimer = 0;
currentLocalPosition = transform.localPosition;
this.onMoveEnd = onMoveEnd;//将之后要执行的方法方到自身委托链上
}
//设置装备属性(UI图标,数量等)
public void SetArticle(Article article)
{
this.article = article;
//显示数据
articleSprit.sprite = Resources.Load<Sprite>(this.article.spritPath);
count.text = this.article.count.ToString();
}
//开始拖拽时执行
public void OnStartDrag()
{
canvas.sortingOrder = defortSort + 1;//显示在同级上层
//transform.SetParent(transform.parent.parent);
BagPanel.instence.curretnAricle = this;//正在拖拽的为此物体
}
public void OnDrag()
{
}
//拖拽结束时执行
public void OnEndDrag()
{
//结束拖拽时所选格子不为空时,物品进入格子,
if (BagPanel.instence.currtenHoverGrid != null && !BagPanel.instence.currtenHoverGrid.gameObject.Equals(transform.parent.gameObject))
{
BagPanel.instence.currtenHoverGrid.DragIntoGride(BagPanel.instence.curretnAricle);//格子的方法
canvas.sortingOrder = defortSort;//恢复层级
}
else//为空则返回
{
//transform.SetParent(Origentparent);
//使用委托实现结束后执行
MoveToOrigin(() => { canvas.sortingOrder = defortSort; });//表达式内为方法结束后要执行的语句
}
BagPanel.instence.curretnAricle = null;//结束拖拽时正在拖拽的物体为空
}
}
——————————————————————————————
实现拖拽的类:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class UIDrag : MonoBehaviour,IBeginDragHandler,ICanvasRaycastFilter ,IDragHandler,IEndDragHandler
{
private Vector3 mousePosition;
private RectTransform rect;
public Action onDrag;
public Action onStartDrag;
public Action onEndDrag;
private bool isDraging = false;
private void Awake()
{
rect = GetComponent<RectTransform>();
if (rect ==null)
{
throw new System.Exception("只能拖拽UI物体");
}
}
//使用事件渗透监听不到拖拽事件时可用下面代码
/*private void Update()
{
if (isDraging)
{
*//*rect.anchoredPosition += (Vector2)(Input.mousePosition - mousePosition);
mousePosition = Input.mousePosition;
//transform.position = eventData.position; //中心随光标移动
//锚点的位置加上鼠标移动
//rect.anchoredPosition += eventData.delta;
//if (onDrag != null) onDrag();
onDrag?.Invoke();*//*
}
if(Input .GetMouseButtonUp(0)&&isDraging==true)
{
onEndDrag?.Invoke();
isDraging = false;
}
}*/
public void OnBeginDrag(PointerEventData eventData)
{
mousePosition = Input.mousePosition;
onStartDrag?.Invoke();
isDraging = true;
}
//事件渗透接口:渗透过当前事件向下进行事件检测(背包系统渗透装备UI图标向下检测所在物品栏)
public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)//事件渗透接口:返回值TRUE时:检测,返回值为FALES:渗透事件。
{
return !isDraging;//拖拽时事件渗透当前拖拽的物体渗透当前事件继续检测
}
//事件渗透监听不到此接口事件(实际监听的到),但要保留接口实现拖拽
public void OnDrag(PointerEventData eventData)//参数为相机与点击物体的射线检测点
{
rect.anchoredPosition += (Vector2)(Input.mousePosition - mousePosition);
mousePosition = Input.mousePosition;
//transform.position = eventData.position; //中心随光标移动
//锚点的位置加上鼠标移动
//rect.anchoredPosition += eventData.delta;
//if (onDrag != null) onDrag();
onDrag?.Invoke();
}
//事件渗透监听不到此接口事件(实际监听的到)
public void OnEndDrag(PointerEventData eventData)
{
onEndDrag?.Invoke();
isDraging = false;
}
}
——————————————————————————————
格子类:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class BagGrde : MonoBehaviour , IPointerEnterHandler,IPointerExitHandler
{
private ArticleItem articleItem;
private Image bgImage;
private Color defortColor;
public ArticleItem ArticleItem
{
get { return articleItem; }
}
private void Awake()
{
bgImage = transform.GetComponent<Image>();
defortColor = bgImage.color;
}
//设置格子内的装备物品方法
public void SetArticleItem(ArticleItem articleItem)
{
this.articleItem = articleItem;//此格子装着的物品
this.articleItem.gameObject.SetActive(true);
//将此物品栏设置父物体
this.articleItem.transform.SetParent(transform);
//刷新背包时直接设置位置,取消物品UI缓动效果
articleItem.transform.localPosition = Vector3.zero;
//防止发生变化
//设置位置
//this.articleItem.transform.localPosition = Vector3.zero;
this.articleItem.MoveToOrigin(() =>//用物品类里面的方法实现拖拽到格子时的缓动效果
{//设置5px的边界值
this.articleItem.GetComponent<RectTransform>().offsetMin = new Vector2(5, 5);
this.articleItem.GetComponent<RectTransform>().offsetMax = new Vector2(-5, -5);
});
//设置大小
this.articleItem.transform.localScale = Vector3.one;
//设置
//this.articleItem.GetComponent<RectTransform>().offsetMin = new Vector2(5, 5);
//this.articleItem.GetComponent<RectTransform>().offsetMax = new Vector2(-5, -5);
}
//清空格子
public void ClearGride()
{
articleItem.gameObject.SetActive(false);
articleItem.transform.SetParent(null);
articleItem = null;
}
//物品填入格子
public void DragIntoGride(ArticleItem articleItem)
{
//物品原来所在的格子
BagGrde lastGride = articleItem.transform.parent.GetComponent<BagGrde>();
if (this.articleItem==null)//如果这个格子中没有物品
{
//清空之前的格子
lastGride.ClearGride();
//设置拖拽到的此格子
SetArticleItem(articleItem);
//lastGride.ClearGride();
}
else//此格子不为空时将物品进行交换
{
//当前格子内物品设置到之前的格子
lastGride.SetArticleItem(this.articleItem);
//设置拖拽过来的新物品到的此格子
SetArticleItem(articleItem);
}
}
//鼠标进入格子时接口调用的函数
public void OnPointerEnter(PointerEventData eventData)
{
if(BagPanel.instence .curretnAricle!=null)//拖拽的物品不为空时
{
BagPanel.instence.currtenHoverGrid = this;//光标进入此格子则选中此格子
bgImage.color = Color.white;//该变选中格子的颜色
}
//此格子布为空时显示此格子物品的信息界面
if (this.articleItem != null)
{
UIManager.Instence.articleInformation.gameObject.SetActive(true);
UIManager.Instence.articleInformation.panel.transform.position = transform.position;
UIManager.Instence.articleInformation.info.text = this.articleItem.article.name + "\n" + this.articleItem.article.count.ToString ();
}
}
//光标退出时
public void OnPointerExit(PointerEventData eventData)
{
BagPanel.instence.currtenHoverGrid = null;
bgImage.color = defortColor;
//隐藏信息界面
UIManager.Instence.articleInformation.gameObject.SetActive(false);
UIManager.Instence.articleInformation.panel.transform.position = Vector3.zero;
UIManager.Instence.articleInformation.info.text = " ";
}
}
———————————————————————————————————
背包模块类:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class BagPanel : MonoBehaviour
{
private List<Article> articlesList = new List<Article>();//背包中所有物品的属性
private List<GameObject> articleObjectPool = new List<GameObject>();//储存物品预制件的对象池
public GameObject articleItemPrafab;//物品UI预制件
private BagGrde[] bagGrdes;//物品栏
public BagGrde currtenHoverGrid;//当前鼠标所悬浮所在格子
public ArticleItem curretnAricle;//当前拖拽物品
//单例
public static BagPanel instence;//单例,在外部访问公开属性
//private Button btn_Back;
// Start is called before the first frame update
void Awake()
{
/*if (instence !=null)
{
Destroy(gameObject);
return;
}*/
instence = this;
//DontDestroyOnLoad(gameObject);
//btn_Back = transform.Find("btn_Back").GetComponent<Button>();
//btn_Back.onClick.AddListener(UIManager.Instence.ExtBagPanel);
InitArticleDate();
bagGrdes = transform.GetComponentsInChildren<BagGrde>();//获取所有格子
LoadDate();//初始加载全部数据
}
/* private void Start()
{
LoadDate();
}*/
//加载全部数据
public void LoadDate()
{
ClearGrideAndHideItems();
for (int i = 0; i < articlesList.Count; i++)
{
//将列表中所有物品的属性生成对应物品装入空着的格子
GetBagGrid().SetArticleItem(LoadArticleItem(articlesList[i]));
}
}
//按类加载的重载方法
public void LoadDate(ArticleType articleType)
{
ClearGrideAndHideItems();
for (int i = 0; i < articlesList.Count; i++)
{
if (articlesList[i].articleType == articleType)
{
//将列表中某类物品生成对应物品装入空着的格子
GetBagGrid().SetArticleItem(LoadArticleItem(articlesList[i]));
}
}
}
//获取空着的格子
public BagGrde GetBagGrid()
{
for (int i = 0; i < bagGrdes.Length; i++)
{
if (bagGrdes[i].ArticleItem == null)
return bagGrdes[i];
}
return null;
}
//加载ArticleItem物品:根据属性创建对应装备物品
public ArticleItem LoadArticleItem(Article article)
{
GameObject go = GetGameObject();
ArticleItem articleItem = go.GetComponent
articleItem.SetArticle(article);
return articleItem;
}
//获取GameObject:获取对象池中空闲物品预制件
public GameObject GetGameObject()
{
for (int i = 0; i < articleObjectPool.Count; i++)
{
if (articleObjectPool[i].activeSelf==false)
{
articleObjectPool[i].SetActive(true);
return articleObjectPool[i];
}
}
GameObject go = Instantiate(articleItemPrafab);
articleObjectPool.Add(go);
return go;
}
//重新加载背包时物品栏清空
public void ClearGrideAndHideItems()
{
for (int i = 0; i < bagGrdes.Length; i++)
{
if (bagGrdes[i].ArticleItem!=null)
{
bagGrdes[i].ClearGride();
}
}
}
//初始化物品数据:加载拥有的制备数据应从服务器获取,此处实验性加载部分装备
public void InitArticleDate()
{
//武器
articlesList.Add(new Article("刀刀","at0", ArticleType.Weapon, 2));
articlesList.Add(new Article("剑剑", "at1", ArticleType.Weapon, 1));
articlesList.Add(new Article("春药", "at2", ArticleType.Drag, 7));
articlesList.Add(new Article("夏药", "at3", ArticleType.Drag, 6));
articlesList.Add(new Article("秋药", "at4", ArticleType.Drag, 5));
articlesList.Add(new Article("冬药", "at5", ArticleType.Drag, 4));
articlesList.Add(new Article("典藏种子", "at6", ArticleType.Collect, 1001));
articlesList.Add(new Article("玻璃碎片", "at7", ArticleType.Pick, 12));
}
#region 点击标签事件(所有标签都在同一个标签组-只有一个标签可选。勾选标签是执行)
public void OnAllToggleValueChange(bool v)//v为标签是否被勾选
{
if (v) LoadDate();
}
public void OnWepanToggleValueChange(bool v)
{
if (v) LoadDate(ArticleType.Weapon);
}
public void OnDragToggleValueChange(bool v)
{
if (v) LoadDate(ArticleType.Drag);
}
public void OnClctorToggleValueChange(bool v)
{
if (v) LoadDate(ArticleType.Collect);
}
public void OnPickToggleValueChange(bool v)
{
if (v) LoadDate(ArticleType.Pick);
}
#endregion
}