Unity鼠标带动物体运动的三种方法

news2024/10/6 8:00:36

目录

第一种:物体跟随鼠标移动。

第二种:鼠标拖动物体运动。

第三种:鼠标点到哪,物体运动到哪。


第一种:物体跟随鼠标移动。

描述:鼠标左键点击物体,将物体拾起,松开鼠标左键,物体跟随鼠标光标移动。再次点击鼠标左键,物体不在跟随鼠标,处于静止状态。

实现方法:射线。

1657678042844

写在前面:什么是射线?

简单来说就是当鼠标点击某个物体时,通过摄像机camera发射射线,射线与物体碰撞在一个点上。我们通过这个点找到该点对应的物体,先判断该物体是否是我们想要移动的(是否为可以移动的)。

如果是,那我们就拿到要操作的对象了,接下来就是让其坐标位置和鼠标位置保持一致即可。

具体解释和详细使用方法读者可自行查阅相关文献。

由此我们可以得出,我们要先声明一个射线的变量,还有碰撞点,由于有碰撞点,我们就必需为物体添加刚体组件。为了判断是不是我们要的物体,就定义一个布尔值。此外,为了区分鼠标点击这一动作是拾起还是放下物体,我们要声明一个标志量flag。为了得到该碰撞点对应的物体,我们要声明一个GameObject组件来得到它。

    private Ray ra;//声明射线
    private RaycastHit hit;//声明碰撞点
    private bool is_element =false;//判断是否是我们要的物体
    private int flag = 0;//标志量
    private GameObject Element;//控件

接下来就是干正事儿了。

判断鼠标是否按下:

if (Input.GetMouseButtonDown(0))
        {
            
        }

鼠标按下后,摄像机往按下位置发射射线。

    ra = Camera.main.ScreenPointToRay(Input.mousePosition);

判断射线是否跟物体发生碰撞得到碰撞点hit,并且同时判断该点对应的物体是不是我们要的。

判断物体是不是我们要的,这里我使用的是判断其标签是不是'element',因此应该给先给物体添加一个标签。

以上检测完后将布尔值设为true,并将碰撞点对应的物体给Element。

if (Physics.Raycast(ra, out hit)&&hit.collider.tag=="element")
            {
                is_element = true;
                Element = hit.collider.gameObject;
            }

判断鼠标按下是拾起还是放下。

这里我规定,鼠标拾起物体时,flag=1,再次点击flag=0。

总的判断部分代码为:

if (Input.GetMouseButtonDown(0))
        {
            ra = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ra, out hit)&&hit.collider.tag=="element")
            {
                is_element = true;
                Element = hit.collider.gameObject;
                Debug.Log(Element.transform.position);
                if (flag == 0)
                {
                    flag = 1;
                }
                else
                {
                    flag = 0;
                }
            }
        }

改变物体位置和鼠标位置一致。

我们要先得到鼠标的位置。

鼠标只有x和y轴,为了和物体位置一致,这里将鼠标的z轴设置为物体的坐标。

Vector3 mousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y,
                Element.transform.position.z);

由于鼠标位置是屏幕坐标,而物体坐标是世界坐标,那我们就要把鼠标的屏幕坐标换成世界坐标。

Vector3 mouseSToW = Camera.main.ScreenToWorldPoint(mousePos);

细心的人可以发现,这里有个“陷阱”。

我们在把鼠标的二位坐标用三位坐标表示时,其z轴就是物体的世界坐标的位置,然后我们之后又把它当作屏幕坐标转化成世界坐标,那么最后的坐标肯定和以前的不一样了。

所以我们要先将物体的世界坐标转化成成屏幕坐标,在把屏幕坐标的z轴坐标给鼠标的屏幕坐标,然后一同转化成世界坐标。然后将得到的世界坐标给物体。

Vector3 targetScreenPos = Camera.main.WorldToScreenPoint(Element.transform.position);
Vector3 mousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y,targetScreenPos.z);
Element.transform.position = Camera.main.ScreenToWorldPoint(mousePos);

当flag=1时,我们是拾起物体的,因此在flag变为0之前,我们的物体都是跟着鼠标移动的。

因此以上操作都是在flag==1以及is_element=true的条件下进行的。

if (flag == 1&&is_element)
        {
            Vector3 targetScreenPos = Camera.main.WorldToScreenPoint(Element.transform.position);
            Vector3 mousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y,targetScreenPos.z);
            Element.transform.position = Camera.main.ScreenToWorldPoint(mousePos);
        }

代码汇总得:

using System.Collections;
using System.Collections.Generic;
using System.Linq.Expressions;
using Unity.VisualScripting;
using UnityEngine;
 
public class camera : MonoBehaviour {
    //public Camera ca;
    private Ray ra;
    private RaycastHit hit;
    private bool is_element =false;
    private int flag = 0;
    private GameObject Element;

    // Use this for initialization
    void Start () {
        
    }
	
    // Update is called once per frame
    void Update () {
        if (Input.GetMouseButtonDown(0))
        {
            ra = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ra, out hit)&&hit.collider.tag=="element")
            {
                is_element = true;
                Element = hit.collider.gameObject;
                if (flag == 0)
                {
                    flag = 1;
                }
                else
                {
                    flag = 0;
                }
            }
        }

        if (flag == 1&&is_element)
        {
            Vector3 targetScreenPos = Camera.main.WorldToScreenPoint(Element.transform.position);
            Vector3 mousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y,
                targetScreenPos.z);
            Element.transform.position = Camera.main.ScreenToWorldPoint(mousePos);
        }
    }
}

第二种:鼠标拖动物体运动。

描述:长按鼠标左键,物体跟随鼠标移动,松开鼠标左键,物体停止运动。

实现方法:协程或者射线。

有了前面的坐标转换基础,再加上对协程的基本了解,这个实现是非常容易的,我就直接上代码吧。

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

public class Cooperation : MonoBehaviour
{
    
    IEnumerator OnMouseDown()    //使用协程
    {
        Vector3 targetScreenPos = Camera.main.WorldToScreenPoint(transform.position);//三维物体坐标转屏幕坐标
        //将鼠标屏幕坐标转为三维坐标,再计算物体位置与鼠标之间的距离
        var offset = transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, targetScreenPos.z));
        
        while (Input.GetMouseButton(0))
        {
            //将鼠标位置二维坐标转为三维坐标
            Vector3 mousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, targetScreenPos.z);
            //将鼠标转换的三维坐标再转换成世界坐标+物体与鼠标位置的偏移量
            var targetPos = Camera.main.ScreenToWorldPoint(mousePos) + offset;
            transform.position = targetPos;
            yield return new WaitForFixedUpdate();//循环执行
        }
    }
    }
    
}

使用射线的方法与之类似,这里就不在赘述。

第三种:鼠标点到哪,物体运动到哪。

描述:类似于英雄联盟的移动方式,鼠标点击平面任意位置,物体立即朝该方向移动。

1657681859641

首先,对移动物体和地面进行bake,操作如下:

选中Cube,点击window—>AI—>Navigation

然后将Navigation Static勾选上

 之后选择bake,地面和移动物体(Cube)都要勾选上。

 代码我就直接给了,比较容易理解。

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

public class Nvgt : MonoBehaviour
{
    private NavMeshAgent navMeshAgent;
    void Start()
    {
        navMeshAgent = gameObject.GetComponent<NavMeshAgent>();//初始化navMeshAgent
    }
    void Update()
    {
        if (Input.GetMouseButtonDown(0))//鼠标左键点下  
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//住摄像机向鼠标位置发射射线 
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit))//射线检验 
            {
                if (hit.collider.gameObject.tag == "Plane")
                {
                    navMeshAgent.SetDestination(hit.point);//mHit.point就是射线和plane的相交点,实为碰撞点
                }
            }
        }
    }
}

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

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

相关文章

每日一练蓝桥杯C语言:2020年真题题集(B组)

在这里我给大家推荐一款不错刷算法学习网站&#xff1a;点击这处链接牛客网&#xff1b;牛客网作为国内内容超级丰富的 IT 题库&#xff0c;各种东西看的我眼花缭乱&#xff0c;题库面试学习求职讨论大厂内推等等服务&#xff0c;堪称"互联网求职神器"。它好就好在不…

MySQL(九):MVCC能否解决幻读问题

尺有所短&#xff0c;寸有所长&#xff1b;不忘初心&#xff0c;方得始终。 请关注公众号&#xff1a;星河之码 幻读【前后多次读取&#xff0c;数据总量不一致】 同一个事务里面连续执行两次同样的sql语句&#xff0c;可能导致不同结果的问题&#xff0c;第二次sql语句可能会返…

CSS3动画属性 animation详解(看完就会)

CSS3动画属性 animation 文章包含个人理解错误请指出 往期文章 【css高级】变量详解 轮播图swiper框架的基本使用【Transform3D】转换详解&#xff08;看完就会&#xff09;【css动画】移动的小车 【CSS3】 float浮动与position定位常见问题&#xff08;个人笔记&#xff09…

MySQL入门安装(一步一图)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a;小刘主页 ♥️每天分享云计算网络运维课堂笔记&#xff0c;努力不一定有收获&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️夕阳下&#xff0c;是最美的绽放&#xff0…

三极管工作原理介绍(动画图解)

三极管BJT 各位社区的小伙伴们大家好&#xff0c;相信大家也像我一样&#xff0c;因为上学的时候学过&#xff0c;但是呢&#xff0c;出社会不怎么用&#xff0c;久而久之就忘了&#xff0c;今天来给大家巩固一下&#xff0c;我对三极管的通俗易懂的工作原理介绍&#xff01; 半…

怎样提高报表呈现的性能

报表的性能很重要&#xff0c;是一个总被谈及的问题&#xff0c;跑的慢的报表用户体验恶劣&#xff0c;无法忍受。解决这些慢的性能问题&#xff0c;也成了项目方和工程师头疼的事情。一出状况&#xff0c;就得安排技术好的&#xff0c;能力强的工程师去救火&#xff0c;本来利…

『赠书活动 | 第二期』《元宇宙Ⅱ:图解元技术区块链、元资产与Web3.0、元人与理想国(全三册)》

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; 『赠书活动 &#xff5c; 第二期』 本期书籍&#xff1a;《元宇宙Ⅱ&#xff1a;图解元技术区块链、元资产与Web3.0、元人与理想国》 赠书规则&#xff1a;评论区&…

齐全且实用的MySQL函数使用大全

目录 一、MySQL函数介绍 二、MySQL函数分类 &#xff08;一&#xff09;单行函数 ①字符串函数 ②数学函数 ③日期函数 ④流程控制函数 ⑤系统信息函数 ⑥其他函数 &#xff08;二&#xff09;聚合函数 三、函数使用示例 &#xff08;一&#xff09;字符函数 ①le…

【K8S系列】深入解析etcd

序言 时间永远是旁观者&#xff0c;所有的过程和结果&#xff0c;都需要我们自己去承担。 文章标记颜色说明&#xff1a; 黄色&#xff1a;重要标题红色&#xff1a;用来标记结论绿色&#xff1a;用来标记一级论点蓝色&#xff1a;用来标记二级论点 Kubernetes (k8s) 是一个容器…

WeIdentity智能合约源码分析

WeIdentity智能合约 介绍 本文结合WeIdentity智能合约文档对其源码进行阅读分析。当前&#xff0c;WeIdentity合约层面的工作目标主要包括两部分&#xff1a; WeIdentity DID智能合约&#xff0c;负责链上ID体系建立&#xff0c;具体包括生成DID&#xff08;Distributed IDe…

【C++】vector类详细总结(包括vector二维数组)(持续更新中)

目录 一、vector的初始化&#xff08;9种&#xff09; 二、vector的访问和遍历 2.1 访问&#xff08;3种&#xff09; &#xff08;1&#xff09;使用下标运算符[]访问和修改 &#xff08;2&#xff09;使用迭代器访问 &#xff08;3&#xff09;使用at()函数访问 &#…

Spring Boot配置多数据源的四种方式

1、导读 在日常开发中我们都是以单个数据库进行开发&#xff0c;在小型项目中是完全能够满足需求的。 但是&#xff0c;当我们牵扯到像淘宝、京东这样的大型项目的时候&#xff0c;单个数据库就难以承受用户的CRUD操作。 那么此时&#xff0c;我们就需要使用多个数据源进行读写…

centos上使用yum安装redis

使用yum install -y redis时报错&#xff0c;没有找到安装包 解决办法&#xff1a; 下载fedora的epel仓库&#xff0c;yum添加epel源&#xff1a;执行 yum install epel-release 回车 再次&#xff1a;yum install redis 回车 开启redis服务 service redis star…

C语言设计扫雷(保姆级教学)

目录 引入&#xff1a; 游戏思路与逻辑&#xff1a; 游戏具体实现过程 整个程序的大体逻辑&#xff1a; 游戏的执行逻辑&#xff1a; game.h头文件内容&#xff1a; 具体函数讲解 menu&#xff08;菜单函数&#xff09; Initboard&#xff08;初始化棋盘函数&#xff09…

Ubuntu 22.04安装Cuda11.7和cudnn8.6

这篇文章记录了如何在Ubuntu22.04上安装CUDA11.7和cudnn8.6。按照步骤理应可以安装成功。如果还有问题&#xff0c;可以留言。 安装显卡驱动 打开‘软件和更新。 点击附加驱动安装显卡驱动 如果已经安装显卡驱动&#xff0c;请忽略上面的步骤。 安装gcc 新安装的Ubuntu22…

微软 New Bing AI 申请与使用保姆级教程(免魔法)

本文已收录到 AndroidFamily&#xff0c;技术和职场问题&#xff0c;请关注公众号 [彭旭锐] 提问。 大家好&#xff0c;我是小彭。 最近的 AI 技术实在火爆&#xff0c;从 OpenAI 的 ChatGPT&#xff0c;到微软的 New Bing&#xff0c;再到百度的文心一言&#xff0c;说明 AI …

[408] cache与主存的映射部分概念

涉及:基本理解 (防止误解映射规则cache 与 主存 的 "地址"构成主存块、cache块cache容量、cache的总容量有关计算的一些刁难名词不涉及:cache 与 主存映射规则基本理解:  首先我们需要明确的是我们之后针对的位数都是针对的 地址. 与实际的存储的 (01) 二进制无关. …

C# | 对象池

对象池 文章目录 对象池前言什么是对象池对象池的优点对象池的缺点 实现思路示例代码 结束语 前言 当我们开发一个系统或者应用程序时&#xff0c;我们通常需要创建很多的对象&#xff0c;这些对象可能是线程、内存、数据库连接、文件句柄等等。在某些情况下&#xff0c;我们需…

CM311-1A 卡刷 + 线刷、刷安卓与 Armbian 教程

使用到的工具软件与固件下载地址&#xff1a; https://41ws38-my.sharepoint.com/:f:/g/personal/ddf_41ws38_onmicrosoft_com/EhgM458YouBBshliWJhjcDcBAU-F5Mu6HTIU8PeKJHZnZA?eZnJZa6 不能下载&#xff0c;帖子下面评论。 准备工作 设备 / 硬件&#xff1a;CM311-1a YST 电…

C语言格式化输出总结:%d,%c,%s,%f, %lf,%m.nd,%m.nf,%m.ns 以及sprintf函数

凡事发生必将有益于我&#xff0c;高手&#xff0c;从来都不仅仅是具备某种思维的人&#xff0c;而是那些具备良好学习习惯的人&#xff0c;成为高手&#xff0c;无他&#xff0c;手熟尔&#xff01; -----来自一位IT领域的大神 在最近的学习之中&#xff0c;对于格式化输出这个…