首页 > 其他分享 >【Unity基础】Unity中拖拽3D物体的过程分析和实现方法

【Unity基础】Unity中拖拽3D物体的过程分析和实现方法

时间:2024-12-20 12:59:36浏览次数:7  
标签:鼠标 触摸 Unity Input main 拖拽 输入 3D

我们先来分析一下Unity中拖拽物体的过程:

第一步:先检测拖拽的输入方式,可以鼠标,触摸,可以用InputManager输入,也可以 使用InputSystem输入

第二步:获取触碰点的位置,并计算offset。

第三步:在每一帧里改变物体的位置。

其实3D物体拖拽的过程可以分为上面几个清晰的步骤,而每一步都有不同的方法可以选择,尤其是在第一步和第二步,你可以根据项目需求和输入方式的不同选择合适的实现方法。下面,我会根据你的描述,对每个步骤和方法做一个详细的拆解。

第一步:检测拖拽的输入方式

这一阶段主要是检测用户的输入,具体输入方式可以有很多种,每种方式有不同的事件方法或API调用:

  1. 鼠标输入:

    • OnMouseDownOnMouseDrag:通过 Unity 自带的 MonoBehaviour 事件,适用于鼠标操作。这种方式简单直观,但对于复杂的拖拽控制可能不够灵活。

      void onm ouseDown() {
          // 记录点击时的偏移量
      }
      
      void onm ouseDrag() {
          // 获取新的鼠标位置,并移动物体
      }
      
    • Input.GetMouseButtonDownInput.GetMouseButton:通过 Input 类手动检查鼠标按钮的状态。适用于需要手动控制输入事件的场景,能够精细控制鼠标输入。

      if (Input.GetMouseButtonDown(0)) {
          // 鼠标按下时记录位置
      }
      if (Input.GetMouseButton(0)) {
          // 鼠标拖动时更新位置
      }
      
  2. Event System (UI):

    • OnBeginDragOnDragOnEndDrag

      :这些方法来自

      IDragHandler
      

      接口,适合需要与 Unity 的

      EventSystem
      

      一起工作的项目。这种方式适用于有 UI 或需要流畅交互的场景。

      public void OnBeginDrag(PointerEventData eventData) {
          // 拖拽开始,记录偏移
      }
      
      public void OnDrag(PointerEventData eventData) {
          // 拖拽过程中,根据触摸点移动物体
      }
      
      public void OnEndDrag(PointerEventData eventData) {
          // 拖拽结束
      }
      
  3. 触摸输入(适用于移动设备):

    • OnTouchBeginOnTouchMoved

      :适用于移动设备的触摸输入。这种方式通常与移动端游戏或应用的触摸交互配合使用,特别是多点触控的场景。

      void OnTouchBegin() {
          // 获取触摸开始的位置信息
      }
      
      void OnTouchMoved() {
          // 获取触摸移动的位置信息,并更新物体位置
      }
      
  4. 新输入系统(Input System):

    • Mouse.current.leftButton.wasPressedThisFrame

      :使用 Unity 的新输入系统,可以精确控制鼠标、触摸等各种输入设备。

      if (Mouse.current.leftButton.wasPressedThisFrame) {
          // 鼠标按下
      }
      

第二步:获取触碰点的位置并计算 offset

获取触碰点的位置是拖拽的关键。在 3D 场景中,通常会使用射线检测(Raycasting)或将屏幕空间的触摸位置转换为世界空间来实现。

  1. 使用 Camera.main.ScreenToWorldPoint: 将触摸或鼠标位置从屏幕空间转换为世界空间,适用于你有准确的摄像机信息,并希望直接获取物体在世界空间的位置。

    Vector3 touchPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    Vector3 offset = transform.position - touchPosition;
    
  2. 使用 Raycast: 使用射线检测可以在 3D 场景中更精确地判断鼠标点击的物体,并通过射线交点来计算物体的新位置。射线通常从摄像机位置发出,穿过鼠标或触摸点。

    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    RaycastHit hit;
    if (Physics.Raycast(ray, out hit)) {
        Vector3 touchPosition = hit.point;
        Vector3 offset = transform.position - touchPosition;
    }
    

第三步:改变物体的位置

一旦得到了触碰点和 offset,可以通过直接修改物体的位置来实现拖拽效果。

  1. 直接设置物体位置: 通过将物体的位置设置为新的触摸或鼠标位置来完成拖拽。你需要确保物体的位置在物理世界中平滑移动。

    Vector3 targetPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition) + offset;
    transform.position = targetPosition;
    
  2. 使用 Rigidbody 移动: 如果你的物体有 Rigidbody 组件,并且需要物理反馈(比如碰撞或惯性效果),可以使用物理方法来更新物体的位置。

    Rigidbody rb = GetComponent<Rigidbody>();
    Vector3 targetPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition) + offset;
    rb.MovePosition(targetPosition);
    

组合方式

根据输入方式和具体需求,第一步和第二步会有不同的组合方式。以下是一些可能的组合:

  1. 鼠标输入 + Camera.main.ScreenToWorldPoint:适合基础的桌面端拖拽,无需复杂的射线检测。
  2. 鼠标输入 + Raycast:适合需要精确控制和碰撞检测的拖拽,特别是在3D空间中。
  3. Event System + Camera.main.ScreenToWorldPoint:适合有 UI 交互需求的拖拽,能够结合 Unity 的 EventSystem
  4. 触摸输入 + Camera.main.ScreenToWorldPoint:适合移动设备,简化触摸位置的转换。
  5. 触摸输入 + Raycast:适合在 3D 空间中实现触摸拖拽,支持碰撞和精确位置控制。
  6. 新输入系统 + Raycast 或 Camera.main.ScreenToWorldPoint:适合支持多种输入设备的场景,能够灵活处理各种设备输入。

我们先将拖拽过程分为这些步骤:检测输入方式、计算触碰点位置、更新物体位置。通过不同的组合,能够满足不同的项目需求。

以下是几种常见的拖拽实现方式,结合上面提到的组合进行分析,并给出优缺点和适用场景:

1. 鼠标输入 + Camera.main.ScreenToWorldPoint

这种方式简单直观,适用于基础的桌面端拖拽,不需要过多的物理处理和碰撞检测。

示例代码:
private Vector3 offset;
private bool isDragging = false;

void onm ouseDown() {
    // 记录初始偏移量
    offset = transform.position - Camera.main.ScreenToWorldPoint(Input.mousePosition);
    isDragging = true;
}

void onm ouseDrag() {
    if (isDragging) {
        Vector3 targetPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition) + offset;
        targetPosition.z = 0; // 确保拖拽物体在二维平面上移动
        transform.position = targetPosition;
    }
}

void onm ouseUp() {
    isDragging = false;
}
优点:
  • 简单易懂:只需要使用 OnMouseDownOnMouseDrag 事件进行处理。
  • 性能较好:不需要复杂的射线检测或物理计算,适合简单的拖拽需求。
  • 适合桌面端:特别适用于桌面端的鼠标操作。
缺点:
  • 缺乏物理反馈:没有物理碰撞的处理,不能模拟物体与其他物体的碰撞反应。
  • 限制性较强:仅适用于鼠标操作,不能直接支持多点触控等复杂输入设备。
适用场景:
  • 简单的 2D 游戏或桌面应用中的拖拽需求。
  • 不需要物理交互或碰撞检测的场景。

2. 鼠标输入 + Raycast

这种方式通过射线检测来判断鼠标点击的位置,适用于3D场景中需要精确控制拖拽对象的情况。

示例代码:
private Vector3 offset;
private bool isDragging = false;

void Update() {
    if (Input.GetMouseButtonDown(0)) {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;
        if (Physics.Raycast(ray, out hit)) {
            offset = hit.point - transform.position;
            isDragging = true;
        }
    }

    if (isDragging && Input.GetMouseButton(0)) {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;
        if (Physics.Raycast(ray, out hit)) {
            Vector3 targetPosition = hit.point + offset;
            transform.position = targetPosition;
        }
    }

    if (Input.GetMouseButtonUp(0)) {
        isDragging = false;
    }
}
优点:
  • 精确控制:使用射线检测可以精确控制拖拽物体与其他物体的交互。
  • 适用于3D场景:特别适合需要对物体进行 3D 拖拽的场景。
  • 支持碰撞检测:能够通过射线检测与其他物体碰撞,适应复杂场景。
缺点:
  • 性能开销:射线检测会占用一定的性能,尤其是在复杂场景中。
  • 需要物理组件:射线检测对物体的碰撞需要依赖物理引擎,可能增加开发复杂性。
适用场景:
  • 3D 游戏中的物体拖拽,特别是涉及到复杂的物理交互或物体间的碰撞。
  • 需要精准控制鼠标与物体交互的场景。

3. Event System + OnBeginDrag, OnDrag, OnEndDrag

使用 Unity 的 EventSystem 来处理拖拽,可以实现更加流畅的交互体验,特别适合有 UI 或复杂交互需求的场景。

示例代码:
using UnityEngine;
using UnityEngine.EventSystems;

public class Draggable : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {
    private Vector3 offset;

    public void OnBeginDrag(PointerEventData eventData) {
        // 记录初始偏移
        offset = transform.position - Camera.main.ScreenToWorldPoint(eventData.position);
    }

    public void OnDrag(PointerEventData eventData) {
        Vector3 targetPosition = Camera.main.ScreenToWorldPoint(eventData.position) + offset;
        targetPosition.z = 0; // 确保物体在 2D 平面内
        transform.position = targetPosition;
    }

    public void OnEndDrag(PointerEventData eventData) {
        // 结束拖拽
    }
}
优点:
  • 流畅的交互体验:通过 EventSystem 处理拖拽,能够确保UI和物体拖拽的流畅体验。
  • 易于扩展:支持与其他 UI 元素的交互,能够轻松集成到复杂的 UI 系统中。
  • 自动处理交互:不需要手动编写输入检测代码,EventSystem 会自动管理输入事件。
缺点:
  • 依赖 EventSystem:需要依赖 Unity 的 EventSystem,且实现稍微复杂一些。
  • 限制于 UI 系统:适用于与 UI 组件的交互,复杂的 3D 场景中可能不太适用。
适用场景:
  • 需要与 UI 元素交互的拖拽场景,例如 UI 控件、按钮等。
  • 需要流畅拖拽体验且项目中已经在使用 EventSystem。

4. 触摸输入 + Camera.main.ScreenToWorldPoint

适用于移动设备,处理触摸输入来实现物体的拖拽,尤其适合简单的触摸拖拽。

示例代码:
private Vector3 offset;
private bool isDragging = false;

void Update() {
    if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began) {
        // 触摸开始
        Vector3 touchPosition = Camera.main.ScreenToWorldPoint(Input.GetTouch(0).position);
        offset = transform.position - touchPosition;
        isDragging = true;
    }

    if (isDragging && Input.touchCount > 0) {
        // 触摸拖拽
        Vector3 touchPosition = Camera.main.ScreenToWorldPoint(Input.GetTouch(0).position);
        transform.position = touchPosition + offset;
    }

    if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Ended) {
        // 触摸结束
        isDragging = false;
    }
}
优点:
  • 适用于移动设备:专为触摸屏设备设计,支持多点触控和手势操作。
  • 简单易用:类似于鼠标拖拽的方式,易于实现。
缺点:
  • 触摸精度问题:在某些情况下,触摸输入的精度可能不如鼠标,尤其在快速移动时。
  • 设备限制:不适用于桌面设备,局限性较强。
适用场景:
  • 移动设备上的拖拽需求,特别是平板、手机等触摸屏设备。
  • 不需要复杂物理反馈的应用。

5. 新输入系统 + Raycast 或 Camera.main.ScreenToWorldPoint

使用 Unity 新输入系统来处理多种输入设备,适合需要支持多种设备(如鼠标、触摸、手柄)的拖拽场景。

示例代码:
using UnityEngine.InputSystem;

private Vector3 offset;
private bool isDragging = false;

void Update() {
    if (Mouse.current.leftButton.wasPressedThisFrame) {
        // 开始拖拽
        Ray ray = Camera.main.ScreenPointToRay(Mouse.current.position.ReadValue());
        RaycastHit hit;
        if (Physics.Raycast(ray, out hit)) {
            offset = hit.point - transform.position;
            isDragging = true;
        }
    }

    if (isDragging && Mouse.current.leftButton.isPressed) {
        // 拖拽中
        Ray ray = Camera.main.ScreenPointToRay(Mouse.current.position.ReadValue());
        RaycastHit hit;
        if (Physics.Raycast(ray, out hit)) {
            Vector3 targetPosition = hit.point + offset;
            transform.position = targetPosition;
        }
    }

    if (Mouse.current.leftButton.wasReleasedThisFrame) {
        // 结束拖拽
        isDragging = false;
    }
}
优点:
  • 多设备支持:可以处理鼠标、触摸、手柄等不同输入设备。
  • 灵活性强:能够轻松适配不同类型的输入设备,适合跨平台开发。
缺点:
  • 需要新输入系统:如果项目还没有集成新输入系统,可能需要额外的学习成本和配置。
  • 复杂性较高:相比于传统的 Input 方式,代码实现可能会稍显复杂。
适用场景:
  • 需要支持多种输入设备

的项目,如PC、移动端和游戏机。

  • 跨平台应用,特别是需要处理多种输入设备的场景。

总结

拖拽方式优点缺点适用场景
鼠标输入 + ScreenToWorldPoint简单易懂,性能较好缺乏物理反馈,限制于鼠标输入适合桌面端简单的 2D 游戏或应用
鼠标输入 + Raycast精确控制,支持碰撞检测性能开销较大,依赖物理引擎3D 游戏中的精确物体拖拽,带碰撞检测
Event System + OnBeginDrag流畅的交互体验,易于扩展依赖 EventSystem,实现稍复杂UI 交互或需要 EventSystem 支持的拖拽场景
触摸输入 + ScreenToWorldPoint简单易用,适合移动设备触摸精度较低,设备限制较强移动设备上的简单拖拽,适合触摸屏设备
新输入系统 + Raycast 或 ScreenToWorldPoint支持多设备输入,灵活适应多平台需要配置新输入系统,代码稍复杂多设备支持的应用,跨平台项目,支持鼠标和触摸输入

标签:鼠标,触摸,Unity,Input,main,拖拽,输入,3D
From: https://blog.csdn.net/tealcwu/article/details/144497355

相关文章

  • 国内外免费 solidworks零件库 3d零件库 traceparts零件库下载网站推荐
    SolidWorks零件库‌是包含标准件和常用件模型的资源库,旨在帮助用户更高效地进行设计和建模工作。它包含了丰富的零件资源,涵盖了多种常用的机械零件和标准件,能够极大地提升设计效率和准确性‌。今天小编给大家推荐几家国外和国内比较优秀的零部件模型免费下载的平台。一、CAD......
  • 【Unity 低多边形3D 资源包】POLYGON Prototype - Low Poly 3D Art by Synty 专为游戏
    POLYGONPrototype-LowPoly3DArtbySynty是一款由知名工作室SyntyStudios提供的高质量低多边形(LowPoly)3D资源包,专为游戏开发者打造,适用于快速创建原型、概念演示和低多边形风格的游戏项目。它提供了一个全面的低模资产集合,既能满足开发需求,又具有出色的美术表现力......
  • 【Unity 军事基地和战争环境插件】Military Base Megapack 高质量的军事基地场景、建
    MilitaryBaseMegapack是一款为Unity开发者设计的插件,提供了一系列高质量的军事基地场景、建筑物、车辆、道具和其他环境资源,专门用于构建军事主题的游戏或应用。该插件以细致的3D建模和高效的资源管理为特色,适用于需要丰富战场、军事设施和战斗环境的项目。无论是战术类、......
  • 【Unity 计算机视觉插件】OpenCV for Unity 轻松实现图像处理、目标检测、物体识别、A
    OpenCVforUnity是一款功能强大的Unity插件,将著名的计算机视觉库OpenCV无缝集成到Unity中,为开发者提供丰富的计算机视觉功能支持。通过该插件,开发者可以轻松实现图像处理、目标检测、物体识别、AR增强现实等复杂功能,适用于多种平台,包括Windows、macOS、Android、iOS等。功......
  • abb机器人3d模型,abb机器人模型下载 一文全了解
    ‌ABB机器人是一种工业机器人,由ABB集团研发和生产。ABB是全球领先的机器人与机械自动化供应商之一,总部位于瑞士苏黎世。‌ABB机器人以其运动控制技术为核心,能够实现高精度的循径控制、快速的运动速度和可靠的周期时间,从而大幅度提高生产的质量、效率和可靠性。‌abb机器人主要......
  • 【Unity功能】Unity分页器
    前言在开发Unity项目时,经常会遇到需要展示大量数据的情况,比如物品列表、排行榜等。为了提供更好的用户体验,我们通常会使用分页功能来展示这些数据。本文将介绍如何在Unity中实现一个功能完整的分页器组件。一、效果演示二、制作过程简言这个分页器具有以下特点:1、支......
  • 物联网开发利器:基于web的强大的可拖拽组态软件
      随着互联网、物联网技术的快速发展,BY组态基于多年研发积累和私有部署实践打磨、以及对业务场景的深入理解,推出了适用于物联网应用场景的轻量型web组态软件。该产品采用B/S架构,提供web管理界面,软件包大小仅50MB,无需安装客户端,可通过浏览器直接访问。图形组态功能,是工......
  • 在 Vue 中实现拖拽排序功能的最佳方式。
    在Vue.js中实现拖拽排序功能,可以使用现成的库来简化开发过程。以下是几种推荐的方法:使用vuedraggable库:vuedraggable是一个基于Sortable.js的Vue组件,它提供了简单易用的API来创建可拖拽和排序的列表。这是最流行的选择之一。安装:npminstallvuedraggable......
  • 拖拽事件
    鸿蒙系统拖拽事件简易使用支持版本与资源限制从APIVersion7开始支持拖拽事件,后续版本可能有新增内容并标记起始版本。应用本身预置的资源文件仅支持本地应用内拖拽。默认支持组件及属性设置ArkUI框架对部分组件实现了默认拖拽能力。默认支持拖出能力的组件有Search......
  • 【Unity 场景传送工具】Mighty Leap 支持直接点击场景任意位置进行瞬间传送,无需耗时调
    MightyLeap是一款专注于场景内即时传送的工具,可以帮助开发者高效地在Unity场景中快速定位和导航。通过简单的热键或鼠标点击操作,可以轻松到达场景的任何角落,大幅提升关卡设计、调试和场景演示的效率。主要功能与特点快速场景导航支持直接点击场景任意位置进行瞬间传送......