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

news2024/11/28 9:43:06

效果展示:

2D转3D视频

在这里插入图片描述

UI结构
在这里插入图片描述
UI组件挂载

UI结构

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

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上面

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);

            });
        }

    }

}

挂载到空物体上

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

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

这个脚本 不需要挂载

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1168739.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据库存储引擎和锁

存储引擎&#xff1a; mysal当中数据用各种不同的技术存储在文件中&#xff0c;每一种技术都使用不同的存储机制&#xff0c;索引技巧&#xff0c;锁定水平以及最终提供的不同功能和能力&#xff0c;这些就是我们说的存储引擎。 功能&#xff1a; 1、mysql将数据存储在文件系…

H5ke9

上次fetvh就一个参数url,,就是get请求 fetch还可以第二个参数对象,可以指定method:改为POST 请求头header :发送txt,servlet,json给客户端,,异步请求图片 1 这节客户端传到服务器端 2异步文件上传,两三行代码把文件传输 mouseover事件 .then()的使用 是Promise对象的一个方法…

prometheus监控告警部署(k8s内部)

一、部署prometheus 先来说明一下需要用到的组件&#xff0c;需要使用pv、pvc存放prometheus的数据,使用pvc存放数据即使pod挂了删除重建也不会丢失数据&#xff0c;使用configmap挂载prometheus的配置文件和告警规则文件&#xff0c;使用service开放对外访问prometheus服务的端…

高防IP的原理

高防IP&#xff0c;把域名解析到高防IP上(web事务只要把域名指向高防IP 即可。非web事务&#xff0c;把事务IP换成高防IP即可)一起在高防IP上设置转发规矩;所有公网流量都会走高防IP&#xff0c;通过端口协议转发的方法将用户的拜访通过高防IP转发到源站IP&#xff0c;一起将歹…

进程控制(三):进程替换

文章目录 进程控制&#xff08;三&#xff09;进程替换进程替换函数进程中的环境变量 总结 进程控制&#xff08;三&#xff09; 进程控制中的进程替换&#xff0c;下文我们学习进程替换的意义&#xff0c;以及进程替换的方式 进程替换 初步认识进程替换&#xff0c;我们先使…

Appium —— 初识移动APP自动化测试框架Appium

说到移动APP自动化测试&#xff0c;代表性的测试框架非Appium莫属&#xff0c;从今天开始我们将从APP结构解析、Appium框架学习、安卓/iOS自动化测试实战、自动遍历回归测试、自动化测试平台及持续集成&#xff0c;多个维度一起由浅入深的学废Appium 今天我们先来初步认识Appi…

远程设备常用工具:向日葵、Todesk

其实按理说远程工具例如向日葵、Todesk如果是计算机专业、计算机从业者是必须知道的一个东西&#xff0c;但是在大学期间身边知道的人是少之又少的。 向日葵、Todesk工具的优势&#xff1a;方便、快捷、速度快等等我就不过多阐述了 PS:现在我就是在学校用远程写这篇 很多时候…

使用Navicat访问宝塔中的MySQL数据库

首先放开数据库权限 然后放开3306端口 数据库默认端口是3306&#xff0c;如果改了&#xff0c;这里就填改的那个端口 连接数据库 复制数据库用户名和密码 填入Navicat中&#xff0c;主机只需要填IP即可 连接成功

动手学深度学习——残差网络ResNet(原理解释+代码详解)

残差网络ResNet 1. 函数类2. 残差块3. ResNet模型4. 训练模型 ResNet为了解决“新添加的层如何提升神经网络的性能”&#xff0c;它在2015年的ImageNet图像识别挑战赛夺魁 它深刻影响了后来的深度神经网络的设计&#xff0c;ResNet的被引用量更是达到了19万。 1. 函数类 假…

Android studio新版本多渠道打包配置

最近公司套壳app比较多 功能也都一样只有地址&#xff0c;和app名字还有icon不一样 签名文件也是一样的,所以就研究了多渠道打包 配置如下&#xff1a; 在app下build.gradle配置 因为最新版as中禁用了BuildConfig 所以我们需要手动配置一下 android { //TODO 其他省略buildFe…

网络编程套接字(二)

目录 简单的TCP网络程序服务端创建套接字服务端绑定服务端监听服务端获取连接服务端处理请求单执行流服务器的弊端 多进程版TCP网络程序捕捉SIGCHLD信号让孙子进程提供服务多线程版的TCP网络程序客户端创建套接字客户端链接服务器客户端发起请求 线程池版的TCP网络程序 简单的T…

SpringBoot整合数据库版本管理工具Liquibase,赶紧整起来!

SpringBoot整合数据库版本管理工具Liquibase 背景一、什么是数据库版本管理工具&#xff1f;数据库版本管理工具主要特性什么是数据库版本管理工具Flyway和Liquibase对比及选型 二、Liquibase整合步骤1.引入pom依赖2.配置application.yml3.新建master.xml&#xff08;用于配置你…

使用pandas处理excel文件【Demo】

一、代码示例 import pandas as pd from pandas import Series,DataFrame from pandasql import sqldf import matplotlib.pyplotidInfos DataFrame(pd.read_excel(home_data.xlsx))print(idInfos.head(2))print(idInfos.dtypes)# print(idInfos[:][姓名]) # 自定义一个函数s…

QTreeView 常见节点操作

目录 1、节点遍历 2、设置当前选中项 3、树节点数据绑定 4、树节点自定义样式 5、数据检索 6、获取当前选中项 QTreeView作为项目最经常使用的空间&#xff0c;常用接口和操作必须熟悉熟悉在熟悉&#xff01;&#xff01;&#xff01; 1、节点遍历 void ParamSettingDl…

【python VS vba】(3) 在python直接调用vba脚本

目录 0 前言 1 VBA 内容 1.1 EXCEL这边VBA的内容 1.2 VBA的测试代码 2 python 调用 2.1 python 调用VBA的过程和结果 2.2 代码 0 前言 前面写了这么多&#xff0c;没想到&#xff0c;其实py是可以直接支持VBA的 python的模块import xlwings&#xff0c;可以让python直…

Leetcode1128. 等价多米诺骨牌对的数量

Every day a Leetcode 题目来源&#xff1a;1128. 等价多米诺骨牌对的数量 解法1&#xff1a;暴力 代码&#xff1a; class Solution { public:int numEquivDominoPairs(vector<vector<int>> &dominoes){int n dominoes.size(), count 0;for (int i 0;…

理解训练深度前馈神经网络的难度【PMLR 2010】

论文地址&#xff1a;Excellent-Paper-For-Daily-Reading/summarize at main 类别&#xff1a;综述 时间&#xff1a;2023/11/03 摘要 这篇论文比较久了&#xff0c;但仍能从里面获得一些收获&#xff0c;论文主要是讨论并研究了不同的非线性激活函数的影响&#xff0c;sig…

Java与Redis的集成以及Redis中的项目应用

一、Java连接Redis Redis与MySQL都是数据库&#xff0c;java操作redis其实跟操作mysql的过程是一样的。 1.1 导入依赖 打开IDEA&#xff0c;进入Java项目&#xff0c;导入pom依赖&#xff0c;代码如下&#xff1a; <dependency><groupId>redis.clients</gro…

threejs 2. 辅助对象

ArrowHelper 箭头 const arrowHelper new THREE.ArrowHelper(new THREE.Vector3( 1, 2, 0 ).normalize(), // 方向向量必须是单位向量,默认值为(0,0,1)new THREE.Vector3( 0, 0, 0 ), // 起点,默认值为(0,0,0)1, // 长度,默认值为10xffff00, // 颜色,默认值为0xffff00undefine…

JavaSE基础 --- 类与对象

1.类与对象的定义 类是一种抽象的数据类型&#xff0c;它描述了一类对象的行为和状态。例如&#xff0c;我们可以定义一个名为“Dog”的类&#xff0c;它描述了狗这类动物的一般特性&#xff0c;如颜色、品种等状态&#xff0c;以及跑、叫等行为。 对象则是类的实例&#xff0c…