Низкий FPS из за физики | Процедурный MeshColider

152
23 декабря 2021, 17:50

Как оптимизировать физику на Unity? Через Profiler на Unity я посмотрел что больше всего нагружает физика, а физичный объект у меня только вода. У меня есть пластины с динамическим мешом который изменяется с помощью perlinNoise каждый кадр и динамическим меш-колайдером который меняется с помощью этого куска:

Mesh myMesh = this.GetComponent<MeshFilter>().mesh;
DestroyImmediate(this.GetComponent<MeshCollider>());
gameObject.AddComponent<MeshCollider>();
GetComponent<MeshCollider>().sharedMesh = myMesh;

Edit: Вот сам код который генерирует воду:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WaterNoise : MonoBehaviour
{
    public float power = 3;
    public float scale = 1;
    public float timeScale = 1;
    float offsetX;
    float offsetY;
    MeshFilter mf;
    private void Start()
    {
        mf = GetComponent<MeshFilter>();
        GenNoise();
    }
    private void FixedUpdate()
    {
        GenNoise();
        offsetX += Time.deltaTime * timeScale;
        offsetY += Time.deltaTime * timeScale;
    }
    void GenNoise()
    {
        Vector3 myPos = transform.localPosition;
        Vector3[] vertices = mf.mesh.vertices;
        for(int i = 0; i < vertices.Length; i++)
        {
            vertices[i].y = CalculateHeight(vertices[i].x + myPos.x, vertices[i].z + myPos.z) * power;
        }
        Mesh myMesh = this.GetComponent<MeshFilter>().mesh;
        DestroyImmediate(this.GetComponent<MeshCollider>());
        gameObject.AddComponent<MeshCollider>();
        GetComponent<MeshCollider>().sharedMesh = myMesh;
        mf.mesh.vertices = vertices;
    }
    float CalculateHeight(float x, float y)
    {
        float xCoord = x * scale + offsetX;
        float yCoord = y * scale + offsetY;
        return Mathf.PerlinNoise(xCoord, yCoord);
    }
}

Приложение однопоточное.

Answer 1

Важно!

Никогда, нет, не так. НИКОГДА не изменяйте меш коллайдера в рантайме. Физический движок работает не так, как кажется со стороны. Чтобы меш действительно правильно и, главное, быстро просчитывал столкновения, движок производит некоторые достаточно дорогие манипуляции, которые происходят на этапе инициализации компонента MeshCollider.

Решение? Не делать то, что вы пытаетесь сделать.

  1. Зачем каждый фрейм уничтожать компоненты и тут же создавать их заново?

    Mesh myMesh = this.GetComponent<MeshFilter>().mesh;   // копия меши
    DestroyImmediate(this.GetComponent<MeshCollider>());  // уничтожения оригинального коллайдера
    gameObject.AddComponent<MeshCollider>();              // добавление нового коллайдера
    GetComponent<MeshCollider>().sharedMesh = myMesh;     // обновление нового коллайдера
    
  1. Mesh.vertices возвращает копию массива вершин

Returns a copy of the vertex positions or assigns a new vertex positions array.

Поскольку меш изменяет только этот скрипт, то можно просто закэшировать этот массив 1 раз и не вызывать каждый физический фрейм Mesh.vertices, GC скажет вам спасибо:

private Mesh _sharedMesh;
private Vector3[] _vertices;
private MeshCollider _meshCollider;
private void Awake()
{
    _sharedMesh = GetComponent<MeshFilter>().sharedMesh;
    _vertices = _sharedMesh.vertices;
    _meshCollider =  GetComponent<MeshCollider>();
}
private void FixedUpdate()
{
    // изменяем _vertices
    // изменяем полигональную сетку
    _sharedMesh.vertices = _vertices;
    _sharedMesh.RecalculateBounds();
    // отдаем эту сетку физическому движку
    // это побудит его заново пересчитать сетку для физических взаимодействий
    _meshCollider.sharedMesh = _sharedMesh;
}
READ ALSO
Передача в функцию параметра с неопределенным типом C#

Передача в функцию параметра с неопределенным типом C#

Этот метод не будет работать, но как можно реализовать подобную логику?

157
Некорректная работа VK бота

Некорректная работа VK бота

Решил попробовать написать своего первого бота (надеюсь не последнего) для Vk, используя VKNet и на языке C#Найдя несколько гайдов, я приступил...

81
Где взять знания? [закрыт]

Где взять знания? [закрыт]

Хотите улучшить этот вопрос? Переформулируйте вопрос так, чтобы на него можно было дать ответ, основанный на фактах и цитатах

269
Проблема с индексами элементов массива

Проблема с индексами элементов массива

Почему у меня высвечивается ошибка с индексом: Array index is out of range

195