You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 00:07:55