zoukankan      html  css  js  c++  java
  • 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标签

    给图片添加名字

  • 相关阅读:
    解决SharePoint 文档库itemadded eventhandler导致的上传完成后,编辑页面保持报错的问题,错误信息为“该文档已经被编辑过 the file has been modified by...”
    解决SharePoint 2013 designer workflow 在发布的报错“负载平衡没有设置”The workflow files were saved but cannot be run.
    随机实例,随机值
    Spring4笔记
    struts2笔记(3)
    struts2笔记(2)
    获取文本的编码类型(from logparse)
    FileUtil(from logparser)
    DateUtil(SimpleDateFormat)
    struts2笔记
  • 原文地址:https://www.cnblogs.com/vuciao/p/10363577.html
Copyright © 2011-2022 走看看