• 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标签

    给图片添加名字

  • 相关阅读:
    Linux学习之路——ls命令及文件权限
    解析规范格式的日志文件至List中
    Flask
    GIT和github
    常见的面试题
    python—面向对象的封装
    作业—数据类型8.20
    练习—8.17 while循环
    s7day2
    oracle 开窗分析函数和树形结构
  • 原文地址:https://www.cnblogs.com/vuciao/p/10363577.html
Copyright © 2020-2023  润新知