unity中 使用IDragHandler拖动交换子物体

这篇具有很好参考价值的文章主要介绍了unity中 使用IDragHandler拖动交换子物体。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

using DG.Tweening;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using VRSightCheck.Scripts;

public class SwapPanel : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
    /// <summary>
    /// 是否已经响应拖拽
    /// </summary>
    public static bool isDrag = false;

    private List<RectTransform> items;  // 子物体数组

    private int currentIndex = -1;  // 当前需要交换位置的子物体索引

    /// <summary>
    /// 开始点击gameobject
    /// </summary>
    private GameObject mStartGo;

    /// <summary>
    /// 开始坐标
    /// </summary>
    private Vector3 startPos = Vector3.zero;

    /// <summary>
    /// 结束点击gameobject
    /// </summary>
    private GameObject mEndGo;

    /// <summary>
    /// 结束坐标
    /// </summary>
    private Vector3 endPos = Vector3.zero;

    /// <summary>
    /// 是否正在移动
    /// </summary>
    private bool isMove = false;

    /// <summary>
    /// 移动时间
    /// </summary>
    private const float MOVE_TIME = 0.2f;

    /// <summary>
    /// 动画
    /// </summary>
    private Tweener[] tws;

    /// <summary>
    /// 成功换位置事件
    /// </summary>
    private Action<GameObject, GameObject> ChangeSucAct;

    private void Awake()
    {
        items = new List<RectTransform>();
        currentIndex = -1;
        mStartGo = null;
        startPos = Vector3.zero;
        mEndGo = null;
        endPos = Vector3.zero;
        isMove = false;
        tws = new Tweener[3];
        ChangeSucAct = new Action<GameObject, GameObject>(ChangeSuc);
    }

    /// <summary>
    /// 清除子物体
    /// </summary>
    public void ClearItem()
    {
        items.Clear();
    }

    /// <summary>
    /// 添加子物体
    /// </summary>
    public void AddItem(RectTransform it)
    {
        items.Add(it);
    }

    /// <summary>
    /// 设置委托
    /// </summary>
    /// <param name="act"></param>
    public void SetChangeSucAct(Action<GameObject, GameObject> act)
    {
        ChangeSucAct = act;
    }

    public void OnBeginDrag(PointerEventData eventData)
    {
        //Debug.Log("OnBeginDrag=======================>");
        if (items.Count == 0 || isMove || isDrag) return;
        // 检查触摸点是否在另一个子物体上,并根据索引信息交换两个子物体的位置
        List<RaycastResult> results = new List<RaycastResult>();
        EventSystem.current.RaycastAll(eventData, results);
        if (results.Count == 0) return;
        List<GameObject> gos = new List<GameObject>();
        for (int i = 0; i < results.Count; i++)
        {
            gos.Add(results[i].gameObject);
        }
        // 检查触摸点是否在其中一个子物体上
        for (int i = 0; i < items.Count; i++)
        {
            //if (RectTransformUtility.RectangleContainsScreenPoint(items[i], eventData.position, UICanvasManager.Instance.CameraCanvas))
            if(gos.Contains(items[i].gameObject))
            {
                currentIndex = i;
                mStartGo = items[i].gameObject;
                startPos = items[i].position;

                isDrag = true;
                break;
            }
        }
    }

    public void OnDrag(PointerEventData eventData)
    {
        //Debug.Log("OnDrag=======================>");
        if (items.Count == 0 || isMove) return;
        
        if (currentIndex >= 0)
        {
            // 根据触摸点的移动距离计算出当前子物体应该移动的位置
            Vector2 offset = eventData.delta / transform.localScale.x;
            if(items.Count > currentIndex)
            {
                items[currentIndex].anchoredPosition += offset;
            }
        }
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        //Debug.Log("OnEndDrag=======================>");
        if (items.Count == 0 || isMove || mStartGo == null) return;
        
        for (int i = 0; i < items.Count; i++)
        {
            if (i != currentIndex && RectTransformUtility.RectangleContainsScreenPoint(items[i], eventData.position , UICanvasManager.Instance.CameraCanvas))
            {
                mEndGo = items[i].gameObject;
                endPos = items[i].position;
                Change();
                break;
            }
        }
        if (mEndGo == null)
        {
            MoveBack();
        }
        currentIndex = -1;

        isDrag = false;
    }

    /// <summary>
    /// 清除开始点击gameObject
    /// </summary>
    void ClearStartGo()
    {
        if (mStartGo == null) return;
        mStartGo.transform.localScale = Vector3.one;
        mStartGo = null;
    }


    /// <summary>
    /// 未成功换位置,返回
    /// </summary>
    void MoveBack()
    {
        isMove = true;

        tws[0] = mStartGo.transform.DOMove(startPos, MOVE_TIME);

        tws[0].SetEase(Ease.Linear);
        tws[0].OnComplete( () =>{
            ClearStartGo();
            isMove = false;
        });

        if (mEndGo != null)
        {
            mEndGo = null;
        }
    }

    /// <summary>
    /// 替换位置
    /// </summary>
    void Change()
    {
        isMove = true;
        int idx = mStartGo.transform.GetSiblingIndex();
        mStartGo.transform.SetSiblingIndex(mEndGo.transform.GetSiblingIndex());
        mEndGo.transform.SetSiblingIndex(idx);

        tws[1] = mStartGo.transform.DOMove(endPos, MOVE_TIME);
        tws[1].SetEase(Ease.Linear);
        tws[2] = mEndGo.transform.DOMove(startPos, MOVE_TIME);
        tws[2].SetEase(Ease.Linear);
        tws[2].OnComplete(() => {
            Debug.Log("替换位置================>" + ChangeSucAct);
            ChangeSucAct(mStartGo, mEndGo);
            ClearStartGo();
            isMove = false;
            mEndGo = null;
        });
    }


    private void OnDestroy()
    {
        //停止动画
        for (int i = 0; i < tws.Length; i++)
        {
            if (tws[i] != null) tws[i].Kill();
        }
    }


    private void ChangeSuc(GameObject arg1, GameObject arg2)
    {

    }
}文章来源地址https://www.toymoban.com/news/detail-751830.html

到了这里,关于unity中 使用IDragHandler拖动交换子物体的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • unity拖拽背包物体,并交换两个物体的信息

    前几天看了一个教程,背包物品交换。由于教程中使用的是ngui,很多代码需要使用UGUI重新写,因此苦恼了几天。 我遇到了以下问题,在此详细罗列,以记录错误的原因和修改的方法,供日后阅读查找。 一、背包中的物品在拖拽之后放入指定的空格子(问题1:不知道该怎么

    2024年04月15日
    浏览(35)
  • 使用团结引擎开发Unity 3D射击游戏

           本案例是初级案例,意在引导想使用unity的初级开发者能较快的入门,体验unity开发的方便性和简易性能。       本次我们将使用团结引擎进行开发,帮助想体验团结引擎的入门开发者进行较快的环境熟悉。      本游戏是一个俯视角度的射击游戏。主角始终位于屏幕

    2024年01月19日
    浏览(52)
  • Unity 语法详解之查找游戏物体的方法(含查找隐藏物体)

    为了更好的看懂,有一个非常基础的知识,如果不知道可以移步去了解一下哦 unity | gameobject和transform的区别和关联通俗解释_gameobject transform_菌菌巧乐兹的博客-CSDN博客 一、前情提要 大写的 GameObject是个类,里面写满了物体有关的代码 小写的 gameObject指的是物体本身 大写的

    2024年02月12日
    浏览(33)
  • 【Unity3D】Unity 脚本 ③ ( C# 脚本的执行入口函数 | 获取当前游戏物体及物体名称 | 获取游戏物体的 Transform 组件数据 | UnityEngine 命名空间简介 )

    在 C# 脚本中控制 游戏物体 GameObject 运动 , 要先获取该物体 , 然后 修改其 Transform 组件的属性 ; 在 游戏开始运行后 , 会自动执行 游戏物体 GameObject 上的 C# 组件代码 , 程序入口是 MonoBehaviour#Start() 函数 ; 在 C# 脚本中 , 主要的内容都在 Start() 函数 中实现 ; 在 C# 脚本中 , 游戏物体

    2023年04月12日
    浏览(59)
  • Unity上接入手柄,手柄控制游戏物体移动

    1、unity软件上安装system input 组件。菜单栏【window】-【Packag Manager】打开如下界面,查找Input System,并且安装。 2、安装成功后插入手柄到windows上,打开菜单栏上【window】--【Analysis】--【Input Debuger】 进入Input Debug界面,可以看到手柄设备能被Unity识别。 3、双击【XinputControllerW

    2024年04月15日
    浏览(34)
  • Unity3D实现UI的单击、双击、拖动状态判断

    这篇文章就来实现UI的单击、双击、按压、拖动的不同状态判断。不定时更新Unity开发技巧,觉得有用记得一键三连哦。 示例、 判断单击和双击,主要是判断点击的次数。 UI的点击事件,需要继承UI的点击事件接口,重写点击事件即可。 UI点击事件接口: 3-1-1 所引用的命名空

    2024年01月20日
    浏览(35)
  • 解决Unity中UI的中心锚点无法拖动修改问题(笔记)

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 记录一下UI中容易忘记的细节。

    2024年02月08日
    浏览(31)
  • Unity UI不被3D物体遮挡

    UI Shader: 用该Shader创建一个材质,将该材质挂到不被模型遮挡的UI上。 TextMeshPro 设置: 修改TextMesh Pro/Shaders/TMP_SDF.shader 修改如下:

    2024年02月07日
    浏览(40)
  • unity UI 跟随3D物体移动

     

    2024年02月11日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包