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
繁體地址,請注明出處:http://hk.pswp.cn/diannao/85599.shtml
英文地址,請注明出處:http://en.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 &#…