如何优化Unity车辆变形C#代码,避免因顶点过多导致游戏崩溃?
优化Unity顶点变形代码以避免高顶点模型崩溃
原代码核心问题分析
你的代码在碰撞时会遍历所有顶点,当模型顶点数过万时,单次碰撞的循环计算量会直接拉满CPU,导致游戏崩溃。另外还有几个隐性性能问题:
- 用
Vector3.Distance计算距离,每次都会触发开根号运算,比平方距离比较慢3-5倍 - 碰撞后立刻调用
UpdateMeshVerticies,但协程还没完成顶点修改,数据同步错误 - 每次碰撞都更新
MeshCollider,高顶点Mesh的碰撞体重建是性能杀手
针对性优化方案
- 只处理碰撞范围内的顶点:不用遍历全部顶点,先把碰撞点转换为模型空间,然后计算顶点到碰撞点的平方距离,只处理小于
deformRadius²的顶点,大幅减少循环次数 - 替换距离计算方式:用
Vector3.SqrMagnitude代替Vector3.Distance,避免开根号的性能损耗 - 调整Mesh更新时机:把Mesh更新逻辑放到协程内,确保顶点修改完成后再更新Mesh和碰撞体,避免数据不同步
- MeshCollider优化(关键):高顶点模型用
MeshCollider本身就非常耗性能,建议改用Compound Collider(多个Box/Capsule/Sphere Collider组合模拟车辆碰撞),完全放弃MeshCollider;如果必须用MeshCollider,只在变形完成后间隔一段时间更新
修改后的代码
using System.Collections; using UnityEngine; public class Deform : MonoBehaviour { [Range(0, 10)] public float deformRadius = 0.2f; [Range(0, 10)] public float maxDeform = 0.1f; [Range(0, 1)] public float damageFalloff = 1; [Range(0, 10)] public float damageMultiplier = 1; [Range(0, 100000)] public float minDamage = 1; private MeshFilter filter; private Rigidbody physics; private MeshCollider coll; private Vector3[] startingVertices; private Vector3[] meshVertices; private float deformRadiusSqr; // 预计算半径平方,避免重复乘法 void Start() { filter = GetComponent<MeshFilter>(); physics = GetComponent<Rigidbody>(); coll = GetComponent<MeshCollider>(); startingVertices = filter.mesh.vertices; meshVertices = filter.mesh.vertices; deformRadiusSqr = deformRadius * deformRadius; } void OnCollisionEnter(Collision collision) { float collisionPower = collision.impulse.magnitude; if (collisionPower <= minDamage) return; foreach (ContactPoint point in collision.contacts) { StartCoroutine(DeformAndUpdateMesh(point)); } } IEnumerator DeformAndUpdateMesh(ContactPoint point) { Vector3 localCollisionPoint = transform.InverseTransformPoint(point.point); for (int i = 0; i < meshVertices.Length; i++) { // 用平方距离判断,跳过超出变形范围的顶点 Vector3 vertexToCollision = meshVertices[i] - localCollisionPoint; float distanceSqr = vertexToCollision.sqrMagnitude; if (distanceSqr > deformRadiusSqr) continue; float distanceFromOriginal = Vector3.Distance(startingVertices[i], meshVertices[i]); if (distanceFromOriginal >= maxDeform) continue; // 计算衰减值,仅在需要时开根号 float distance = Mathf.Sqrt(distanceSqr); float falloff = 1 - (distance / deformRadius) * damageFalloff; // 修正变形方向:朝向碰撞点,避免原代码方向错误问题 Vector3 deformDir = vertexToCollision.normalized; float deformAmount = falloff * damageMultiplier; deformAmount = Mathf.Clamp(deformAmount, 0, maxDeform - distanceFromOriginal); meshVertices[i] -= deformDir * deformAmount; } // 顶点修改完成后统一更新Mesh filter.mesh.vertices = meshVertices; filter.mesh.RecalculateNormals(); // 可选,修复变形后的光照异常 // 仅在必要时更新MeshCollider,建议替换为Compound Collider if (coll != null) { coll.sharedMesh = filter.mesh; } yield return null; } }
额外性能提升建议
- 模型拆分:把车辆模型拆分为多个子物体(车身、车门、车轮等),每个子物体单独处理变形,减少单次处理的顶点数量
- Job System加速:把顶点计算放到后台线程,避免主线程卡顿,适合超大规模顶点模型
- 限制变形频率:添加冷却时间,短时间内多次碰撞只处理一次,避免重复计算
内容的提问来源于stack exchange,提问作者ZOMBYSPIDER
相关产品推荐
相关产品推荐

