unity 从UI上拖出3D物体,(2D转3D)

效果展示:

2D转3D视频

UI结构

UI组件挂载

UI结构

这个脚本挂载到 3D物体身上

csharp 复制代码
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);
        }
    }
}

挂载到UI上面

csharp 复制代码
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);

            });
        }

    }

}

挂载到空物体上

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

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

这个脚本 不需要挂载

csharp 复制代码
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
}

可以根据自己需求去修改,比如 动态生成背包里的类型和元素,

Demo上传了,可以下载,

相关推荐
Thomas_YXQ1 小时前
Unity3D Huatuo技术原理剖析详解
unity·unity3d·游戏开发·性能调优·热更新
小板凳-BGM1 小时前
C# 第二阶段 modbus
开发语言·ui·c#
zh路西法4 小时前
【C++决策和状态管理】从状态模式,有限状态机,行为树到决策树(二):从FSM开始的2D游戏角色操控底层源码编写
c++·游戏·unity·设计模式·状态模式
UI设计兰亭妙微5 小时前
教育行业 UI 设计基础篇:简洁直观的风格打造
ui
隐形喷火龙5 小时前
element ui--下拉根据拼音首字母过滤
前端·vue.js·ui
谷谷地图下载器5 小时前
【全网首发】台湾省模型数据“去水印“说明(3Dtiles和osgb格式),全台湾省的模型数据,全域无水印AI处理,支持所有模型格式
3d
橘子遇见BUG8 小时前
Unity Shader学习日记 part 3 线性代数--矩阵变换
学习·线性代数·unity·矩阵·图形渲染
Artistation Game10 小时前
一、c#基础
游戏·unity·c#·游戏引擎
成都渲染101云渲染666611 小时前
云渲染,Enscape、D5、Lumion渲染提速教程
运维·服务器·unity·电脑·图形渲染·blender·houdini
Cachel wood13 小时前
Django REST framework (DRF)中的api_view和APIView权限控制
javascript·vue.js·后端·python·ui·django·前端框架