Minden egyes Collider, Collider2D és Renderer komponensnek lekérdezhető hogy milyen térrészen belül helyezkedik el. Ezen térrész egy olyan téglatest, aminek minden éle párhuzamos a globális koordinátarendszer egyik tengelyével.
A Bound típus
Ezen befoglaló téglatestet egy Bounds
típus írja le. Egy Bound
példánynak van egy Vector3
középpontja (.center
) és egy kiterjedése a tér három dimenziójában (.size
), ami szintén Vector3
típusú.
void OnDrawGizmos()
{
Renderer r = GetComponent<Renderer>();
Collider2D c2 = GetComponent<Collider2D>();
Collider c3 = GetComponent<Collider>();
Bounds bounds; // Téglatest térrészt leíró típus
if (r != null)
bounds = r.bounds;
else if (c2 != null)
bounds = c2.bounds;
else if (c3 != null)
bounds = c3.bounds;
else
return;
Gizmos.color = Color.red;
Gizmos.DrawWireCube(bounds.center, bounds.size); // A befoglaló téglatest kirajzolása
}
Nézzük meg mit rajzol ki a fenti metódus!
Ezen befoglaló téglatestet használja fel a fizikai és a render-motor sok-sok optimalizálásra. Például azz Occlusion Culling folyamata eldob minden olyan objektumot a renderelésnél, aminek a befoglaló doboza nem érintkezik a kamera terével és ezt jóval gyorsabb kiszámolni, mint arra tesztelni, hogy a megjelenített mesh pontosan benne van-e a látótérben.
Pár hasznos művelet Bound-okkal:
Vector3 c = bounds.center; // Középpont
Vector3 s = bounds.size; // Méret
Vector3 e = bounds.extents; // Félméret (tengeleynként)
Vector3 min = bounds.min; // Bal, alsó, hátsó sarok
Vector3 max = bounds.max; // Jobb, felső, elülső sarok
bool inside = bounds.Contains(p); // Bound-on belül van-e a pont?
Vector3 closest = bounds.ClosestPoint(p); // A legközelebbi pont a bound-on belül
bool intersect= bounds.IntersectRay(ray); // Metszi-e a bound a sugarat?
Saját magunk is létrehozhatunk egy Bound típust és használhatjuk bármire.
Például az alábbi kód egy beállítható [SerializeField] Bounds
térrészen belül készít akárhány másolatot egy prototípusként megadott objektumból.
using UnityEngine;
using Random = UnityEngine.Random;
public class BoundInstantiater: MonoBehaviour
{
[SerializeField] Bounds bounds;
[SerializeField, Min(0)] float count = 5000;
[SerializeField] GameObject prototype;
void Start()
{
for (int i = 0; i < count; i++)
InstantiateNew();
}
void InstantiateNew()
{
float randomX = Random.Range(bounds.min.x, bounds.max.x);
float randomY = Random.Range(bounds.min.y, bounds.max.y);
float randomZ = Random.Range(bounds.min.z, bounds.max.z);
Vector3 nextPosition = new Vector3(randomX, randomY, randomZ);
GameObject newGO = Instantiate(prototype, transform);
newGO.transform.position = nextPosition;
}
void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawWireCube(bounds.center, bounds.size);
}
}
Ebből látható, hogy valójában a Bound típusú objektum az (egyes tengelyenkénti) fél-méretet (.extent
) tárolja el, de lekérhető is a teljes méret (.size
) is egy Property-n keresztül.
Hogy ez mire volt jó?… Hát azt én sem tudom. 🤷 Csak érzékeltetni akartam a Bounds
típus működését.
A Rect típus
A Rect
, azaz Rectangle/Téglalap egy típus, ami tekinthető a Bound megfelelőjének a 2D síkon, mivel a Rect
objektum pozíciója és mérete is egyaránt Vector2
típusú. A Rect
főleg a UI felületek kirajzolásához hasznos. Lásd később: Unity UI (Félkész…)