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

事件接口
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);//报错:在鼠标进入的事件接口里,无法获得拖动的物体
    }

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

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

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

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

虚拟摇杆案例

画布设置1280x720

轮盘功能

轮盘的代码逻辑

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>注释的方法很简单,在方法之前输入 /// 就会自动生成。
移动的功能

移动的代码逻辑

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 = 0;
        moveDir.z = handler.transform.localPosition.y;
        transform.Translate(moveDir * Time.deltaTime * movespeed);
    }
}

层级管理

代码操作层级

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行
背包布局

背包拖动

拖动的代码逻辑

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()
    {
    }
}

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

添加Grid标签

给图片添加名字

猜你喜欢

转载自www.cnblogs.com/ciaowoo/p/10363577.html