IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Unity中如何用鼠标(mouse)优雅的把一坨物体拖动(drag)旋转 -> 正文阅读

[游戏开发]Unity中如何用鼠标(mouse)优雅的把一坨物体拖动(drag)旋转

一、网上能见到的拖拽旋转代码

它们都是沿着自身的某两个轴进行rotate,代码通常如下:

float XaxisRotation = Input.GetAxis("Mouse X") * RotationSpeed;
//float XaxisRotation = Input.mousePosition.x * RotationSpeed;

float YaxisRotation = Input.GetAxis("Mouse Y") * RotationSpeed;
//float YaxisRotation = Input.mousePosition.y * RotationSpeed;

// 设置旋转的轴心和旋转的量
go.Rotate(Vector3.down, XaxisRotation);
go.Rotate(Vector3.right, -YaxisRotation);

结局:
第一次拖拽都是母慈子孝——拖它往左,它就往左转,拖它往右,它就往右转,but(一看见but你就应该想到,要反转了),当物体转到背面后,你会发现:你往左拖,它往右转…简直鸡飞狗跳…

请看下面的效果:
请添加图片描述

如何修改呢?

二、请先欣赏这种母慈子孝的拖动效果

如何?向左拖向左转,向下拖向下转,始终都不会乱!!!
请添加图片描述

  • 脚本的参数:
    在这里插入图片描述

三、实现的思路

  • 旋转前:beginDrag
    1、生成旋转的root
    2、root对正方向:lookAt摄像机
    3、绑定父子关系:要旋转的物体作为root的子物体

  • 旋转中:Drag
    1、旋转root,带动子物体旋转

  • 停止旋转:endDrag
    1、撤销父子关系
    2、销毁root

  • 什么时候拖呢
    如上所示,你发现当鼠标悬停到物体上的时候,物体变成红色,此时物体才能拖动

四、代码

using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using System;
using static txlib;
using UnityEngine.EventSystems;

/*******************************************
    旋转前:beginDrag
        1、生成旋转的root
        2、对正方向:正对摄像机
        3、绑定父子关系

   旋转中:Drag
        1、旋转root,带动子物体旋转

   停止旋转:endDrag
        1、撤销父子关系
        2、销毁root
    *****************************************/


/// <summary>
/// 鼠标拖拽物体进行旋转
/// </summary>
public class DragObjectRotate : MonoBehaviour
{
    /// <summary>
    /// 相机
    /// </summary>
    public Transform cam;

    /// <summary>
    /// 要旋转点的物体
    /// </summary>
    public Transform objectToRotate;

    /// <summary>
    /// 旋转的速度因子
    /// </summary>
    public float RotationSpeed;

    /// <summary>
    /// 旋转物体的root
    /// </summary>
    private Transform rotateRoot;

    /// <summary>
    /// 旋转物体的父物体
    /// </summary>
    private Transform parent;

    /// <summary>
    /// 子物体
    /// </summary>
    public List<GameObject> childrenObjs = new List<GameObject>();

    // Start is called before the first frame update
    void Start()
    {
        childrenObjs.Clear();
        childrenObjs = GetChildren(objectToRotate);

        //记录物体的parent
        parent = objectToRotate.parent;       

        //事件添加
        childrenObjs.ForEach(obj=> 
        {
            //添加组件——EventTrigger
            if (obj.GetComponent<EventTrigger>() == null)
            {
                obj.gameObject.AddComponent<EventTrigger>();
            }

            //添加BoxCollider组件
            if (obj.GetComponent<Collider>() == null)
            {
                obj.gameObject.AddComponent<BoxCollider>();
            }

            //开始拖拽事件绑定
            obj.GetComponent<EventTrigger>().AddListener(EventTriggerType.BeginDrag, (PointerEventData eventData) =>
            {
                Debug.Log($"BeginDrag:");
                rotateRoot = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform;
                rotateRoot.position = objectToRotate.position;
                rotateRoot.LookAt(cam);
                rotateRoot.transform.localScale = new Vector3(50, 50, 50);
                objectToRotate.parent = rotateRoot;                
            });

            //结束拖拽事件绑定
            obj.GetComponent<EventTrigger>().AddListener(EventTriggerType.EndDrag, (PointerEventData eventData) =>
            {
                Debug.Log($"EndDrag:");
                objectToRotate.parent = parent;
                Destroy(rotateRoot.gameObject);
                obj.GetComponent<MeshRenderer>().material.color = Color.white;
            });

            //拖拽事件绑定
            obj.GetComponent<EventTrigger>().AddListener(EventTriggerType.Drag, (PointerEventData eventData) =>
            {
                Debug.Log($"Dragging......");
                RotateOjb(RotationSpeed, rotateRoot);
                //RotateOjb(RotationSpeed, objectToRotate);
            });

            //得着焦点
            obj.GetComponent<EventTrigger>().AddListener(EventTriggerType.PointerEnter, (PointerEventData eventData) =>
            {
                obj.GetComponent<MeshRenderer>().material.color = Color.red;
            });

            //失去焦点
            obj.GetComponent<EventTrigger>().AddListener(EventTriggerType.PointerExit, (PointerEventData eventData) =>
            {
                obj.GetComponent<MeshRenderer>().material.color = Color.white;
            });
        });       
    }

    /// <summary>
    /// 用鼠标来旋转物体
    /// </summary>
    /// <param name="RotationSpeed">旋转速度</param>
    /// <param name="go">旋转的物体</param>
    void RotateOjb(float RotationSpeed,Transform go)
    {
        float XaxisRotation = Input.GetAxis("Mouse X") * RotationSpeed;
        //float XaxisRotation = Input.mousePosition.x * RotationSpeed;

        float YaxisRotation = Input.GetAxis("Mouse Y") * RotationSpeed;
        //float YaxisRotation = Input.mousePosition.y * RotationSpeed;

        // 设置旋转的轴心和旋转的量
        go.Rotate(Vector3.down, XaxisRotation);
        go.Rotate(Vector3.right, -YaxisRotation);
    }   

#if UNITY_EDITOR
    [ContextMenu("获取物体的子物体测试")]
#endif 
    void Test()
    {
        childrenObjs = GetChildren(objectToRotate);
    }

    /// <summary>
    /// 获取子物体:包含渲染组件的物体
    /// </summary>
    /// <param name="root"></param>
    /// <returns></returns>
    public List<GameObject> GetChildren(Transform root)
    {
        return root.GetComponentsInChildren<Transform>().Where(x => x.GetComponent<MeshRenderer>() != null).Select(x => x.gameObject).ToList();
    }
}

五、备注:代码中用到的一个AddListener扩展方法【using static txlib;】

    /// <summary>
    /// 为EventTrigger的事件类型绑定Action方法
    /// ===============示例代码=================begin
    ///  GetComponent<EventTrigger>()
    ///  .AddListener(EventTriggerType.PointerEnter, (PointerEventData eventData) =>
    ///  {
    ///     Debug.Log($"当前Enter的物体:{p.seriseNo}");
    ///     endImage = p.go;
    ///  });
    /// ===============示例代码=================end
    /// </summary>
    /// <param name="trigger">EventTrigger组件对象</param>
    /// <param name="eventType">事件类型</param>
    /// <param name="listenedAction">要执行的方法</param>
    public static void AddListener(this EventTrigger trigger, EventTriggerType eventType, Action<PointerEventData> listenedAction)
    {
        EventTrigger.Entry entry = new EventTrigger.Entry();
        entry.eventID = eventType;
        entry.callback.AddListener(data => listenedAction.Invoke((PointerEventData)data));
        trigger.triggers.Add(entry);
    }
  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-05-13 11:58:23  更:2022-05-13 11:58:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 11:02:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码