何为常用?被我碰到那就是常用的
RectTransform.anchoredPosition
瞄点的中心点坐标
RectTransform.anchorMax
父 RectTransform 中右上角锚定到的标准化位置。
RectTransform.anchorMin
父 RectTransform 中左下角锚定到的标准化位置。
RectTransform.GetWorldCorners
获取计算的矩形在世界空间中的各个角
RectTransform.offsetMax
矩形右上角相对于右上锚点的偏移。
提醒,如果当前ui跟随父物体上下左右都保持边距为5,offsetMax要取反
RectTransform.offsetMin
矩形左下角相对于左下锚点的偏移
RectTransform.sizeDelta
瞄点之间的距离,如果跟随父物体在父物体的4个角上,即宽高
我的做法:
还是用grid layout group搭建背包的格子,然后在格子下放图片,在加载对应类型之前要清空图片,点击对应类型的toggle显示对应的图片在背包最上面,否则不实例化。
这样每次点击都先清空,再实例化,后序再优化
效果图:
当修改ui预制体的canvas层级,请不要直接将assets里的预制体添加canvas组件,然后修改层级,这样会导致ui显示不出来
而是将预制体拖到hierarchy面板下的canvas下,再添加canvas组件和Graphic Raycaster,然后修改层级,就可以正常显示
1.比如当我们点击鞋子类别时,如何将对应的所有item都显示在最上面的格子呢?
这个只需要遍历格子,判断当前格子里的item是否为空,为空就可以加载了
2.实现物品的拖拽功能
导入using UnityEngine.EventSystems;
继承IDragHandler,IBeginDragHandler,IEndDragHandler3个接口,并实现接口
下面是我自己写的,有点bug,在拖拽物体离格子越远的时候,鼠标会逐渐偏离拖拽物体,有大佬解决下吗
public void OnBeginDrag(PointerEventData eventData)
{
mousePosition = Input.mousePosition;
onStarDrag?.Invoke();
}
public void OnDrag(PointerEventData eventData)
{
rect.localPosition += (Input.mousePosition - mousePosition);
rect.anchoredPosition += (Vector2)(Input.mousePosition - mousePosition);
mousePosition = Input.mousePosition;
onDrag?.Invoke();
}
public void OnEndDrag(PointerEventData eventData)
{
onEndDrag?.Invoke();
}
网上的话,是通过将屏幕坐标转化为世界坐标进行坐标的赋值,点这里
private void SetDraggedPosition(PointerEventData eventData)
{
Vector3 globalMousePos;
//把屏幕坐标转换为世界坐标,参数2-》参数4
if (RectTransformUtility.ScreenPointToWorldPointInRectangle(rect, eventData.position, eventData.pressEventCamera, out globalMousePos))
{
rect.position = globalMousePos;
}
//print(globalMousePos);
}
eventData 为拖拽物体的信息
ScreenPointToWorldPointInRectangle:将一个屏幕空间点转换为世界空间中位于给定 RectTransform 平面上的一个位置
PointerEventData.pressEventCamera(对于单击功能)获取正确的摄像机。这会为给定事件自动使用正确的摄像机(或 null)
IPointerEnterHandler,IPointerExitHandler接口可以监听鼠标的进入与退出
ICanvasRaycastFilter接口:如果顶级元素被命中,它还能进一步“检查”该位置是否有效。
当拖拽物品到对应格子上时,都会对格子的背景进行实时更新
提醒:背包本来就是一个比较大的模块,代码量也比较多,当然我只做了搭建背包和拖拽功能及优化和toggle的绑定,仍存在缺陷,量力而行
操作:
1.BagPanel挂载BagPanel脚本,Grid挂载BagGrid脚本
随便做一个image,命名为articleItem作为预制体,添加4个组件
BagPanel.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BagPanel : ViewBase
{
public MenuPanel menuPanel;
public GameObject ArticleItemPre;
private BagGrid[] bagGrids;
//存article的信息
public List<Article> articles = new List<Article>();
//当前鼠标所处格子
public BagGrid currentMouseGrid;
//当前拖拽物体article
public ArticleItem currentDragArticle;
public static BagPanel instance;
public override void Hide()
{
base.Hide();
menuPanel.Show();
}
private void Awake()
{
instance = this;
Init();
bagGrids = transform.GetComponentsInChildren<BagGrid>();
}
// Start is called before the first frame update
void Start()
{
LoadData();
}
public void Init()
{
articles.Add(new Article("枪", "Sprite/weapon1", ArticleType.Weapon, 1));
articles.Add(new Article("刀", "Sprite/weapon2", ArticleType.Weapon, 2));
articles.Add(new Article("剑", "Sprite/weapon3", ArticleType.Weapon, 3));
articles.Add(new Article("仙剑", "Sprite/weapon4", ArticleType.Weapon, 4));
articles.Add(new Article("饺子", "Sprite/drug1", ArticleType.Drug, 1));
articles.Add(new Article("鸡肉", "Sprite/drug2", ArticleType.Drug, 2));
articles.Add(new Article("药丸", "Sprite/drug3", ArticleType.Drug, 3));
articles.Add(new Article("仙丹", "Sprite/drug4", ArticleType.Drug, 4));
articles.Add(new Article("枪", "Sprite/shoe1", ArticleType.Shoes, 1));
articles.Add(new Article("枪", "Sprite/shoe2", ArticleType.Shoes, 2));
articles.Add(new Article("枪", "Sprite/shoe3", ArticleType.Shoes, 3));
articles.Add(new Article("枪", "Sprite/shoe4", ArticleType.Shoes, 4));
articles.Add(new Article("枪", "Sprite/book1", ArticleType.Book, 1));
articles.Add(new Article("枪", "Sprite/book2", ArticleType.Book, 2));
articles.Add(new Article("枪", "Sprite/book3", ArticleType.Book, 3));
articles.Add(new Article("枪", "Sprite/book4", ArticleType.Book, 4));
}
//获取一个空闲的格子
public BagGrid GetBagGrid()
{
for (int i = 0; i < bagGrids.Length; i++)
{
if (bagGrids[i].ArticleItem == null)
{
return bagGrids[i];
}
}
return null;
}
//加载格子里的页面在对应的格子
public void LoadData()
{
HideAllArticleItems();
for (int i = 0; i < articles.Count; i++)
{
bagGrids[i].SetArticleItem(LoadArticleItem(articles[i]));
}
}
public void LoadData(ArticleType articleType)
{
HideAllArticleItems();
for (int i = 0; i < articles.Count; i++)
{
if (articles[i].articleType == articleType)
{
GetBagGrid().SetArticleItem(LoadArticleItem(articles[i]));
}
}
}
//加载格子页面
public ArticleItem LoadArticleItem(Article article)
{
GameObject obj = GameObject.Instantiate(ArticleItemPre);
ArticleItem articleItem = obj.GetComponent<ArticleItem>();
//加载格子页面的图片
articleItem.SetArticle(article);
return articleItem;
}
//清空格子下的item
public void HideAllArticleItems()
{
for (int i = 0; i < bagGrids.Length; i++)
{
if(bagGrids[i].ArticleItem!=null)
{
bagGrids[i].ClearGrid();
}
}
}
#region 点击1事件
public void OnAllToggleValueEvent(bool v)
{
if(v)
{
LoadData();
}
}
public void OnWeaponToggleValueEvent(bool v)
{
if(v)
{
LoadData(ArticleType.Weapon);
}
}
public void OnShoesToggleValueEvent(bool v)
{
if (v)
{
LoadData(ArticleType.Shoes);
}
}
public void OnBookToggleValueEvent(bool v)
{
if (v)
{
LoadData(ArticleType.Book);
}
}
public void OnDrugToggleValueEvent(bool v)
{
if (v)
{
LoadData(ArticleType.Drug);
}
}
#endregion
}
BagGrid.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
//管理格子
public class BagGrid : MonoBehaviour,IPointerEnterHandler,IPointerExitHandler
{
private ArticleItem articleItem;
private Image bagImage;
private Color defaultColor;
public ArticleItem ArticleItem
{
get
{
return articleItem;
}
}
// Start is called before the first frame update
void Start()
{
bagImage = transform.GetComponent<Image>();
defaultColor = bagImage.color;
; }
//设置item
public void SetArticleItem(ArticleItem articleItem)
{
this.articleItem = articleItem;
this.articleItem.transform.parent = transform;
//this.articleItem.transform.localPosition = Vector3.zero;
this.articleItem.transform.localScale = Vector3.one;
this.articleItem.MoveToOrign();
;
this.articleItem.GetComponent<RectTransform>().offsetMin = new Vector2(5, 5);
this.articleItem.GetComponent<RectTransform>().offsetMax= new Vector2(-5, -5);
}
//销毁item
public void ClearGrid()
{
if (articleItem.gameObject != null)
Destroy(articleItem.gameObject);
articleItem = null;
}
//拖拽到对应格子
public void DragToThisGrid(ArticleItem articleItem)
{
BagGrid preGrid = articleItem.transform.parent.GetComponent<BagGrid>();
if(this.articleItem==null)
{
//清空之前的格子
preGrid.articleItem=null;
SetArticleItem(articleItem);
}
else
{
//交换
preGrid.SetArticleItem(this.articleItem);
SetArticleItem(articleItem);
}
}
//鼠标进入接口
public void OnPointerEnter(PointerEventData eventData)
{
if(BagPanel.instance.currentDragArticle!=null)
{
//this为当前鼠标所在格子
BagPanel.instance.currentMouseGrid = this;
bagImage.color = Color.yellow;
}
}
//鼠标退出接口
public void OnPointerExit(PointerEventData eventData)
{
BagPanel.instance.currentMouseGrid = null;
bagImage.color = defaultColor;
}
}
ArticleItem.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
//管理图片及对应信息
public class ArticleItem : MonoBehaviour
{
private Image articleSprite;
private Text number;
private UIDrag uIDrag;
private Article article;
private Canvas canvas;
private int defaultSort;
private Vector3 currentLocalPosition;
private float Timer=0;
private float MoveTime = 0.2f;
private bool isMoving = false;
// Start is called before the first frame update
private void Awake()
{
articleSprite = transform.GetComponent<Image>();
number=transform.Find("Text").GetComponent<Text>();
canvas = transform.GetComponent<Canvas>();
defaultSort = canvas.sortingOrder;
//在BagGrid写了回调函数
uIDrag = transform.GetComponent<UIDrag>();
uIDrag.onStarDrag += this.OnStartDrag;
uIDrag.onDrag += this.OnDrag;
uIDrag.onEndDrag += this.OnEndDrag;
}
private void Update()
{
MovingOrign();
}
//回到原位置
public void MovingOrign()
{
if (isMoving)
{
Timer += Time.deltaTime * (1 / MoveTime);
transform.localPosition = Vector3.Lerp(currentLocalPosition, Vector3.zero, Timer);
if (Timer >= 1)
{
Timer = 0;
isMoving = false;
canvas.sortingOrder = defaultSort;
}
}
}
//设置article信息
public void SetArticle(Article article)
{
this.article = article;
//初始化图片
articleSprite.sprite = Resources.Load<Sprite>(article.spritePath);
number.text = article.count.ToString();
}
//开始拖拽
public void OnStartDrag()
{
canvas.sortingOrder = defaultSort + 1;
//this为当前开始拖拽的article
BagPanel.instance.currentDragArticle = this;
}
//拖拽过程
public void OnDrag()
{
}
//拖拽结束
public void OnEndDrag()
{
if(BagPanel.instance.currentMouseGrid!=null)
{
//移动到对应格子
BagPanel.instance.currentMouseGrid.DragToThisGrid(BagPanel.instance.currentDragArticle);
//修改层级
canvas.sortingOrder = defaultSort;
}
else
{
//当移动位置不合法则移动到原点
MoveToOrign();
}
BagPanel.instance.currentDragArticle = null;
}
//开始移动到起点的初始化
public void MoveToOrign()
{
isMoving = true;
Timer = 0;
currentLocalPosition = transform.localPosition;
}
}
UIDrag.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class UIDrag : MonoBehaviour,IDragHandler,IBeginDragHandler,ICanvasRaycastFilter,IEndDragHandler
{
private RectTransform rect;
private Vector3 mousePosition;
//回调函数
public Action onStarDrag;
public Action onDrag;
public Action onEndDrag;
private bool isDraging = false;
private void Start()
{
rect = transform.GetComponent<RectTransform>();
}
private void Update()
{
if (isDraging)
{
rect.localPosition += (Input.mousePosition - mousePosition);
rect.anchoredPosition += (Vector2)(Input.mousePosition - mousePosition);
mousePosition = Input.mousePosition;
//SetDraggedPosition(eventData);
onDrag?.Invoke();
}
if(Input.GetMouseButtonUp(0)&&isDraging)
{
isDraging = false;
}
}
public void OnBeginDrag(PointerEventData eventData)
{
mousePosition = Input.mousePosition;
//SetDraggedPosition(eventData);
isDraging = true;
onStarDrag?.Invoke();
}
public void OnDrag(PointerEventData eventData)
{
//rect.localPosition += (Input.mousePosition - mousePosition);
//rect.anchoredPosition += (Vector2)(Input.mousePosition - mousePosition);
//mousePosition = Input.mousePosition;
SetDraggedPosition(eventData);
//onDrag?.Invoke();
}
public void OnEndDrag(PointerEventData eventData)
{
//SetDraggedPosition(eventData);
onEndDrag?.Invoke();
}
private void SetDraggedPosition(PointerEventData eventData)
{
Vector3 worldMousePos;
//把屏幕坐标转换为世界坐标
if (RectTransformUtility.ScreenPointToWorldPointInRectangle(rect, Input.mousePosition,eventData.pressEventCamera, out worldMousePos))
{
rect.position = worldMousePos;
}
}
public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
{
return !isDraging;
}
}
Article .cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum ArticleType
{
Weapon,
Shoes,
Book,
Drug,
}
public class Article
{
public string name;
public string spritePath;
public ArticleType articleType;
public int count;
public Article(string name,string spritePath,ArticleType articleType,int count)
{
this.name = name;
this.spritePath = spritePath;
this.articleType = articleType;
this.count = count;
}
}