博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Unity内实现OBB包围盒算法
阅读量:6343 次
发布时间:2019-06-22

本文共 4016 字,大约阅读时间需要 13 分钟。

前言

作为碰撞盒的检测,OBB是一个常用的办法。网上有很多文章是介绍原理的,具体可以查一下。 以下给出OBB的Unity实现版本。亲测可跑。

参考 :

效果

实现

基础:对象拥有BoxCollider控件(用作包围盒)和MeshRenderer控件(模型)

步骤:1.更新BoxCollider 2.更新AABB

更新BoxCollider。这个只需要在编辑器中更新一下即可,不需要运行时不断更新。

using UnityEngine;public class UpdateBoxColliderHelp{    private Transform m_Transform;    private MeshRenderer m_MeshRenderer;    private BoxCollider m_BoxCollider;    public UpdateBoxColliderHelp(Transform transform)    {        m_Transform = transform;        m_MeshRenderer = m_Transform.GetComponent
(); m_BoxCollider = m_Transform.GetComponent
(); UpdateBoxCollider(); } public void UpdateBoxCollider() { if (m_MeshRenderer == null || m_BoxCollider == null) { Debug.Log(string.Format("对象{0}没有指定控件,跳过。", m_Transform.name)); return; } Vector3 position = m_Transform.position; Vector3 scale = m_Transform.localScale; Quaternion rotation = m_Transform.rotation; m_Transform.position = Vector3.zero; m_Transform.localScale = Vector3.one; m_Transform.rotation = new Quaternion(0,0,0,1); m_BoxCollider.size = m_MeshRenderer.bounds.size; m_BoxCollider.center = m_MeshRenderer.bounds.center; m_Transform.position = position; m_Transform.localScale = scale; m_Transform.rotation = rotation; Debug.Log(string.Format("对象{0}的BoxCollider更新完毕。", m_Transform.name)); }}复制代码

OBB的实现

using System;using UnityEngine;public class OBBRect{    public Transform m_Transform;    public BoxCollider m_BoxCollider;    private double m_Rotation;    public Vector2 m_Extents;    public Vector2[] m_Axiss;    public OBBRect(Transform transform)    {        m_Transform = transform;        m_BoxCollider = m_Transform.GetComponent
(); m_Axiss = new Vector2[2]; SetExtents(); } private void SetExtents() { Quaternion rotation = m_Transform.rotation; m_Transform.rotation = new Quaternion(0, 0, 0, 1); Vector3 center = m_BoxCollider.center; Vector3 size = m_BoxCollider.size / 2; Vector3 Point1 = new Vector3(center.x + size.x, center.y, center.z - size.z); Vector3 Point2 = new Vector3(center.x - size.x, center.y, center.z + size.z); Point1 = m_Transform.localToWorldMatrix.MultiplyPoint3x4(Point1); Point2 = m_Transform.localToWorldMatrix.MultiplyPoint3x4(Point2); m_Extents = new Vector2(Mathf.Abs(Point1.x - Point2.x)/2,Mathf.Abs(Point2.z - Point1.z)/2); m_Transform.rotation = rotation; } public float dot(Vector2 a, Vector2 b) { return Mathf.Abs(a.x * b.x + a.y * b.y); } public float getProjectionRadius(Vector2 axis) { return (m_Extents.x * dot(m_Axiss[0], axis) + m_Extents.y * dot(m_Axiss[1], axis)); } public void Update() { m_Rotation = m_Transform.eulerAngles.y * Math.PI / 180; m_Axiss[0] = new Vector2( (float) Math.Cos(m_Rotation), -(float) Math.Sin(m_Rotation)); m_Axiss[1] = new Vector2(-m_Axiss[0].y, m_Axiss[0].x); } public bool intersects(OBBRect other) { Update(); other.Update(); Vector2 distanceVector = new Vector2(m_Transform.position.x - other.m_Transform.position.x, m_Transform.position.z - other.m_Transform.position.z); Vector2[] checkObbVector2s = { m_Axiss[0], m_Axiss[1], other.m_Axiss[0], other.m_Axiss[1], }; for (int index = 0; index < checkObbVector2s.Length; index++) { Vector2 curVector2 = checkObbVector2s[index]; if ((getProjectionRadius(curVector2) + other.getProjectionRadius(curVector2)) <= dot(distanceVector, curVector2)) { return false; } } return true; }}复制代码

注意点

1.先更新包围盒,所有计算(宽高这些)都是基于包围盒的数据。

2.该算法是做到模型忽略Y轴进行检测,需要的话可以自己补充一下。思路:多一个轴向计算。

3.计算Sin值和参考文章不一样,这里是使用-Sin才得到正确的数值。原因我也还没想到。。知道的话麻烦告诉我一下哈哈哈

转载于:https://juejin.im/post/5cf08fc0f265da1b8a4f0306

你可能感兴趣的文章
从 JS 编译原理到作用域(链)及闭包
查看>>
flutter 教程(一)flutter介绍
查看>>
CSS面试题目及答案
查看>>
【从蛋壳到满天飞】JS 数据结构解析和算法实现-Arrays(数组)
查看>>
每周记录(三)
查看>>
Spring自定义注解从入门到精通
查看>>
笔记本触摸板滑动事件导致连滑的解决方式
查看>>
Android推荐常用的31个库
查看>>
Runtime 学习:消息传递
查看>>
你了解BFC吗?
查看>>
linux ssh tunnel使用
查看>>
十、详解FFplay音视频同步
查看>>
自定义元素探秘及构建可复用组件最佳实践
查看>>
小猿圈Python教程之全面解析@property的使用
查看>>
mpvue开发小程序所遇问题及h5转化方案
查看>>
View和Activity的生命周期
查看>>
解决PHP下载大文件失败,并限制下载速度
查看>>
java B2B2C Springcloud电子商城系统—Feign实例
查看>>
java B2B2C Springcloud多租户电子商城系统 (五)springboot整合 beatlsql
查看>>
Throwable是一个怎样的类?
查看>>