Unity3d bounds包围盒 和collider碰撞器区别

news2024/11/26 12:50:10

Bounds 外包围盒

Bounds 叫作外包围盒、边界框、外扩矩形.是struct 结构体。而我们获得Bounds的主要途径有三种:Render,Collider,Mesh。

Render.bounds 世界坐标

Collider.bounds 世界坐标

Mesh.bounds  本地坐标

        var m= GetComponent<MeshFilter>().bounds;
        var c = GetComponent<Collider>().bounds;
        var r = GetComponent<Renderer>().bounds;

把 Mesh.bounds 本地坐标换算成世界坐标bounds 

  //把本地坐标换算成世界坐标
        var centerPoint = transform.TransformPoint(bounds.center);
        Bounds newBounds = new Bounds(centerPoint, bounds.size);

碰撞器绿方框

Bounds和碰撞器的绿方框(绿色线)的区别

碰撞器的方框始终跟着模型旋转移动,缩放跟着模型的,只要模型不缩放它也不缩放

Bounds 跟随模型移动,而不会跟模型着旋转,而是随着模型旋转而缩放变大变小,始终包裹模型.

下面红色方框就是 Bounds 方框

Bounds属性

只读属性

我们不能直接修改 Bounds 结构体里头的 center 和 size 属性都不能直接设置,而且 BoxCollider 的 bounds 属性也不能.

.bounds.center;  //中心点坐标
.bounds.size;        //盒子的总尺寸,xyz长度
.bounds.min;            //最小点的位置:左下角
.bounds.max;                //最大点的位置:右上角
.bounds.center.x;            //中心点的X
.bounds.center.y;                //中心点的Y

Bounds 常用方法

// 点point是否在这个包围盒内部
public bool Contains(Vector3 point);

// bounds会自动扩充大小(改变center和extens),来包含这个point
public void Encapsulate(Vector3 point);

// bounds会自动扩充大小(改变center和extens),把原本的bounds和传入的bounds都包含进来
public void Encapsulate(Bounds bounds);

// 这条射线是否与这个包围盒相交
public bool IntersectRay(Ray ray);

//包围盒最近的点
public Vector3 ClosestPoint(Vector3 point);

//设置边界框的最小最大值
public void SetMinMax(Vector3 min, Vector3 max);

多物体Bounds, Encapsulate方法

计算多物体Bounds,则要遍历所有子物体,然后调用Encapsulate方法来计算。

Bounds bounds;
Renderer[] renderers = model.GetComponentsInChildren<Renderer>();
for (int i = 0; i < renderers.Length; i++)
{
    bounds.Encapsulate(renderers[i].bounds);
}


 

计算包围盒的八个顶点

center = bounds.center;
ext = bounds.extents;

float deltaX = Mathf.Abs(ext.x);
float deltaY = Mathf.Abs(ext.y);
float deltaZ = Mathf.Abs(ext.z);

#region 获取AABB包围盒顶点
points = new Vector3[8];
points[0] = center + new Vector3(-deltaX, deltaY, -deltaZ);        // 上前左(相对于中心点)
points[1] = center + new Vector3(deltaX, deltaY, -deltaZ);         // 上前右
points[2] = center + new Vector3(deltaX, deltaY, deltaZ);          // 上后右
points[3] = center + new Vector3(-deltaX, deltaY, deltaZ);         // 上后左

points[4] = center + new Vector3(-deltaX, -deltaY, -deltaZ);       // 下前左
points[5] = center + new Vector3(deltaX, -deltaY, -deltaZ);        // 下前右
points[6] = center + new Vector3(deltaX, -deltaY, deltaZ);         // 下后右
points[7] = center + new Vector3(-deltaX, -deltaY, deltaZ);        // 下后左
#endregion

 

绘制bounds方框

    /// <summary>
    /// 绘制Bounds方框
    /// </summary>
    /// <param name="bounds"></param>
    /// <param name="color"></param>
    /// <param name="offsetSize"></param>
    /// <param name="duration"></param>
    public static void DrawBoundBoxLine(Bounds bounds, Color color = default(Color), float offsetSize = 1f, float duration = 0.1f)
    {
        //先计算出包围盒8个点
        Vector3[] points = new Vector3[8];
        var width_x = bounds.size.x * offsetSize;
        var hight_y = bounds.size.y * offsetSize;
        var length_z = bounds.size.z * offsetSize;

        var LeftBottomPoint = bounds.min;
        var rightUpPoint = bounds.max;
        var centerPoint = bounds.center;
        var topPoint = new Vector3(centerPoint.x, centerPoint.y + hight_y / 2, centerPoint.z);
        var bottomPoint = new Vector3(centerPoint.x, centerPoint.y - hight_y * 0.5f, centerPoint.z);

        points[0] = LeftBottomPoint + Vector3.right * width_x;
        points[1] = LeftBottomPoint + Vector3.up * hight_y;
        points[2] = LeftBottomPoint + Vector3.forward * length_z;

        points[3] = rightUpPoint - Vector3.right * width_x;
        points[4] = rightUpPoint - Vector3.up * hight_y;
        points[5] = rightUpPoint - Vector3.forward * length_z;

        points[6] = LeftBottomPoint;
        points[7] = rightUpPoint;

        Debug.DrawLine(LeftBottomPoint, points[0], color, duration);
        Debug.DrawLine(LeftBottomPoint, points[1], color, duration);
        Debug.DrawLine(LeftBottomPoint, points[2], color, duration);

        Debug.DrawLine(rightUpPoint, points[3], color, duration);
        Debug.DrawLine(rightUpPoint, points[4], color, duration);
        Debug.DrawLine(rightUpPoint, points[5], color, duration);

        Debug.DrawLine(points[1], points[3], color, duration);
        Debug.DrawLine(points[2], points[4], color, duration);
        Debug.DrawLine(points[0], points[5], color, duration);

        Debug.DrawLine(points[2], points[3], color, duration);
        Debug.DrawLine(points[0], points[4], color, duration);
        Debug.DrawLine(points[1], points[5], color, duration);
    }

绘制碰撞器方框 -方法1

    /// <summary>
    /// 绘制boxCollider的绿色方框
    /// </summary>
    /// <param name="color"></param>
    void DrawGizmosOnRunTime(Color color)
    {
        var boxCollider = GetComponent<BoxCollider>();
            Gizmos.color = color;
            Matrix4x4 rotationMatrix = Matrix4x4.TRS(boxCollider.transform.position, boxCollider.transform.rotation, boxCollider.transform.lossyScale);
            Gizmos.matrix = rotationMatrix;
            Gizmos.DrawWireCube(boxCollider.center, boxCollider.size);
        
    }

     void OnDrawGizmos()
    {
        DrawGizmosOnRunTime(Color.red);
    }

绘制碰撞器方框 -方法2

    /// <summary>
    /// 绘制boxCollider的绿色方框
    /// </summary>
    /// <param name="boxCollider"></param>
    /// <param name="color"></param>
    /// <param name="offsetSize"></param>
    public static void DrawOnGameViewRuntime(BoxCollider boxCollider, Color color = default(Color), float offsetSize = 1f)
    {
        
        float width = 0.1f;
        Vector3 rightDir = boxCollider.transform.right.normalized;
        Vector3 forwardDir = boxCollider.transform.forward.normalized;
        Vector3 upDir = boxCollider.transform.up.normalized;
        Vector3 center = boxCollider.transform.position + boxCollider.center;
        Vector3 size = boxCollider.size * offsetSize;
        size.x *= boxCollider.transform.lossyScale.x;
        size.y *= boxCollider.transform.lossyScale.y;
        size.z *= boxCollider.transform.lossyScale.z;


        Debug.DrawLine(center + upDir * size.y / 2f + rightDir * size.x / 2f + forwardDir * size.z / 2f, center + upDir * size.y / 2f - rightDir * size.x / 2f + forwardDir * size.z / 2f, color);
        Debug.DrawLine(center - upDir * size.y / 2f + rightDir * size.x / 2f + forwardDir * size.z / 2f, center - upDir * size.y / 2f - rightDir * size.x / 2f + forwardDir * size.z / 2f, color);
        Debug.DrawLine(center + upDir * size.y / 2f + rightDir * size.x / 2f + forwardDir * size.z / 2f, center - upDir * size.y / 2f + rightDir * size.x / 2f + forwardDir * size.z / 2f, color);
        Debug.DrawLine(center + upDir * size.y / 2f - rightDir * size.x / 2f + forwardDir * size.z / 2f, center - upDir * size.y / 2f - rightDir * size.x / 2f + forwardDir * size.z / 2f, color);
        Debug.DrawLine(center + upDir * size.y / 2f + rightDir * size.x / 2f - forwardDir * size.z / 2f, center + upDir * size.y / 2f - rightDir * size.x / 2f - forwardDir * size.z / 2f, color);
        Debug.DrawLine(center - upDir * size.y / 2f + rightDir * size.x / 2f - forwardDir * size.z / 2f, center - upDir * size.y / 2f - rightDir * size.x / 2f - forwardDir * size.z / 2f, color);
        Debug.DrawLine(center + upDir * size.y / 2f + rightDir * size.x / 2f - forwardDir * size.z / 2f, center - upDir * size.y / 2f + rightDir * size.x / 2f - forwardDir * size.z / 2f, color);
        Debug.DrawLine(center + upDir * size.y / 2f - rightDir * size.x / 2f - forwardDir * size.z / 2f, center - upDir * size.y / 2f - rightDir * size.x / 2f - forwardDir * size.z / 2f, color);
        Debug.DrawLine(center + upDir * size.y / 2f + rightDir * size.x / 2f + forwardDir * size.z / 2f, center + upDir * size.y / 2f + rightDir * size.x / 2f - forwardDir * size.z / 2f, color);
        Debug.DrawLine(center - upDir * size.y / 2f + rightDir * size.x / 2f + forwardDir * size.z / 2f, center - upDir * size.y / 2f + rightDir * size.x / 2f - forwardDir * size.z / 2f, color);
        Debug.DrawLine(center + upDir * size.y / 2f - rightDir * size.x / 2f + forwardDir * size.z / 2f, center + upDir * size.y / 2f - rightDir * size.x / 2f - forwardDir * size.z / 2f, color);
        Debug.DrawLine(center - upDir * size.y / 2f - rightDir * size.x / 2f + forwardDir * size.z / 2f, center - upDir * size.y / 2f - rightDir * size.x / 2f - forwardDir * size.z / 2f, color);
    }

求两个包围盒之间的距离

    // Distance between two ClosestPointOnBounds
    // this is needed in cases where entites are really big. in those cases,
    // we can't just move to entity.transform.position, because it will be
    // unreachable. instead we have to go the closest point on the boundary.
    //
    // Vector3.Distance(a.transform.position, b.transform.position):
    //    _____        _____
    //   |     |      |     |
    //   |  x==|======|==x  |
    //   |_____|      |_____|
    //
    //
    // Utils.ClosestDistance(a.collider, b.collider):
    //    _____        _____
    //   |     |      |     |
    //   |     |x====x|     |
    //   |_____|      |_____|
    //
    public static float ClosestDistance(Collider a, Collider b)
    {
        return Vector3.Distance(a.ClosestPointOnBounds(b.transform.position),
                                b.ClosestPointOnBounds(a.transform.position));
    }

 求点A到包围盒最近的点,ClosestPoint

 计算所有包围盒的中心点

计算出多个Bounds的中心点

[MenuItem ("MyMenu/Do Test")]
	static void Test () 
	{
		Transform parent = 	Selection.activeGameObject.transform;
		Vector3 postion = parent.position;
		Quaternion rotation = parent.rotation;
		Vector3 scale = parent.localScale;
		parent.position = Vector3.zero;
		parent.rotation = Quaternion.Euler(Vector3.zero);
		parent.localScale = Vector3.one;
 
 
		Vector3 center = Vector3.zero;
		Renderer[] renders = parent.GetComponentsInChildren<Renderer>();
		foreach (Renderer child in renders){
			center += child.bounds.center;   
		}
		center /= parent.GetComponentsInChildren<Transform>().Length; 
		Bounds bounds = new Bounds(center,Vector3.zero);
		foreach (Renderer child in renders){
			bounds.Encapsulate(child.bounds);   
		}
	
		parent.position = postion;
		parent.rotation = rotation;
		parent.localScale = scale;
 
		foreach(Transform t in parent){
			t.position = t.position -  bounds.center;
		}
		parent.transform.position = bounds.center + parent.position;
 
	}

参考 

  https://blog.csdn.net/sinat_25415095/article/details/104588989

https://www.5axxw.com/questions/content/imitu9

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

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

相关文章

抖音用户浏览行为数据分析与挖掘

下文部分代码省略&#xff0c;完整项目代码及数据集链接&#xff1a;抖音用户浏览行为数据分析与挖掘 目录1.特征指标构建0. 项目介绍与说明**数据集说明**浏览行为1. 数据简单处理2. 特征指标构建用户指标分析&#xff1a;作者指标分析&#xff1a;作品指标分析&#xff1a;3.…

5分钟快速上手Nmap指令(基于Kali系统)

前言正文1、修改Kali系统中网络配置2、Nmap简介2.1 用途2.2优势2.3 相关知识3、Nmap中最常用的命令3.1 单主机扫描3.2 多目标扫描3.3 检测目标主机漏洞3.3 时序选择3.4 保存4、kali系统中常见报错参考文献前言 本篇为理论篇&#xff0c;主要为CTF攻防做铺垫&#xff0c;围绕 基…

[附源码]SSM计算机毕业设计影院售票系统JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

mac m1 mysqlworkbench8 Unknown table ‘COLUMN_STATISTICS‘

原因&#xff1a;本地mysql版本是8&#xff0c;远程是mariaDb-10&#xff0c;版本不匹配导致报错。 仔细看mysqlworkbench8.0导出时的错误信息&#xff0c;有mysqldump的具体路径。 mac os (m1, ventura系统)&#xff0c;具体位置是这里&#xff1a; /Applications/MySQLWor…

【树莓派开发日记1】1.3k预算的树莓派+显示屏+键鼠的选型与拆箱物理安装

树莓派开发日记1 经过了漫长的上课与考试周期&#xff0c;终于有时间闲下来进行技术栈的开发与学习 作为立志成为优秀机器人开发者的青年工程师&#xff08;青春版&#xff09;&#xff0c;不可能不去了解微机处理系统和Ubuntu系统&#xff0c;所以在此又给自己开了一个大坑 …

OpManager 帮助排查网络延迟问题

什么是网络延迟 网络中的延迟是指数据通过网络传输到其预期目的地所需的时间。它通常表示为往返延迟&#xff0c;即数据从一个位置传输到另一个位置所需的时间。 什么原因导致网络延迟 有四个主要原因会影响网络延迟。其中包括&#xff1a; 传输介质&#xff0c;例如 WAN 或…

JUC并发编程第六篇,带你了解Java内存模型JMM

JUC并发编程第六篇&#xff0c;带你了解Java内存模型JMM一、Java Memory Model&#xff08;Java内存模型&#xff09;是什么&#xff1f;二、JMM规范三大特性1. 可见性2. 原子性3. 有序性三、JMM规范下多线程对变量的读写过程四、JMM规范下多线程先行发生原则&#xff08;happe…

Oracle面试题整理

目录 Oracle面试题整理 1.MySQL和Oracle的区别&#xff1a; 2.Oracle中function和procedure的区别&#xff1f; 3. 比较truncate和delete命令 &#xff1f; 4.oralce中 rowid, rownum的定义 5. 事务的特性&#xff08;ACID&#xff09;是指什么 6. 列举几种表连接方式…

[附源码]计算机毕业设计springboot天狗电子商城系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

plink2.0和plink1.9的忧伤笔记

虽然plink2.0已经存在好久了&#xff0c;但是一直用的都是plink1.9&#xff0c;因为语法熟悉。更主要是plink2.0语法变动太大&#xff0c;害怕步子迈得太大了…… 今天看一下plink2.0的读入和输出数据常用参数&#xff0c; plink2.0用是不会用的&#xff0c;2022年都不会用&am…

计算机网络基础

前言 计算机网络学习的核心内容就是网络协议的学习。网络协议是为计算机网络中进行数据交换而建立的规则、标准或者说是约定的集合。因为不同用户的数据终端可能采取的字符集是不同的&#xff0c;两者需要进行通信&#xff0c;必须要在一定的标准上进行。一个很形象地比喻就是…

平时健身买什么耳机好、分享五款最好的运动耳机推荐

不少人喜欢在健身房或者户外运动中使用手机或者MP3来听音乐&#xff0c;这种方式不仅可以减少运动中的枯燥感&#xff0c;而且那些节奏较强的音乐还能够进一步激发人们的运动潜能&#xff0c;达到事半功倍的效果。作为音乐传递的桥梁&#xff0c;一款佩戴舒适的运动耳机是必不可…

又撸了一个开源项目!!!

花了两周左右&#xff0c;写了一个客户关系管理系统&#xff0c;基于 Vue Go 实现&#xff0c;主要功能有仪表盘、客户管理、合同管理、产品管理&#xff0c;订阅等功能。 前几天已经在 Github 上开源了&#xff0c;今天也把项目部署到云服务器上了&#xff0c;很完美&#x…

负载均衡组件Ribbon核心-@LoadBalanced-上

引言 书接上篇 微服务负载均衡小能手-Ribbon 使用RIbion实现负载均衡远程调用 Bean LoadBalanced public RestTemplate restTemplate(){return new RestTemplate(); } 都知道没有LoadBalanced注解前&#xff0c;RestTemplate就是一个简单的http请求工具类&#xff0c;贴上该…

AI-多模态-2021:DALL-E模型【文本生成图像工具】【OpenAI】

Dall-e&#xff1a;从拟物文字到图片的创造 人类不断地从五种感官接收和整合信息&#xff0c;通过视觉、听觉、触觉、嗅觉和味觉等生物信息来理解文字和图片。然而文字和图片属于符号&#xff0c;Dall-e模型在理解符号的含义时并不能通过生物信息的传递。通过将对自然语言的理…

Ambari-yarn-timeline 内置 HBase数据表清理

HDP 集群 timeline 内置的 HBase 数据表持续增大&#xff0c;我们将默认TTL30改 为7 天。 ambari界面YARN 服务中 的 timeline v2.0 timeline 内置 HBase数据HDFS路径 &#xff1a; 表在HDFS上的大小 使用如下命令进入 Hbase shell [hdfswinner-backup-hdp root]$ hbase -…

网站变灰代码如何让网页变灰

1.网站变灰代码应用场景 一般在清明节&#xff0c;全国哀悼日&#xff0c;大地震的日子&#xff0c;以及一些影响力很大的伟人逝世或纪念日的时候&#xff0c;身为站长的我们都会让自己的网站的全部网页变成灰色&#xff08;黑白色&#xff09;&#xff0c;以表示我们对逝者的…

数据分析之人力资源管理驾驶舱

驾驶舱是数据分析报表中用于展示关键分析指标和综合展示数据情况的&#xff0c;因此需要展示的内容多&#xff0c;需要做的内容甄选也多。 一 前言 人力资源作为企业的关键生产力&#xff0c;是一个企业成长发展的根本。随着“知识经济”时代的到来、市场竞争的加剧&#xff…

Shiro-全面详解(学习总结---从入门到深化)

Shiro介绍_Shiro简介 Shiro是apache旗下的一个开源安全框架&#xff0c;它可以帮助我们完成身 份认证&#xff0c;授权、加密、会话管理等功能。它有如下特点&#xff1a; 1、易于理解的API 简单的身份认证&#xff0c;支持多种数据源 2、简单的授权和鉴权 3、简单的加密API 4、…

《机器学习实战》11.Apriori算法进行关联分析

目录 使用Apriori算法进行关联分析 1 关联分析 2 Apriori原理 3 使用Apriori算法来发现频繁集 3.1 生成候选项集 3.2 组织完整的Apriori算法 4 从频繁项集中挖掘关联规则 5 示例&#xff1a;发现国会投票中的模式 6 示例&#xff1a;发现毒蘑菇的相似特征 7 本章小结…