Unity Drag 3D objects from the UI (2D to 3D)

Show results:

2D to 3D video

Insert image description here

UI structure
Insert image description here
UI structure configuration

UI structure

This script is mounted on the 3D object

using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DragGame : MonoBehaviour
{
    
    
    [HideInInspector]
    public bool isDrag;



   
    public int z=8;
    void Start()
    {
    
    
      

    }


    // Update is called once per frame
    void Update()
    {
    
    

    }


    IEnumerator OnMouseDown()
    {
    
    
        Vector3 screenSpace = Camera.main.WorldToScreenPoint(transform.position);//三维物体坐标转屏幕坐标
        //将鼠标屏幕坐标转为三维坐标,再计算物体位置与鼠标之间的距离
        var offset = transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenSpace.z));
        isDrag = true;
        while (Input.GetMouseButton(0))
        {
    
    
            
            Vector3 curScreenSpace = new Vector3(Input.mousePosition.x, Input.mousePosition.y, z);
            var curPosition = Camera.main.ScreenToWorldPoint(curScreenSpace) + offset;
            transform.position = curPosition;
            yield return new WaitForFixedUpdate();
        }
    }
    IEnumerator OnMouseUp()
    {
    
    
        isDrag = false;

        Whereabouts();

        yield return 0;
    }

    private void OnTriggerEnter(Collider other)
    {
    
    
        //物体拖出后  碰到其他物体的逻辑
       
    }
    public void Whereabouts()
    {
    
    
        RaycastHit hit;
        //参数:当前物体,世界空间的方向,碰撞信息,最大距离
        if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.down), out hit, Mathf.Infinity))
        {
    
    
            transform.DOMove(new Vector3(hit.point.x, hit.point.y + (transform.localScale.y / 2), hit.point.z), 0.5f);
        }
    }
}

Mount to UI

using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class KnapsackPanel : MonoBehaviour
{
    
    
    List<GameObject> scrollList = new List<GameObject>();//容量列表
    List<Toggle> toggles = new List<Toggle>();//背包类型列表
    GameObject to, sv, im;

    GameObject toggle;
    GameObject scrollView;
    Toggle Switch;
    public void Start()
    {
    
    
        toggle = transform.Find("GameObject/ToggleGroup/Toggle").gameObject;
        scrollView = transform.Find("GameObject/ScrollGroup/Scroll View").gameObject;
        Switch = transform.Find("GameObject/BG/Switch").GetComponent<Toggle>();
        RectTransform tf = transform.Find("GameObject").GetComponent<RectTransform>();
        Switch.onValueChanged.AddListener((arg) =>
        {
    
    
            if (arg)
            {
    
    
                tf.transform.DOLocalMoveX(tf.transform.localPosition.x - tf.rect.width, 1f);
            }
            else
            {
    
    
                tf.transform.DOLocalMoveX(tf.transform.localPosition.x + tf.rect.width, 1f);
            }
        });

        CreateKnapsack();


    }
  
    /// <summary>
    /// 生成背包内容
    /// </summary>
    public void CreateKnapsack()
    {
    
    
           Toggle[] tog = transform.Find("GameObject/ToggleGroup").GetComponentsInChildren<Toggle>();
        for (int i = 0; i < tog.Length; i++)
        {
    
    
            toggles.Add(tog[i]);
        }
           
          ScrollRect[] scrollbars= transform.Find("GameObject/ScrollGroup").GetComponentsInChildren<ScrollRect>(true);
        for (int i = 0; i < scrollbars.Length; i++)
        {
    
    
            scrollList.Add(scrollbars[i].gameObject);
          
            Transform content = scrollbars[i].transform.Find("Viewport/Content");
           
            for (int j = 0; j < content.childCount; j++)
            {
    
    
                int t = j;
               
                GameObject game = Resources.Load<GameObject>(content.GetChild(t).name);//需要拖拽出的3D物体
           
                DragGameCommand drag = new DragGameCommand(content.GetChild(t).gameObject, game, j, () => {
    
     Switch.isOn = true; });
                //dragGames.Add(drag);
            }
        }
      
           
        

        //类型切换事件绑定
        for (int i = 0; i < toggles.Count; i++)
        {
    
    
            
            int t = i;
            toggles[i].onValueChanged.RemoveAllListeners();
            toggles[i].onValueChanged.AddListener((arg) =>
            {
    
    
                scrollList[t].SetActive(arg);

            });
        }

    }

}

Mount to empty object

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class IEnumeratorManager : MonoBehaviour
{
    
    
    public static IEnumeratorManager instance;
    void Start()
    {
    
    
        instance = this;
    }
}

This script does not need to be mounted

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class DragGameCommand 
{
    
    
    public GameObject instance;//UI图标
    public GameObject dragGame;//拖拽的物体
    GameObject game;//要创建的物体

    public GameObject scrollView;//对应的背包分类界面(拖回物体到UI的范围)
    public int z;//物体的Z轴距离
    int index;//在背包里排列的索引
    Action dragEnd;
    public DragGameCommand(GameObject image, GameObject _game, int _index, Action _dragEnd)
    {
    
    
        instance = image;
        game = _game;
        scrollView = image.transform.parent.parent.parent.gameObject;
        AddListener();
        z = 8;
        int index = _index;
        dragEnd = _dragEnd;
        AddEvent(scrollView.transform);
    }
    #region 背包拖出物体
    /// <summary>
    /// 物体从UI 拖出的事件
    /// </summary>
    private void AddListener()
    {
    
    
      //给Image 动态添加 拖拽 事件
        EventTrigger eventTrigger = instance.gameObject.AddComponent<EventTrigger>();

        EventTrigger.Entry beginDrag = new EventTrigger.Entry();
        beginDrag.eventID = EventTriggerType.BeginDrag;
        beginDrag.callback.AddListener((v) =>
        {
    
    
            Debug.Log("开始拖拽");
            Image dragImage = instance.GetComponent<Image>();
            dragImage.raycastTarget = false;//UI置灰
            dragImage.color = new Color(1, 1, 1, 0.5f);
            string name = game.name;
            dragGame = GameObject.Instantiate(game);//创建3D物体
            DragGame dg = dragGame.GetComponent<DragGame>();
            dg.z = z;
            dragGame.name = name;
            ObjFollowMouse(dragGame);//让物体跟随鼠标

        });


        EventTrigger.Entry drag = new EventTrigger.Entry();
        drag.eventID = EventTriggerType.Drag;
        drag.callback.AddListener((v) =>
        {
    
    
          
            ObjFollowMouse(dragGame);//让物体跟随鼠标
        });

        EventTrigger.Entry endDrag = new EventTrigger.Entry();
        endDrag.eventID = EventTriggerType.EndDrag;
        endDrag.callback.AddListener((v) => {
    
    
            dragEnd?.Invoke();
            dragGame.GetComponent<DragGame>().Whereabouts();//下落
        });


        eventTrigger.triggers.Add(beginDrag);
        eventTrigger.triggers.Add(drag);
        eventTrigger.triggers.Add(endDrag);

    }
    /// <summary>
    /// UI跟随鼠标
    /// </summary>
    /// <param name="eventData"></param>
    private void ObjFollowMouse(GameObject gameObject)
    {
    
    

        gameObject.transform.position = Camera.main.ScreenToWorldPoint(Input.mousePosition + new Vector3(0, 0, z));
    }
    #endregion

    #region 物体放回背包
    Coroutine coroutine;
    //绑定背包界面鼠标移入和移出事件
    public void AddEvent(Transform viewport)
    {
    
    
    
        EventTrigger eventr = viewport.gameObject.AddComponent<EventTrigger>();//给拖入范围UI,添加 鼠标进入和鼠标离开事件
        EventTrigger.Entry pointerEnter = new EventTrigger.Entry();
        pointerEnter.eventID = EventTriggerType.PointerEnter;
        pointerEnter.callback.RemoveAllListeners();
        //鼠标进入UI
        pointerEnter.callback.AddListener((v) =>
        {
    
    
            if (dragGame != null)//已经拖出来的物体
            {
    
    

                DragGame dragGame1 = dragGame.GetComponent<DragGame>();
                if (dragGame1.isDrag)//物体正在拖拽中
                {
    
    
                    coroutine =IEnumeratorManager.instance. StartCoroutine(OnMouse(index));//放回背包事件

                }
            }

        });
        EventTrigger.Entry pointerExit = new EventTrigger.Entry();
        pointerExit.eventID = EventTriggerType.PointerExit;
        pointerExit.callback.RemoveAllListeners();
        //鼠标离开UI
        pointerExit.callback.AddListener((v) =>
        {
    
    
            if (coroutine != null)
            {
    
    
                IEnumeratorManager.instance.StopCoroutine(coroutine);

            }
        });



        eventr.triggers.Add(pointerEnter);
        eventr.triggers.Add(pointerExit);
    }

    /// <summary>
    /// 物体放回背包
    /// </summary>
    /// <param name="index"></param>
    /// <returns></returns>
    IEnumerator OnMouse(int index)
    {
    
    

        DragGame game = dragGame.GetComponent<DragGame>();
        Image image = instance.GetComponent<Image>();
        while (true)
        {
    
    

            if (!game.isDrag && scrollView.activeInHierarchy)//物体结束拖拽 并且在对应的背包类型容量处于显示状态、
            {
    
    
                GameObject.DestroyImmediate(game.gameObject);
                image.raycastTarget = true;
                image.color = new Color(1, 1, 1, 1);
                dragGame = null;
                IEnumeratorManager.instance. StopCoroutine(coroutine);
            }
            yield return 0;
        }
    }
  
    #endregion
}

You can modify it according to your own needs, such as dynamically generating types and elements in the backpack,

The demo has been uploaded and can be downloaded.

Guess you like

Origin blog.csdn.net/o_ojjj/article/details/134202454