Misc Utilities
BakeAndAttachCollider
BakeAndAttachColliderpublic void BakeAndAttachCollider(bool convex)
{
if (!m_SkinnedMeshRenderer) return;
Mesh baked = new Mesh { name = "Baked_SkinnedMesh", hideFlags = HideFlags.HideAndDontSave };
m_SkinnedMeshRenderer.BakeMesh(baked, true);
if (!m_MeshCollider) CacheComponents();
m_MeshCollider.sharedMesh = baked;
m_MeshCollider.convex = convex;
}Purpose: Bake a SkinnedMeshRenderer to a static Mesh and assign it to the MeshCollider.
Parameters: convex — whether to set MeshCollider.convex.
Returns: void
Notes: Useful for dynamic characters when you need a quick collision shell.
SetMaskBox
SetMaskBoxpublic void SetMaskBox(Vector3 centerWs, Vector2 sizeWs)
{
center = transform.InverseTransformPoint(centerWs);
size = sizeWs;
ForceRebuild(true);
}Purpose: Update center and size of the mask in one call, then rebuild.
Parameters: centerWs (world), sizeWs
Returns: void
GetProjectionBounds
GetProjectionBoundspublic Bounds GetProjectionBounds()
=> new(transform.TransformPoint(center),
Vector3.Scale(new Vector3(size.x, size.y, maxDistance), transform.lossyScale));Purpose: Get current projection Bounds in world space.
Returns: Bounds
GetSubdivisionSettings
GetSubdivisionSettingspublic Vector2Int GetSubdivisionSettings()
=> new(meshSubdivisions, colliderSubdivisions);Purpose: Return current (mesh, collider) subdivision counts.
Returns: Vector2Int
EstimateMemoryFootprint
EstimateMemoryFootprintpublic int EstimateMemoryFootprint(int overrideSubDiv = -1)
{
int sub = overrideSubDiv > 2 ? overrideSubDiv : meshSubdivisions;
int verts = (sub + 1) * (sub + 1);
int tris = sub * sub * 2;
const int vertSize = 12 * 2 + 8; // pos+normal+uv
return (verts * vertSize + tris * 4 * 3) / 1024; // KB
}Purpose: Rough memory estimate (KB) for a given subdivision level.
Parameters: overrideSubDiv — if <= 2, uses current meshSubdivisions.
Returns: int (KB)
Notes: Helpful when building quality profiles.
PredictRebuildTimeMS
PredictRebuildTimeMSpublic float PredictRebuildTimeMS(int futureSubDiv)
{
if (m_LastStats.TrianglesVisual == 0) return 0f;
float ratio = Mathf.Pow((float)futureSubDiv / meshSubdivisions, 2f);
return m_LastRebuildTimeMS * ratio;
}Purpose: Predict rebuild time (ms) for a future subdivision, based on last measurement.
Parameters: futureSubDiv
Returns: float (ms)
Notes: Assumes triangle count ~ subdiv².
SetAdaptiveSubdivisions
SetAdaptiveSubdivisionspublic void SetAdaptiveSubdivisions(float targetAvgTriAreaCm2)
{
if (targetAvgTriAreaCm2 <= 0) return;
float current = GetAverageTriArea(false);
if (current <= 0) return;
float ratio = current / targetAvgTriAreaCm2;
int newSub = Mathf.Clamp(
Mathf.RoundToInt(meshSubdivisions * Mathf.Sqrt(ratio)), 3, 64);
if (newSub == meshSubdivisions) return;
meshSubdivisions = newSub;
colliderSubdivisions = Mathf.Clamp(newSub / 4, 3, 64);
ForceRebuild(true);
}Purpose: Automatically tune subdivisions to reach a target average triangle area (cm²).
Parameters: targetAvgTriAreaCm2
Returns: void
Notes: Collider subdivisions are auto-derived as ~¼ of visual for efficiency.
Last updated