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上传了,可以下载,

相关推荐
CG_MAGIC1 天前
从光影到物理渲染:Substance Sampler 照片转材质
3d·材质·贴图·uv·建模教程·渲云渲染
nnsix1 天前
Unity 贴图压缩格式 笔记
笔记·unity·贴图
文创工作室1 天前
Adobe Illustrator 中文
ui·adobe·illustrator
ysn111111 天前
搭建状态同步框架的实践心得
unity·架构
烛衔溟1 天前
HarmonyOS 基础 UI 构建 —— 组件、布局与沉浸式效果
ui·华为·harmonyos
jinxindeep1 天前
PhysX-Omni:面向刚体、形变体与铰接体的统一仿真就绪 3D 生成
3d
一次旅行1 天前
CopilotKit实战:用生成式UI打造智能Agent前端
前端·人工智能·ui
weixin_441940011 天前
【Unity教程】使用vuforia创建简单的AR实例
unity·游戏引擎·ar
郝学胜-神的一滴1 天前
[简化版 GAMES 101] 计算机图形学 12:可见性与 Z‑Buffer 深度缓存
unity·godot·图形渲染·three.js·opengl·unreal
gqk012 天前
Delegate.Target/ Method
前端·ui·xhtml