Unity 限制物体在Bounds 包围盒控制移动

我列举两种方式,其实最终都是涉及到包围盒使用问题。可以通过 Box Collider 的 bounds 属性来获取物体的包围盒(Bounds)也可以直接设置Bounds包围盒使用,从而限制其移动范围。不过需要注意,直接使用 Box Collider 的 size 属性可能无法直接替代 Bounds 的功能,以下是具体实现方案:

1. 方案:使用 Bounds 限制移动范围

Bounds 类 来定义一个三维空间范围(如轴对齐包围盒,AABB),并限制物体的移动使其不超出该范围。以下是具体实现方案:

步骤 1:定义 Bounds 范围

首先,创建一个 Bounds 对象来定义物体允许移动的空间范围,包括中心点 (center) 和扩展范围 (extents):

// 定义三维空间范围的中心点和扩展范围
Bounds movementBounds = new Bounds();
movementBounds.center = new Vector3(0f, 0f, 0f); // 范围中心点
movementBounds.extents = new Vector3(10f, 5f, 10f); // 各轴方向的扩展范围(半宽、半高、半深)

步骤 2:在移动时限制位置

在物体的移动逻辑中(如 Update() 或 FixedUpdate()),检查物体的位置是否在 Bounds 范围内,并通过 Mathf.Clamp 限制其坐标:

方案 1:直接限制物体中心点的位置

void Update()
{// 获取物体当前位置(例如通过键盘输入或脚本控制)Vector3 desiredPosition = transform.position + movementDirection * speed * Time.deltaTime;// 使用 Bounds.Clamp 将位置限制在范围内desiredPosition = movementBounds.ClosestPoint(desiredPosition);// 或者手动对每个轴进行 Clamp(更灵活)desiredPosition.x = Mathf.Clamp(desiredPosition.x, movementBounds.min.x, movementBounds.max.x);desiredPosition.y = Mathf.Clamp(desiredPosition.y, movementBounds.min.y, movementBounds.max.y);desiredPosition.z = Mathf.Clamp(desiredPosition.z, movementBounds.min.z, movementBounds.max.z);// 更新物体位置transform.position = desiredPosition;
}

方案 2:考虑物体自身的大小(如碰撞体或模型)

如果物体有碰撞体或模型,需要确保其整体 不超出范围,此时需将物体的 Bounds 加入计算:

void Update()
{// 假设物体有碰撞体(Collider),获取其局部包围盒Bounds objectBounds = GetComponent<Collider>().bounds;Vector3 objectExtents = objectBounds.extents;// 计算物体允许的最大位置(避免超出范围)Vector3 maxAllowedPosition = movementBounds.max - objectExtents;Vector3 minAllowedPosition = movementBounds.min + objectExtents;// 获取物体当前位置(例如通过输入)Vector3 desiredPosition = transform.position + movementDirection * speed * Time.deltaTime;// 对每个轴进行 ClampdesiredPosition.x = Mathf.Clamp(desiredPosition.x, minAllowedPosition.x, maxAllowedPosition.x);desiredPosition.y = Mathf.Clamp(desiredPosition.y, minAllowedPosition.y, maxAllowedPosition.y);desiredPosition.z = Mathf.Clamp(desiredPosition.z, minAllowedPosition.z, maxAllowedPosition.z);// 更新位置transform.position = desiredPosition;
}

步骤 3:动态调整 Bounds(可选)

如果范围需要动态变化(如随场景变化),可以在运行时重新设置 movementBounds 的中心或扩展范围:

// 动态更新 Bounds
void AdjustBounds()
{movementBounds.center = new Vector3(5f, 2f, -3f); // 新中心点movementBounds.extents = new Vector3(15f, 8f, 12f); // 新扩展范围
}

注意事项 物理引擎兼容性 : 如果物体使用 Rigidbody,直接设置 transform.position
可能会导致物理引擎冲突。此时应使用 Rigidbody.MovePosition() 或调整 velocity:

rigidbody.MovePosition(desiredPosition);

性能优化 :
如果物体移动频繁,建议将 movementBounds 存储为类成员变量,避免重复创建。
可视化调试 :
可通过 Gizmos 绘制 Bounds 边界辅助调试:

void OnDrawGizmos()
{Gizmos.color = Color.red;Gizmos.DrawWireCube(movementBounds.center, movementBounds.size);
}

完整代码示例

using UnityEngine;public class BoundMovement : MonoBehaviour
{public float speed = 5f; // 移动速度public Vector3 movementDirection = Vector3.zero; // 移动方向(可通过输入设置)private Bounds movementBounds; // 定义移动范围void Start(){// 初始化 Bounds:中心点在 (0, 0, 0),范围在 X/Y/Z 轴方向扩展 10/5/10 单位movementBounds = new Bounds(new Vector3(0f, 0f, 0f), new Vector3(20f, 10f, 20f));}void Update(){// 计算目标位置Vector3 desiredPosition = transform.position + movementDirection * speed * Time.deltaTime;// 限制位置在 Bounds 内desiredPosition = movementBounds.ClosestPoint(desiredPosition);// 更新物体位置transform.position = desiredPosition;}void OnDrawGizmos(){// 可视化 Bounds 范围Gizmos.color = Color.red;Gizmos.DrawWireCube(movementBounds.center, movementBounds.size);}
}

通过以上方法,精确控制物体在三维空间中的移动范围,确保其始终位于定义的 Bounds 内。

2. 方案:使用 Box Collider 的 Bounds 限制移动范围

步骤 1:设置 Box Collider

为物体添加一个 Box Collider 组件(或使用已有的)。
调整 Box Collider 的 Size 属性,使其覆盖你希望物体移动的三维空间范围。

步骤 2:获取 Collider 的 Bounds

通过 Collider.bounds 属性获取物体的包围盒范围(即 Box Collider 的 Size 和位置定义的范围)。

步骤 3:限制物体移动

在移动逻辑中,通过 Bounds 的 ClosestPoint 或手动 Clamp 限制物体的位置:

using UnityEngine;public class BoxBoundsMovement : MonoBehaviour
{public float speed = 5f; // 移动速度private BoxCollider movementCollider; // 用于定义移动范围的 Box Colliderprivate Bounds movementBounds; // 通过 Box Collider 获取的 Boundsvoid Start(){// 1. 确保物体有 Box Collider(或通过代码添加)movementCollider = GetComponent<BoxCollider>();if (movementCollider == null){movementCollider = gameObject.AddComponent<BoxCollider>();}// 2. 设置 Box Collider 的 Size 和 Center(可选,根据需求调整)movementCollider.size = new Vector3(20f, 10f, 20f); // 定义移动范围的大小movementCollider.center = Vector3.zero; // 定义移动范围的中心点(相对于物体的位置)// 3. 获取 Bounds(会根据 Box Collider 的 Size 和 Center 自动计算)movementBounds = movementCollider.bounds;}void Update(){// 获取物体当前位置(例如通过输入)Vector3 desiredPosition = transform.position + (movementDirection * speed * Time.deltaTime);// 方法 1:使用 Bounds.ClosestPoint 自动限制位置desiredPosition = movementBounds.ClosestPoint(desiredPosition);// 方法 2:手动 Clamp 每个轴(更灵活)// desiredPosition.x = Mathf.Clamp(desiredPosition.x, movementBounds.min.x, movementBounds.max.x);// desiredPosition.y = Mathf.Clamp(desiredPosition.y, movementBounds.min.y, movementBounds.max.y);// desiredPosition.z = Mathf.Clamp(desiredPosition.z, movementBounds.min.z, movementBounds.max.z);// 更新物体位置transform.position = desiredPosition;}void OnDrawGizmos(){// 可视化 Bounds 范围if (movementBounds != null){Gizmos.color = Color.blue;Gizmos.DrawWireCube(movementBounds.center, movementBounds.size);}}
}

关键点说明 Collider 的 Bounds 是动态的 : Collider.bounds 会根据物体的 Transform
位置、旋转和缩放 自动更新,因此如果物体的父对象有缩放或旋转,需要确保 Bounds 的计算正确。 如果物体本身有缩放,Collider 的
bounds 会自动反映缩放后的大小。 与物体自身大小的兼容性 : 如果物体本身有 Collider 或模型,需要确保移动范围的 Box
Collider 足够大,以包含物体的整体体积。例如:

// 计算物体自身的包围盒(假设物体有其他 Collider)
Bounds objectBounds = GetComponentInChildren<Collider>().bounds;
// 确保物体不超出移动范围
Vector3 maxAllowedPosition = movementBounds.max - objectBounds.extents;
Vector3 minAllowedPosition = movementBounds.min + objectBounds.extents;

物理引擎兼容性 :
如果物体使用 Rigidbody,建议使用 Rigidbody.MovePosition() 而非直接设置 transform.position,以避免物理引擎冲突:

rigidbody.MovePosition(desiredPosition);

对比 Bounds 和 Box Collider 的优缺点

方法优点缺点
手动设置 Bounds灵活,无需依赖物理组件需手动维护范围参数
使用 Box Collider自动关联物体的 Transform 和缩放需依赖 Collider 组件,可能增加物理计算开销

适用场景

使用 Box Collider 的 Bounds :

当物体的移动范围需要与物理碰撞体(如玩家可移动区域)直接关联时。
当需要动态调整范围时(例如通过脚本调整 Box Collider 的 size 和 center)。

手动设置 Bounds :

当不需要物理碰撞,仅需要纯逻辑上的范围限制时。
当希望完全控制范围参数,而不依赖任何组件时。

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

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

相关文章

SpringBoot中缓存@Cacheable出错

SpringBoot中使用Cacheable: 错误代码&#xff1a; Cacheable(value "FrontAdvertiseVOList", keyGenerator "cacheKey") Override public List<FrontAdvertiseVO> getFrontAdvertiseVOList(Integer count) {return this.list(Wrappers.<Adve…

位集合(STL bitset)简介

【bitset 官方网址】 https://cplusplus.com/reference/bitset/bitset/ 位集合&#xff08;Bit Set&#xff09;是一种高效存储和操作布尔值&#xff08;true/false&#xff09;或二进制位&#xff08;0/1&#xff09;的数据结构&#xff0c;主要用于处理大规模整数集合或状态标…

基于SDN环境下的DDoS异常攻击的检测与缓解

参考以下两篇博客&#xff0c;最后成功&#xff1a; 基于SDN的DDoS攻击检测和防御方法_基于sdn的ddos攻击检测与防御-CSDN博客 利用mininet模拟SDN架构并进行DDoS攻击与防御模拟&#xff08;Ryumininetsflowpostman&#xff09;_mininet模拟dos攻击-CSDN博客 需求 H2 模拟f…

责任链模式:构建灵活可扩展的请求处理体系(Java 实现详解)

一、责任链模式核心概念解析 &#xff08;一&#xff09;模式定义与本质 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种行为型设计模式&#xff0c;其核心思想是将多个处理者对象连成一条链&#xff0c;并沿着这条链传递请求&#xff0c;直到有某…

如何进行页面前端监控

&#x1f9d1;‍&#x1f4bb; 写在开头 点赞 收藏 学会&#x1f923;&#x1f923;&#x1f923; 前端监控主要分三个方向 前端性能&#xff08;用户体验优化&#xff09; 异常监控 业务指标跟 下面我来分别介绍三类指标如何获取 1&#xff09;前端性能指标&#xff1a; …

Ajax技术分析方法全解:从基础到企业级实践(2025最新版)

引言 Ajax技术自2005年正式命名以来,已支撑全球83%的Web应用实现异步交互。2025年最新数据显示,单页面应用(SPA)的Ajax请求密度已达日均120亿次/应用。本文将系统化解析Ajax分析方法论,涵盖从基础原理到企业级工程实践的完整技术栈。 一、Ajax技术架构解构 1.1 核心组件…

git管理github上的repository

1. 首先注册github并创建一个仓库&#xff0c;这个很简单&#xff0c;网上教程也很多&#xff0c;就不展开说了 2. 安装git&#xff0c;这个也很简单&#xff0c;不过这里有个问题就是你当前windows的用户名即&#xff1a;C/Users/xxx 这个路径不要有中文&#xff0c;因为git …

Windows 下部署 SUNA 项目:虚拟环境尝试与最终方案

#工作记录 #回顾总结 本文记录了在 Windows 系统上&#xff0c;通过 PyCharm 图形界面&#xff08;尽量减少命令行操作&#xff09;部署 SUNA 项目时&#xff0c;针对不同虚拟环境方案的尝试过程、遇到的问题以及最终选择的可行方案&#xff0c;并补充了整体部署思路与推荐。…

无向图的点、边双连通分量

文章目录 点双连通分量边双连通分量 有向图的强连通分量&#xff1a;寒假学习笔记【匠心制作&#xff0c;图文并茂】——1.20拓扑、强连通分量、缩点 点双连通分量 在这之前&#xff0c;先让我们了解几个概念。 割点&#xff1a;删除一个点和其连出的边后&#xff0c;原图会…

第六十二节:深度学习-加载 TensorFlow/PyTorch/Caffe 模型

在计算机视觉领域,OpenCV的DNN(深度神经网络)模块正逐渐成为轻量级模型部署的利器。本文将深入探讨如何利用OpenCV加载和运行三大主流框架(TensorFlow、PyTorch、Caffe)训练的模型,并提供完整的代码实现和优化技巧。 一、OpenCV DNN模块的核心优势 OpenCV的DNN模块自3.3…

Spring @Autowired自动装配的实现机制

Spring Autowired自动装配的实现机制 Autowired 注解实现原理详解一、Autowired 注解定义二、Qualifier 注解辅助指定 Bean 名称三、BeanFactory&#xff1a;按类型获取 Bean四、注入逻辑实现五、小结 源码见&#xff1a;mini-spring Autowired 注解实现原理详解 Autowired 的…

胜牌™全球成为2026年FIFA世界杯™官方赞助商

胜牌全球将首次与国际足联&#xff08;FIFA&#xff09;旗舰赛事建立合作关系。 此次赞助恰逢美国首个润滑油品牌即将迎来160周年之际&#xff0c;其国际扩张步伐正在加快。 在这项全球顶级赛事筹备期间&#xff0c;胜牌全球将通过各种富有创意的零售和体验活动与球迷互动。 …

YOLOV7改进之融合深浅下采样模块(DSD Module)和轻量特征融合模块(LFI Module)

目录 一、研究背景​ 二. 核心创新点​ ​2.1 避免高MAC操作​ ​2.2 DSDM-LFIM主干网络​ 2.3 P2小目标检测分支​ ​3. 代码复现指南​ 环境配置 关键修改点 ​4. 实验结果对比​ 4.1 VisDrone数据集性能 4.2 边缘设备部署 4.3 检测效果可视化 ​5. 应用场景​ …

【C/C++】chrono简单使用场景

chrono使用场景举例 1 输出格式化字符串 示例代码 auto now std::chrono::system_clock::now(); auto t std::chrono::system_clock::to_time_t(now); auto ms std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;std::ostrin…

Med-R1论文阅读理解-1

论文总结&#xff1a;Med-R1: Reinforcement Learning for Generalizable Medical Reasoning in Vision-Language Models 论文写了什么&#xff1f; 本文提出了一种名为 Med-R1 的新框架&#xff0c;旨在通过强化学习&#xff08;Reinforcement Learning, RL&#xff09;提升…

京东热点缓存探测系统JDhotkey架构剖析

热点探测使用场景 MySQL 中被频繁访问的数据 &#xff0c;如热门商品的主键 IdRedis 缓存中被密集访问的 Key&#xff0c;如热门商品的详情需要 get goods$Id恶意攻击或机器人爬虫的请求信息&#xff0c;如特定标识的 userId、机器 IP频繁被访问的接口地址&#xff0c;如获取用…

MCU_IO驱动LED

注意事项&#xff1a; 1、亮度要求较高的情况下&#xff0c;不能由IO直接驱动LED MCU_IO引脚输出的电压和电流较弱&#xff0c;如果对光的亮度有要求的话&#xff0c;需要使用三极管来驱动。 MCU_IO的电压一般为3.3V或者5V&#xff0c;输出电流一般10mA-25mA。 2、不同颜色…

MyBatis 深度解析:高效 Java 持久层框架实践指南(基于 3.5.10)

一、MyBatis 核心架构与设计哲学 MyBatis 作为半自动 ORM 框架&#xff0c;核心设计目标是在灵活性与开发效率之间取得平衡。与 Hibernate 等全自动 ORM 框架不同&#xff0c;MyBatis 允许开发者完全控制 SQL 编写&#xff0c;同时通过映射机制减少重复代码&#xff0c;特别适…

二叉树(二)

98.验证二叉树 中序遍历二叉树&#xff0c;每次遍历存下当前节点的值&#xff0c;遍历到下一个节点比较&#xff0c;根据二叉搜索树的特性&#xff0c;左<中<右有&#xff1a; 如果当前值小于或等于上一个的值&#xff0c;说明不是二叉搜索树 如果当前值大于上一个节点…

解决Vue3+uni-app导航栏高亮自动同步方案

路由跳转自动识别导航高亮实现方法 以下代码使用wd-tabbar组件实现路由跳转时自动同步导航栏高亮状态&#xff0c;适用于所有的Vue3uni-app项目。 请根据自身使用框架类型完成&#xff0c;也可根据我使用的UI组件进行完成地址如下&#xff1a; Tabbar 标签栏 | Wot UI &#…