Как оптимизировать физику на 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);
}
}
Приложение однопоточное.
Никогда, нет, не так. НИКОГДА не изменяйте меш коллайдера в рантайме. Физический движок работает не так, как кажется со стороны. Чтобы меш действительно правильно и, главное, быстро просчитывал столкновения, движок производит некоторые достаточно дорогие манипуляции, которые происходят на этапе инициализации компонента MeshCollider
.
Решение? Не делать то, что вы пытаетесь сделать.
Зачем каждый фрейм уничтожать компоненты и тут же создавать их заново?
Mesh myMesh = this.GetComponent<MeshFilter>().mesh; // копия меши
DestroyImmediate(this.GetComponent<MeshCollider>()); // уничтожения оригинального коллайдера
gameObject.AddComponent<MeshCollider>(); // добавление нового коллайдера
GetComponent<MeshCollider>().sharedMesh = myMesh; // обновление нового коллайдера
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;
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Этот метод не будет работать, но как можно реализовать подобную логику?
Решил попробовать написать своего первого бота (надеюсь не последнего) для Vk, используя VKNet и на языке C#Найдя несколько гайдов, я приступил...
Хотите улучшить этот вопрос? Переформулируйте вопрос так, чтобы на него можно было дать ответ, основанный на фактах и цитатах
Почему у меня высвечивается ошибка с индексом: Array index is out of range