Unity3D学习笔记(二十三):事件接口、虚拟摇杆、层级管理和背包系统

时间:2024-12-10 13:36:38
事件接口
IDragHandler(常用):鼠标按下拖动时执行(只要鼠标在拖动就一直执行)
IDropHandler:对象拖动结束时,如果鼠标在物体的范围内,执行一次(依赖于IDragHandler存在)
(结束时鼠标必须在图片范围内)
IBeginDragHandler:开始拖动时执行一次
IEndDragHandler:拖动结束时执行一次(结束时对鼠标在哪没有要求)
IScrollHandler:监控鼠标滚轮
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
public class EventDrag : MonoBehaviour,
IDragHandler,
IDropHandler,
IBeginDragHandler,
IEndDragHandler,
IPointerEnterHandler,
IPointerUpHandler,
IPointerClickHandler
{
public void OnDrag(PointerEventData eventData)
{
Debug.Log("IDragHandler.OnDrag");
//Debug.Log("eventData.delta:" + eventData.delta);//上次执行与本次执行的鼠标偏移量
Debug.Log("eventData.scrollDelta:" + eventData.scrollDelta);//上次执行与本次执行的鼠标偏移量
}
public void OnDrop(PointerEventData eventData)
{
Debug.Log("IDropHandler.OnDrop");
}
public void OnBeginDrag(PointerEventData eventData)
{
Debug.Log("IBeginDragHandler.OnBeginDrag");
}
public void OnEndDrag(PointerEventData eventData)
{
Debug.Log("IEndDragHandler.OnEndDrag");
}
public void OnPointerEnter(PointerEventData eventData)
{
//Debug.Log("eventData.delta.name" + eventData.pointerDrag.name);//报错:在鼠标进入的事件接口里,无法获得拖动的物体
}
public void OnPointerUp(PointerEventData eventData)
{
Debug.Log("当前的结果:" + eventData.pointerCurrentRaycast.gameObject.name);
Debug.Log("按下的结果:" + eventData.pointerPressRaycast.gameObject.name);
}
public void OnPointerClick(PointerEventData eventData)
{
Debug.Log("点击次数:" + eventData.clickCount);
}
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
} }
PointerEventData:
button:鼠标按下时判断左右键
clickCount:点击次数(时间间隔固定)
delta:拖动时鼠标的偏移量(一般用在拖动的事件接口中)
dragging:是否处于拖动状态
enterEventCamera:鼠标进入时的事件相机
pressEventCamera:鼠标按下时的事件相机
pointerDrag:拖动的物体(一般用在拖动接口里)
pointerEnter:进入的物体
pointerPress:
pointerCurrentRaycast:鼠标当前的射线检测结果
pointerPressRaycast:鼠标按下时的射线检测结果
scrollDelta:鼠标滚轮的
使用EvenData类的参数时,首先要考虑有无意义
例如,在鼠标进入的事件接口里,无法获得拖动的物体
    public void OnPointerEnter(PointerEventData eventData)
{
//Debug.Log("eventData.delta.name" + eventData.pointerDrag.name);//报错:在鼠标进入的事件接口里,无法获得拖动的物体
}

Unity3D学习笔记(二十三):事件接口、虚拟摇杆、层级管理和背包系统

射线检测结果:按下结果和当前结果是有差别的

    public void OnPointerUp(PointerEventData eventData)
{
Debug.Log("当前的结果:" + eventData.pointerCurrentRaycast.gameObject.name);
Debug.Log("按下的结果:" + eventData.pointerPressRaycast.gameObject.name);
}

Unity3D学习笔记(二十三):事件接口、虚拟摇杆、层级管理和背包系统

RaycastResult - gameObject:一般情况下,判断检测结果是谁的(常用)
连续点击的次数,在一定时间间隔内,会累积计数,超过时间间隔则归零重新计数
    public void OnPointerClick(PointerEventData eventData)
{
Debug.Log("点击次数:" + eventData.clickCount);
}

Unity3D学习笔记(二十三):事件接口、虚拟摇杆、层级管理和背包系统

鼠标有球形滚轮,数值是二维的

Unity3D学习笔记(二十三):事件接口、虚拟摇杆、层级管理和背包系统

虚拟摇杆案例

Unity3D学习笔记(二十三):事件接口、虚拟摇杆、层级管理和背包系统

画布设置1280x720

Unity3D学习笔记(二十三):事件接口、虚拟摇杆、层级管理和背包系统

轮盘功能

Unity3D学习笔记(二十三):事件接口、虚拟摇杆、层级管理和背包系统

轮盘的代码逻辑

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
//1、鼠标在摇杆背景下按下的时候,需要把摇杆移动到鼠标按下的位置
//2、鼠标在拖动的时候,摇杆需要跟随鼠标移动
//3、鼠标松开的时候,摇杆回到中心位置
//4、摇杆的拖动范围是一个圆形区域
//1)、鼠标在圆形区域内,摇杆跟着鼠标移动
//2)、鼠标超出圆形区域,摇杆要在圆的边缘
//5、默认情况摇杆是隐藏的,当鼠标按下时显示,只有在屏幕左下方有效
//创建一张透明图片,在屏幕的左下方
//当在这个透明图片的区域内按下时,整个摇杆的轮盘到鼠标的位置,并且显示
//松开鼠标时,隐藏轮盘
public class Rocker : MonoBehaviour,
IDragHandler,
IPointerDownHandler,
IPointerUpHandler
{
private GameObject handler;//摇杆的句柄,也就是跟随鼠标移动的物体
private GameObject rocker;//摇杆的轮盘
private float r = 90f;//圆形区域的半径
private RectTransform handlerParent;//句柄的父物体的Rect Transform
private RectTransform rockerParent;//轮盘的父物体的Rect Transform
private Vector2 outPos;//转换之后的位置坐标
private void Awake()
{
handler = GameObject.Find("HandlerBig/HandlerSmall");
rocker = GameObject.Find("HandlerBig"); ;
//找到父物体的Rect Transform
handlerParent = handler.transform.parent as RectTransform;
rockerParent = handler.transform.parent as RectTransform;
}
public void OnDrag(PointerEventData eventData)
{
//拖动时,遥感句柄跟随鼠标移动
MoveHandler(eventData);
}
public void OnPointerDown(PointerEventData eventData)
{
PlayerMove.movespeed = 0.1f;
//按下时,轮盘显示,轮盘到鼠标的位置,同时轮盘在鼠标的位置
rocker.SetActive(true);
//转换轮盘的坐标
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(
rockerParent,
eventData.position,
eventData.pressEventCamera,
out outPos
))
{
rocker.transform.localPosition = outPos;
}
//按下时,遥感句柄移到鼠标位置
MoveHandler(eventData);
}
public void OnPointerUp(PointerEventData eventData)
{
//抬起时,轮盘隐藏
rocker.SetActive(false);
//抬起时,遥感句柄回到中心位置
rocker.transform.localPosition = Vector3.zero;
PlayerMove.movespeed = 0f;
}
/// <summary>
/// 封装好的移动句柄的方法
/// </summary>
/// <param name="eventData"></param>
void MoveHandler(PointerEventData eventData)
{
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(
handlerParent,
eventData.position,
eventData.pressEventCamera,
out outPos
))
{
//判断鼠标在圆内还是圆外,通过圆的中心点指向鼠标点的向量的模长来判断
//1、计算圆心指向鼠标向量的模长
//Vector2 temp = outPos - Vector.zero;//outPos就是从圆心指向鼠标的向量
if (outPos.magnitude >= r)
{
//计算圆心指向鼠标的方向 outPos.normalized
//最终位置 - 原点位置 + 在圆心指向鼠标的方向上,移动半径个距离的向量
//Vector2 temp = outPos.normalized * r + Vector3.zero;
Vector2 temp = outPos.normalized * r;
handler.transform.localPosition = temp;
}
else
{
handler.transform.localPosition = outPos;
}
}
}
// Use this for initialization
void Start()
{
rocker.SetActive(false);//默认隐藏
}
// Update is called once per frame
void Update()
{
}
}
在C#中,<summary> 标记应当用于描述类型或类型成员。 生成<summary>注释的方法很简单,在方法之前输入 /// 就会自动生成。
移动的功能
Unity3D学习笔记(二十三):事件接口、虚拟摇杆、层级管理和背包系统

移动的代码逻辑

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMove : MonoBehaviour {
public static float movespeed = 0.1f;
public GameObject handler;//遥感句柄
private Vector3 moveDir;
// Use this for initialization
void Start () { } // Update is called once per frame
void Update () {
//计算圆心指向摇杆的向量
//Vector3 temp = handler.transform.localPosition - Vector3.zero;
//temp = handler.transform.localPosition
moveDir.x = handler.transform.localPosition.x;
moveDir.y = ;
moveDir.z = handler.transform.localPosition.y;
transform.Translate(moveDir * Time.deltaTime * movespeed);
}
}

层级管理

Unity3D学习笔记(二十三):事件接口、虚拟摇杆、层级管理和背包系统

代码操作层级

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LayerManager : MonoBehaviour {
private GameObject red;
private GameObject yellow;
private GameObject blue;
// Use this for initialization
void Start () {
red = GameObject.Find("Red");
yellow = GameObject.Find("Yellow");
blue = GameObject.Find("Blue");
//red.transform.SetSiblingIndex(2);
int temp = red.transform.GetSiblingIndex();
red.transform.SetSiblingIndex(blue.transform.GetSiblingIndex());
blue.transform.SetSiblingIndex(temp);
} // Update is called once per frame
void Update () { }
}
背包案例
Grid Layout Group(网格自动布局)
Padding:距离边界的距离
Cell Size:子物体元素的大小
Spacing:元素间的间隔、
Start Corner:第一个元素的位置,起点位置
Start Axis:排列的轴向
Child Alignment:对其方式
Constraint:约束,没有约束,
----Fixed Row Count:约束行数
----Fixed Column Count:约束列数
注意:9元素,3行4行一样,拿走1个会缺一块,整列拿走重排又会多出第5行
背包布局
Unity3D学习笔记(二十三):事件接口、虚拟摇杆、层级管理和背包系统

背包拖动

Unity3D学习笔记(二十三):事件接口、虚拟摇杆、层级管理和背包系统

拖动的代码逻辑

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using UnityEngine.EventSystems;
//1、控制物品的拖动
//2、显示物品
public class GridUI : MonoBehaviour,
IDragHandler,
IBeginDragHandler,
IEndDragHandler
{
public Transform tempParent;//临时的父节点
public string imageName;//物体图片的名字,如果名字不为“”时有物品,为“”时没有物品
private Image image;//显示物品的组件,拖动的也是他
private RectTransform imageParent;
private Vector2 outPos;
private Vector2 offSet;//鼠标开始拖动时,距离图片中心点的偏移量
private void Awake()
{
image = transform.Find("Image").GetComponent<Image>();
image.raycastTarget = false;//关闭image的射线检测,避免挡住Grid
imageParent = tempParent as RectTransform;
}
public void OnDrag(PointerEventData eventData)
{
if (imageName == "")
{
return;
}
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(
imageParent,
eventData.position,
eventData.enterEventCamera,
out outPos
))
{
image.transform.localPosition = outPos - offSet;
}
}
public void OnBeginDrag(PointerEventData eventData)
{
if (imageName == "")
{
return;
}
//开始时,把图片放在临时的父节点上,保证拖动的图片永远显示在最前面
image.transform.parent = tempParent;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(
imageParent,
eventData.position,
eventData.enterEventCamera,
out outPos
))
{
//计算鼠标距离图片中心点的偏移量
offSet = outPos - new Vector2(image.transform.localPosition.x, image.transform.localPosition.y);
}
}
public void OnEndDrag(PointerEventData eventData)
{
if (imageName == "")
{
return;
}
//结束时,需要把图片的父节点还原,位置也需要归零
image.transform.parent = transform;
//image.transform.SetParent(transform);
image.transform.localPosition = Vector3.zero;
//拖动结束时,判断当前的鼠标位置是否在格子上
if (eventData.pointerCurrentRaycast.gameObject != null &&
eventData.pointerCurrentRaycast.gameObject.CompareTag("Grid"))
{
Debug.Log("格子:" + eventData.pointerCurrentRaycast.gameObject.name);
//把自己的图片给对方,把对方的拿过来
GridUI target = eventData.pointerCurrentRaycast.gameObject.GetComponent<GridUI>();
//把自己的图片名字设置给目标,temp就是对方的图片名字
string temp = target.SetSpriteName(this.imageName);
//然后把对方的图片名字设置给自己
this.SetSpriteName(temp);
}
else
{
Debug.Log("不是格子");
}
}
void UpdateItem()
{
if (imageName == "")
{
image.enabled = false;
}
else
{
image.enabled = true;
if (image.sprite.name != imageName)
{
Sprite sp = Resources.Load<Sprite>("Backpack/ICon/" + imageName);
image.sprite = sp;
}
}
}
//设置自己图片的名字,返回值是之前的名字
public string SetSpriteName(string str)
{
string before = imageName;
imageName = str;
UpdateItem();
return before;
}
// Use this for initialization
void Start()
{
UpdateItem();
}
// Update is called once per frame
void Update()
{
}
}

拖动的临时父节点,保证图片在最上方显示

Unity3D学习笔记(二十三):事件接口、虚拟摇杆、层级管理和背包系统

添加Grid标签

Unity3D学习笔记(二十三):事件接口、虚拟摇杆、层级管理和背包系统

给图片添加名字

Unity3D学习笔记(二十三):事件接口、虚拟摇杆、层级管理和背包系统