【Unity 2D AABB碰撞检测】铸梦之路

news2024/11/15 7:33:06

作者介绍:铸梦xy。IT公司技术合伙人,IT高级讲师,资深Unity架构师,铸梦之路系列课程创始人。

  • 目录
    • 1.AABB 碰撞介绍
    • 2.常用2D碰撞盒
    • 3.为什么要学习如何编写碰撞检测
    • 4.2D BOX & BOX 碰撞检测原理和代码
    • 5.2D BOX &Shpere 碰撞检测原理和代码
    • 6.2D Shpere &Shpere 碰撞检测代码

目录

1.AABB 碰撞介绍

AABB 代表的是轴对齐碰撞盒 (Axis-aligned Bounding Box)

AABB碰撞盒是指与场景基础坐标轴(2D中的是x和y轴)对齐的长方形的碰撞外形。与坐标轴对齐意味着这个长方形没有经过旋转并且它的边线和场景中基础坐标轴平行(例如,左右边线和y轴平行)。这些碰撞盒总是和场景的坐标轴平行,这使得所有的计算都变得更简单。

2.常用2D碰撞盒

一般在2D环境下,常用的碰撞盒有一下几种种。

  • 1.BOX(方形) 碰撞
  • 2.Sphere(圆形) 碰撞
  • 3.BOX&Sphere(方形与圆形) 碰撞

特殊形状的碰撞盒不在本篇文章的讨论范围。

3.为什么要学习如何编写碰撞检测

问题:Unity已经有了自带的2D 和 3D 碰撞体以及一套完整且成熟的物理系统,我们为什么不能直接使用Unity自带的,反而还要去编写这个系统。

答:问的好。当你看到这篇文章的时候,说明你的心中已经有了准确的答案。不然也不会进到这篇文章中。
首先肯定是Unity的物理系统,无法满足我们的特殊需求。
那特殊需求都有哪些呢?

  • 1.我们需要编写一套基于定点数的碰撞检测系统。

  • 2.我们不想用Unity的碰撞检测,想自己编写一套属于自己的碰撞系统。

  • 3.纯纯个人兴趣,来学习如何碰撞系统的检测。

相信肯定是第一种占的人数比较多。

既然有需求,那就满足你们。

4.2D BOX & BOX 碰撞检测原理和代码

请添加图片描述

首先说下2D场景下 BOX&BOX碰撞的原理:

由于AABB碰撞是基于坐标轴对齐的,所以我们检测起来就非常简单。只需要检测两个碰撞盒是否有重合即可,也就是X轴和Y轴上是否有重合或相交。

判断原理:我们只需要检测第一个物体的最右的点是否大于第二个物体的最左侧的点,并且第二个物体的最右侧的点是否大于第一个物体的最左侧的点。Y轴检测原理也是如此

检测原理示意图如下:
请添加图片描述
BOX&BOX碰撞检测源码:

public class FixIntBoxCollider2D : FixIntCollider2D
{
	public float x { get { return transform.position.x; } }
    public float y { get { return transform.position.y; } }
    public Vector2 size = new Vector2(1, 1);
    public Vector2 conter;
    protected float mBoxWidth { get { return size.x / 2; } }
    protected float mBoxHeigth { get { return size.y / 2; } }
    public override bool DetectionBoxCollider(FixIntBoxCollider2D target)
    {
        //第一个物体的最右侧是否大于第二个物体的最左侧 并且 第二个物体的最右侧是否大于第一个物体的最左侧;
        bool isCollider_x = x + mBoxWidth >= target.x - target.mBoxWidth
            && target.x + target.mBoxWidth >= x - mBoxWidth;

        bool isCollider_y = y + size.y >= target.y - target.mBoxHeigth
           && target.y + target.mBoxHeigth >= y - mBoxHeigth;

        return isCollider_x && isCollider_y;
    }
}

5.2D BOX &Shpere 碰撞检测原理和代码

请添加图片描述

BOX与Shpere碰撞检测相较于 BOX&BOX 以及 Shpere&Shpere碰撞检测就稍微复杂一点。 不过也不是特别复杂,因为博主已经给大家画好了碰撞检测流程图,以及碰撞检测计算公式。

其实我们都只到,当球体与BOX平行X轴或Y轴时,我们只需要计算二者之间的半径即可检测出是否发生重叠和相交。
BOX与Shpere碰撞检测主要复杂在当一个球形碰撞盒处于BOX碰撞盒边角时的处理。
这个时候我们已经不能单纯的通过二者之间的距离和半径去判断是否发生碰撞了。因为BOX从中心点到边角的距离是大于BOX的半径的。所以单纯这样检测是不准的。

而准确的做法是获取Shpere球体距离BOX最近的处于BOX碰撞盒上的一个点。然后在由球体半径减去该点得出向量长度,最后计算该向量是否<球体半径,若小于则产生碰撞,否则说明两个碰撞体不重叠。

关于BOX距离球体最近的一个点获取原理:

1.P.y获取原理: (P点如下图位置)

首先获取 球体A的Y点,称作为A.y。
然后获取BOX碰撞体D的Y点坐标。称作为D.y。
A.y-D.y 就得到了一个值Y_Dis。当然这个值可能是大于Box的高度的。也就是超出了Box碰撞盒的区域。所以我们需要通过Clamp(Y_Dis,-D.height/2,D.height/2)强制限制该值,让该值处于Box碰撞盒的范围之内。然后用D.y+Y_Dis就得到了P.y。
通过这种方式我们就得到了P.y。然后就是获取P.x

2.P.x获取原理:
首先获取 球体A的X点坐标,称作为A.x。
然后获取BOX碰撞体D的X点坐标。称作为D.x。
A.x-D.x 就得到了一个值X_Dis。当然这个值也是可能是大于Box的宽度的。也会超出Box碰撞盒的区域。所以我们需要通过Clamp(X_Dis,-D.Width/2,D.Width/2)强制限制该值,让该值处于Box碰撞盒的范围之内。然后用D.x+X_Dis就得到了P.x。
通过这种方式我们就得到了P.x。

通过上面两步我们就得到了距离 Shpere球体A 最近的一个处于BOX碰撞盒上的一个点P。

最后用球体的位置减去P点的位置得出一个向量。这个向量如果小于 Shpere球体A 的半径,则说明发生了碰撞。

碰撞原理和计算公式如下图:

请添加图片描述
BOX &Shpere 碰撞检测代码

public class FixIntBoxCollider2D : FixIntCollider2D
{
	public float x { get { return transform.position.x; } }
    public float y { get { return transform.position.y; } }
    public Vector2 size = new Vector2(1, 1);
    public Vector2 conter;
    protected float mBoxWidth { get { return size.x / 2; } }
    protected float mBoxHeigth { get { return size.y / 2; } }
  
    public override bool DetectionSphereollider(FixIntSphereCollider2D target)
    {
        float xDis = target.x - x;
        float p_x = Mathf.Clamp(xDis, -mBoxWidth, mBoxWidth);

        float yDis = target.y - y;
        float p_y = Mathf.Clamp(yDis, -mBoxHeigth, mBoxHeigth);

        Vector2 closePoint = new Vector2(x+p_x,y+p_y);
        return Vector2.Distance(target.transform.position,closePoint)<=target.radius;
    }
}

6.2D Shpere &Shpere 碰撞检测代码

请添加图片描述
球体与球体的碰撞就在简单不过了,只需要判断半径即可。
原理就是判断A与B之间的向量是否 <= A.radius+B.raduis。小于则说明产生碰撞,大于则不碰撞。

public class FixIntSphereCollider2D : FixIntCollider2D
{
    public float radius;
    public float x { get { return transform.position.x; } }
    public float y { get { return transform.position.y; } }
    
    public override bool DetectionSphereollider(FixIntSphereCollider2D target)
    {
        // 判断A与B之间的向量是否 <= A.radius+B.raduis。小于则说明产生碰撞,大于则不碰撞。
        bool isCollider = Vector2.Distance(transform.position,target.transform.position)  <= (radius + target.radius) ;
        return isCollider;
    }
    public override bool DetectionBoxCollider(FixIntBoxCollider2D target)
    {
        throw new System.NotImplementedException();
    }
}

文章来自于铸梦老师,铸梦之路系列课程。
想了解更多框架、帧同步技术、UGUI优化相关技术可在企鹅kt搜索 铸梦xy。

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

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

相关文章

Linux信号编程、signal函数范例详解( 4 ) -【Linux通信架构系列 】

系列文章目录 C技能系列 Linux通信架构系列 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 期待你的关注哦&#xff01;&#xff01;&#xff01; 现在的一切都是为将来的梦想编织翅膀&#xff0c;让梦想在现实中展翅高飞。 Now everything is for the…

chatgpt赋能python:Python求1是什么?Python求1在SEO中的应用

Python求1是什么&#xff1f;Python求1在SEO中的应用 介绍Python求1 Python求1&#xff0c;也叫做1-bit计数器&#xff0c;是一种用来统计网页浏览量的技术。在Web开发中&#xff0c;我们需要记录网页的浏览次数&#xff0c;以便了解网站的流量和用户的使用情况。传统的做法是…

chatgpt赋能python:Python求绝对值:从初学者到高级工程师的必备知识

Python求绝对值&#xff1a;从初学者到高级工程师的必备知识 Python是一种有趣且功能强大的编程语言。它非常易于学习&#xff0c;同时又具有广泛的应用领域&#xff0c;比如Web开发、数据分析、机器学习和人工智能等。在Python的数学运算中&#xff0c;求绝对值是一个常见的需…

chatgpt赋能python:Python浮点型的两种表示方法

Python浮点型的两种表示方法 Python是一种解释型的动态语言&#xff0c;可以处理多种数据类型。其中&#xff0c;浮点型是其中一种数据类型&#xff0c;它包括十进制和科学计数法两种表示方法。 十进制表示法 十进制浮点数是Python的基本浮点类型&#xff0c;可以表示实数。…

2023 hnust 湖南科技大学 大数据技术与应用 期末考试 复习资料

前言 感谢&#xff1a;lqx&#xff08;主要内容来源&#xff09;&#xff0c;hqh 有自己的理解和魔改 可以参考的资料 课后题答案我爬取的老师布置的学习通课后题往年资料csdn里面找到的&#xff1a;1、2老师ppt上课划重点录音 不提供pdf文件&#xff0c;方便修改&#xff0…

探索技术极致,未来因你出‘粽’

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

chatgpt赋能python:Python游戏——为什么它成为未来最热门的游戏开发工具

Python游戏——为什么它成为未来最热门的游戏开发工具 在游戏开发中&#xff0c;Python一直是非常强大和受欢迎的语言。Python具有很多吸引人的特点和实用功能&#xff0c;它为游戏开发者提供了多种可能&#xff0c;我们在本文中将介绍Python游戏以及为什么它越来越受欢迎。 …

【从零开始学习JAVA | 第十一篇】ArrayList集合

目录 前言&#xff1a; ArrayList&#xff1a; 常用成员方法&#xff1a; 案例练习&#xff1a; 1.集合的遍历方式&#xff08;引用数据类型&#xff09;&#xff1a; 2&#xff1a;集合的遍历方式&#xff08;基本数据类型&#xff09;&#xff1a; 总结&#xff1a;…

一面、二面、三面有什么区别?

很多公司面试都分一面、二面、三面甚至更多&#xff0c;大家可能会好奇&#xff0c;为什么要面这么多面&#xff0c;每一面又有啥区别呢&#xff1f; 首先我来回答下为什么要这么多面&#xff0c;最核心的是最后3点&#xff1a; 如果光是一个人面&#xff0c;担心会看走眼&…

python基础学习6【DatatimeIndex与PeriodIndex函数+Timedelta类+连接数据库+agg()函数和aggregate()函数】

转换与处理时间序列数据 转换字符串时间为标准时间: Timestamp类型&#xff1a;最基础最常用。 pd.to_datetime(data[lock_time])#转换 如果超出时间戳最大值&#xff0c;最小值&#xff0c;时间戳存储可能不成功 &#xff1a; DatatimeIndex与PeriodIndex函数【其实俺暂时…

【Spring Cloud Sleuth 分布式链路跟踪】 —— 每天一点小知识

&#x1f4a7; S p r i n g C l o u d S l e u t h 分布式链路跟踪 \color{#FF1493}{Spring Cloud Sleuth 分布式链路跟踪} SpringCloudSleuth分布式链路跟踪&#x1f4a7; &#x1f337; 仰望天空&#xff0c;妳我亦是行人.✨ &#x1f984; 个人主页——微风撞见云…

scratch lenet(9): C语言实现tanh的计算

文章目录 1. 目的2. tanh ⁡ ( x ) \tanh(x) tanh(x) 的 naive 实现2.1 数学公式2.2 naive 实现 3. tanh ⁡ ( x ) \tanh(x) tanh(x) 的快速计算3.1 Maple 中的近似公式3.2 tan_c3()3.3 Gauss 连分数公式 (Continued Fraction) 4. 最终代码和运行结果代码运行结果 5. 其他Ref…

使用python制作常用图表

案例01 制作柱形图展示数据的对比关系——员工销售业绩统计表.xlsx import xlwings as xw app xw.App(visibleTrue, add_bookFalse) workbook app.books.open(员工销售业绩统计表.xlsx) # 打开要制作图表的工作簿 for i in workbook.sheets: # 遍历工作簿中的工作表chart i…

node.js安装及配置教程(win11)

node.js安装及配置教程&#xff08;win11&#xff09; 一、下载二、安装三、环境配置 一、下载 官网下载&#xff1a;点击下载 根据自己电脑的位数选择对应的版本即可 网盘下载&#xff1a;点击下载 二、安装 下载完成后&#xff0c;双击运行程序&#xff0c;点击next 勾…

iOS自动化环境搭建(超详细)

1.macOS相关库安装 libimobiledevice > brew install libimobiledevice 使用本机与苹果iOS设备的服务进行通信的库。 ideviceinstaller brew install ideviceinstaller 获取设备udid、安装app、卸载app、获取bundleid carthage > brew install carthage 第三方库…

【Redis】Redis最佳实践/经验总结

【Redis】Redis最佳实践/经验总结 文章目录 【Redis】Redis最佳实践/经验总结1. Redis键值设计1.1 优雅的key结构1.2 拒绝BigKey1.2.1 BigKey的危害1.2.2 如何发现BigKey1.2.3 如何删除BigKey 1.3 恰当的数据类型1.3.1 例11.3.2 例2 2. 批处理优化2.1 Pipeline2.1.1 单个命令的…

ROM和RAM的工作原理(DRAM和DROM)以及DRAM的刷新方法

只读存储器ROM: ROM和RAM都是支持随机存取的存储器&#xff0c;其中SRAM和DRAM均为易失性半导体存储器。而ROM中一旦有了信息&#xff0c;就不能轻易改变&#xff0c;即使掉电也不会丢失&#xff0c;它在计算机系统中是只供读出的存储器。ROM器件有两个显著的优点: 1)结构简单&…

RabbitMQ 消息丢失的场景,如何保证消息不丢失?

一.RabbitMQ消息丢失的三种情况 第一种&#xff1a;生产者弄丢了数据。生产者将数据发送到 RabbitMQ 的时候&#xff0c;可能数据就在半路给搞丢了&#xff0c;因为网络问题啥的&#xff0c;都有可能。 第二种&#xff1a;RabbitMQ 弄丢了数据。MQ还没有持久化自己挂了 第三种…

软考A计划-系统集成项目管理工程师--一般常识-中

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff…

【深度学习推荐系统 理论篇】一、Wide Deep Learning for Recommender Systems

前言 在搜广推业务做了3年工程&#xff0c;最近终于有空整理下&#xff0c;完整的梳理下自己的知识架构&#xff08;预计分为理论篇/工程篇&#xff09; Wide & Deep论文链接&#xff1a;https://arxiv.org/abs/1606.07792 另外王喆老师《深度学习推荐系统》中&#xff…