Unity由“鼠标点不准物体”引发的Camera的相关思考

2023-12-07 11:30

本文主要是介绍Unity由“鼠标点不准物体”引发的Camera的相关思考,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

问题        

        前段一个同事在使用Unity开发时遇到一个奇怪的问题,使用左键点击发射射线的方式选择物体,总是选不准,尤其是小的物体,鼠标点击到物体上,有时能选上,有时选不上,偶尔点击到物体旁边反而能选上,于是他让我帮看看咋回事。我第一个想法是也许代码写的有问题吧,但我仔细检查了同事写的代码,规规矩矩,完全没问题。

        就类似下面这种:

if (Input.GetMouseButtonDown(0))
{Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);RaycastHit hit;if (Physics.Raycast(ray, out hit, 500)){Debug.Log(hit.transform.name);}
}

        我一时也是有点儿发懵,但是当我检查他的摄像机设置时,发现他把摄像机的近剪切平面距离设置的很小,是0.01,同事说是为了避免距离近的物体看不到,只能设置到最小,本来想设置为0,但是Unity不允许,最小就只能是0.01了。好吧,反正我也找不到问题所在,咱不妨把这个值先设置为默认值0.3,排除是这个引发问题的可能吧。结果不可思议的事情发生了,再次运行,马上就能够精确点击了。

为啥(一)

        问题是解决了,但是为什么呢?

        先看看这行代码:

Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

        很多时候,这几乎就是Unity的标准写法,一直以来,我都没有深入的研究过,我一直以为这个ray是从摄像机的位置发射出来,也就是ray.origin这个值应该和摄像机的位置是重叠的,但是,当我把ray.origin打印出来(代码如下)的时候,我发现,这个这值位于摄像机的近剪切平面上,并不和摄像机位置重叠!!!

Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Debug.Log(ray.origin);

        但是,这和近剪切距离的值有什么关系呢?

        因为我们会发现,近剪切平面的长宽和近剪切距离是等比关系,如果近剪切距离小,那么意味着近剪切平面的长宽也变得很小,对于

Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

这样的代码来说,射线的 ray.origin这个值的位置取决于鼠标在屏幕上的位置映射到近剪切平面的结果,而近剪切平面的长宽越大,越容易获得一个精确的值(这个也实在是没办法的事情,Unity的位置精度是float嘛,而这种精度也不单单是Unity如此,大部分游戏引擎都如此,据说使用Double精度的位置对显卡渲染速度影响很大,同时动力学计算也有问题,当然了,听说而已,没亲身研究过)。

        所以我们可以认为,如果近剪切距离是0.3的话,其精度是近剪切距离0.01的30倍,嗯,好像应该可以这么认为吧。

为啥(二)

        但是为什么射线的起始点不是和摄像机位置重叠,偏偏要放在近剪切平面上呢?仔细想想,好像也很好理解,摄像机只会渲染其视锥体内的物体,不会渲染摄像机所在位置和近剪切平面之间的物体,如果射线的出发点和摄像机重叠,那么就可以点击到摄像机所在位置和近剪切平面之间的物体,而这个物体用户根本看不到!Unity当然不应该让这种事情发生,于是把射线的位置放在了近剪切平面上就成了解决这个问题的绝佳方法!!

为啥啊

        到此为止,我以为一切都在掌握之中,于是我认为,远剪切平面之外的物体也点击不了,不管你在Physics.Raycast方法中把射线发射距离设置为多远!

        然后我把Physics.Raycast方法中的maxDistance设置为2000,因为摄像机默认的远剪切距离为1000,如果我把一个物体放置在远剪切平面之外,那么一定是即渲染不了,也点击不到。然而经过测试,发现并非如此,远剪切平面之外的物体只要在射线发射的maxDistance距离之内,就能够被点击到,哈哈哈哈,为啥啊......

这篇关于Unity由“鼠标点不准物体”引发的Camera的相关思考的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/465691

相关文章

sqlite3 相关知识

WAL 模式 VS 回滚模式 特性WAL 模式回滚模式(Rollback Journal)定义使用写前日志来记录变更。使用回滚日志来记录事务的所有修改。特点更高的并发性和性能;支持多读者和单写者。支持安全的事务回滚,但并发性较低。性能写入性能更好,尤其是读多写少的场景。写操作会造成较大的性能开销,尤其是在事务开始时。写入流程数据首先写入 WAL 文件,然后才从 WAL 刷新到主数据库。数据在开始

韦季李输入法_输入法和鼠标的深度融合

在数字化输入的新纪元,传统键盘输入方式正悄然进化。以往,面对实体键盘,我们常需目光游离于屏幕与键盘之间,以确认指尖下的精准位置。而屏幕键盘虽直观可见,却常因占据屏幕空间,迫使我们在操作与视野间做出妥协,频繁调整布局以兼顾输入与界面浏览。 幸而,韦季李输入法的横空出世,彻底颠覆了这一现状。它不仅对输入界面进行了革命性的重构,更巧妙地将鼠标这一传统外设融入其中,开创了一种前所未有的交互体验。 想象

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

两个月冲刺软考——访问位与修改位的题型(淘汰哪一页);内聚的类型;关于码制的知识点;地址映射的相关内容

1.访问位与修改位的题型(淘汰哪一页) 访问位:为1时表示在内存期间被访问过,为0时表示未被访问;修改位:为1时表示该页面自从被装入内存后被修改过,为0时表示未修改过。 置换页面时,最先置换访问位和修改位为00的,其次是01(没被访问但被修改过)的,之后是10(被访问了但没被修改过),最后是11。 2.内聚的类型 功能内聚:完成一个单一功能,各个部分协同工作,缺一不可。 顺序内聚:

log4j2相关配置说明以及${sys:catalina.home}应用

${sys:catalina.home} 等价于 System.getProperty("catalina.home") 就是Tomcat的根目录:  C:\apache-tomcat-7.0.77 <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %c{1}:%L - %msg%n" /> 2017-08-10

Node Linux相关安装

下载经编译好的文件cd /optwget https://nodejs.org/dist/v10.15.3/node-v10.15.3-linux-x64.tar.gztar -xvf node-v10.15.3-linux-x64.tar.gzln -s /opt/node-v10.15.3-linux-x64/bin/npm /usr/local/bin/ln -s /opt/nod

git ssh key相关

step1、进入.ssh文件夹   (windows下 下载git客户端)   cd ~/.ssh(windows mkdir ~/.ssh) step2、配置name和email git config --global user.name "你的名称"git config --global user.email "你的邮箱" step3、生成key ssh-keygen

zookeeper相关面试题

zk的数据同步原理?zk的集群会出现脑裂的问题吗?zk的watch机制实现原理?zk是如何保证一致性的?zk的快速选举leader原理?zk的典型应用场景zk中一个客户端修改了数据之后,其他客户端能够马上获取到最新的数据吗?zk对事物的支持? 1. zk的数据同步原理? zk的数据同步过程中,通过以下三个参数来选择对应的数据同步方式 peerLastZxid:Learner服务器(Follo

Unity3D自带Mouse Look鼠标视角代码解析。

Unity3D自带Mouse Look鼠标视角代码解析。 代码块 代码块语法遵循标准markdown代码,例如: using UnityEngine;using System.Collections;/// MouseLook rotates the transform based on the mouse delta./// Minimum and Maximum values can

简单的角色响应鼠标而移动

actor类 //处理移动距离,核心是找到角色坐标在世界坐标的向量的投影(x,y,z),然后在世界坐标中合成,此CC是在地面行走,所以Y轴投影始终置为0; using UnityEngine; using System.Collections; public class actor : MonoBehaviour { public float speed=0.1f; CharacterCo