MultiMesh
Один Mesh с массивом transform, цвета и custom-данных для множества экземпляров.
MultiMesh — ресурс массового инстансинга, не Entity и не коллекция отдельных MeshInstance3D. Все экземпляры используют общий Mesh. Для отображения назначьте ресурс MultiMeshInstance3D.Multimesh или MultiMeshInstance2D.Multimesh. Каждый элемент — индекс записи данных, а не отдельная Entity с собственным скриптом, коллизией и skeleton.
using var geometry = new BoxMesh();
using var batch = new MultiMesh();
batch.TransformFormat = MultiMesh.TransformFormatEnum.Transform3D;
batch.Mesh = geometry;
batch.InstanceCount = 2;
batch.SetInstanceTransform(0, Transform3D.Identity);
batch.SetInstanceTransform(1,
new Transform3D(Basis.Identity, new Vector3(3, 0, 0)));
batch.VisibleInstanceCount = -1;Пример настраивает ресурс, не добавляет видимый объект. При назначении потребителю сохраняйте batch и geometry живыми на весь срок использования; using здесь заканчивает проверку настройки. Формат по умолчанию 2D, поэтому для 3D сначала установите TransformFormat. UseColors и UseCustomData тоже задавайте до InstanceCount. Смена формата/флагов при положительном количестве отклоняется. Для перенастройки сохраните свои данные, установите InstanceCount = 0, задайте формат и заново выделите/заполните записи.
InstanceCount выделяет ёмкость, VisibleInstanceCount выбирает видимый префикс: -1 — все, 0 — ни одного, N — первые N. Это не список произвольных видимых индексов. Ограничение видимости не уменьшает буфер. После изменения ёмкости выставляйте допустимый visible count заново и не рассчитывайте на сохранение старых записей после перераспределения. Инициализируйте все отображаемые transforms явно.
SetInstanceTransform принимает локальный Transform3D относительно потребителя; вариант 2D требует Transform2D и 2D-формата. UseColors разрешает дополнительный цвет, но материал должен его использовать. UseCustomData разрешает четыре float в Color-контейнере для INSTANCE_CUSTOM шейдера: это не обязательный цвет и не автоматическая игровая логика. Цвет/данные не дают каждому экземпляру отдельный Material.
Для полной загрузки используйте Buffer/SetBuffer. Это float[], не byte[] и не сериализованный массив Transform3D. Длина строго InstanceCount × stride. База stride: 12 float для 3D или 8 для 2D; добавьте 4 при UseColors и ещё 4 при UseCustomData. 3D-запись содержит три строки (basis row xyz, origin component): translation лежит в 3,7,11. Для 2D две строки (xx,yx,0,origin.x) и (xy,yy,0,origin.y). Следом идут color RGBA и custom RGBA при включённых каналах. Не копируйте Transform3D памятью: порядок basis отличается. GetBuffer возвращает managed-копию; после правки загрузите её заново. При InstanceCount = 0 SetBuffer ничего не делает.
CustomAabb охватывает всю группу в локальных координатах, включая перемещения/деформацию и размер исходного Mesh. Слишком маленькая граница вызывает исчезновение объектов; слишком большая мешает отсечению. Большой мир разбивайте на пространственные группы: MultiMesh не заменяет streaming и отдельное отсечение каждой Entity. Число draw calls зависит от материалов, поверхностей и render passes; обещать всегда один вызов или фиксированное ускорение нельзя. Blend shapes общего Mesh для MultiMesh не поддерживаются как отдельная анимация экземпляров.
PhysicsInterpolationQuality выбирает способ уже настроенной интерполяции, не включает её и не меняет physics tick rate. SetBufferInterpolated получает current и previous одного layout/длины; вызывайте в соответствующем physics-процессе при включённой интерполяции потребителя. После телепорта задайте новый transform и сбросьте историю нужного индекса через ResetInstancePhysicsInterpolation; вариант ResetInstancesPhysicsInterpolation сбрасывает всю группу. Сам reset не перемещает объект.
ColorArray, CustomDataArray, TransformArray и Transform2DArray помечены SDK Obsolete: они проходят по элементам. Для нового кода используйте per-instance методы или Buffer. Не используйте Changed как универсальный сигнал обновления: 2D-transform и CustomAabb отправляют его, 3D-transform, цвет, custom data и bulk upload — нет.
21 Windows headless-проверка подтвердила настройки ресурса и копирование общего CPU-буфера. Dummy backend не сохраняет отдельные transform/color/custom-записи, возвращает default bounds и не имеет интерполятора. Поэтому успешный headless-вызов не подтверждает положения объектов, видимый цвет, интерполяцию, culling, GPU-рендер или ускорение; эти свойства требуют отдельной проверки с renderer.
Объявления сверены с C# SDK 1.0.0. Раскройте имя, чтобы увидеть сигнатуры и описание.
Конструкторы1
MultiMeshКонструктор
public MultiMesh();Создаёт пустой собственный ресурс: формат 2D, count 0, visible -1, цвета/custom выключены, interpolation quality Fast. Для показа нужен отдельный потребитель.
Свойства13
BufferСвойство
public float[] Buffer { get; set; }Полный float-буфер InstanceCount × stride. Stride = (3D:12 / 2D:8) + colors:4 + custom:4. Getter даёт копию, setter загружает весь буфер. Не byte-массив и не live-view.
ColorArrayСвойство · Устарело
public Color[] ColorArray { get; set; }SDK Obsolete: legacy-массив цветов, обращающийся к экземплярам поэлементно. Для нового кода используйте соответствующие Set/GetInstance методы либо Buffer; не live-view.
CustomAabbСвойство
public Aabb CustomAabb { get; set; }Граница всей группы в локальных координатах, включая полный размер Mesh и движения. Нулевая Aabb снимает пользовательский override для renderer. Setter отправляет Changed; свойство не создаёт коллизию.
CustomDataArrayСвойство · Устарело
public Color[] CustomDataArray { get; set; }SDK Obsolete: legacy-массив custom-данных, обращающийся к экземплярам поэлементно. Для нового кода используйте соответствующие Set/GetInstance методы либо Buffer; не live-view.
InstanceCountСвойство
public int InstanceCount { get; set; }Неотрицательная ёмкость записей. Установка вызывает выделение backend-данных; не рассчитывайте на сохранение записей при изменении ёмкости. Формат/flags задайте заранее.
MeshСвойство
public Mesh Mesh { get; set; }Общий Mesh всех записей либо null. Материалы берутся из общего Mesh/потребителя; отдельного Material для каждой записи это свойство не создаёт.
PhysicsInterpolationQualityСвойство
public MultiMesh.PhysicsInterpolationQualityEnum PhysicsInterpolationQuality { get; set; }Fast по умолчанию или High для метода интерполяции. Не включает интерполяцию, не увеличивает частоту physics и не исправляет неинициализированные transforms.
Transform2DArrayСвойство · Устарело
public Vector2[] Transform2DArray { get; set; }SDK Obsolete: legacy-массив 2D transforms, обращающийся к экземплярам поэлементно. Для нового кода используйте соответствующие Set/GetInstance методы либо Buffer; не live-view.
TransformArrayСвойство · Устарело
public Vector3[] TransformArray { get; set; }SDK Obsolete: legacy-массив 3D transforms, обращающийся к экземплярам поэлементно. Для нового кода используйте соответствующие Set/GetInstance методы либо Buffer; не live-view.
TransformFormatСвойство
public MultiMesh.TransformFormatEnum TransformFormat { get; set; }Формат transforms, по умолчанию 2D. Меняется только при нулевой ёмкости; для 3D выберите Transform3D до InstanceCount.
UseColorsСвойство
public bool UseColors { get; set; }Дополнительные 4 float цвета на запись, выключены по умолчанию. Настраивается только при count 0; видимое использование зависит от материала.
UseCustomDataСвойство
public bool UseCustomData { get; set; }Дополнительные 4 float custom на запись, выключены по умолчанию. Настраивается при count 0; значения читает shader.
VisibleInstanceCountСвойство
public int VisibleInstanceCount { get; set; }Количество первых записей для показа, -1 все. Не размер выделенного массива и не автоматическое индивидуальное отсечение.
Методы32
GetAabbAabb
public Aabb GetAabb();Запрашивает границы группы у renderer. Это не bounds одного экземпляра и не CustomAabb getter. Dummy backend возвращает default, поэтому headless не подтверждает bounds/culling.
AabbRenderer Aabb группы; default в dummy backend.
GetBufferfloat[]
public float[] GetBuffer();Получает managed-копию общего float-буфера. Правки результата не применяются без новой загрузки; renderer readback может быть затратным.
float[]Новая managed-копия float-буфера; чтение не подтверждает visible GPU output.
GetCustomAabbAabb
public Aabb GetCustomAabb();Читает сохранённый пользовательский override, не вычисленный bounds группы.
AabbСохранённый пользовательский Aabb, default до назначения.
GetInstanceColorColor
public Color GetInstanceColor(int instance);Читает color записи при UseColors = true и допустимом индексе. Dummy getter возвращает default, не проверенный цвет GPU.
| Имя | Тип | По умолчанию |
|---|---|---|
instance | int | — |
instanceИндекс записи от 0 до InstanceCount-1, не Entity ID и не номер видимой поверхности.
ColorColor записи; default при диагностике/в dummy. Не универсальный invalid-index маркер.
GetInstanceCountint
public int GetInstanceCount();Читает выделенное количество записей, также InstanceCount. Не число видимых объектов.
intНеотрицательная выделенная ёмкость.
GetInstanceCustomDataColor
public Color GetInstanceCustomData(int instance);Читает четыре custom float через Color при UseCustomData = true. Семантику задаёт shader; dummy возвращает default.
| Имя | Тип | По умолчанию |
|---|---|---|
instance | int | — |
instanceИндекс записи от 0 до InstanceCount-1, не Entity ID и не номер видимой поверхности.
ColorЧетыре float через Color; dummy возвращает default.
GetInstanceTransformTransform3D
public Transform3D GetInstanceTransform(int instance);Читает локальный Transform3D записи 3D-формата, не global transform Entity. Dummy возвращает identity независимо от scalar setter.
| Имя | Тип | По умолчанию |
|---|---|---|
instance | int | — |
instanceИндекс записи от 0 до InstanceCount-1, не Entity ID и не номер видимой поверхности.
Transform3DЛокальный Transform3D; identity в dummy/при диагностике.
GetInstanceTransform2DTransform2D
public Transform2D GetInstanceTransform2D(int instance);Читает локальный Transform2D записи 2D-формата. Для 3D используйте другой метод; dummy возвращает identity.
| Имя | Тип | По умолчанию |
|---|---|---|
instance | int | — |
instanceИндекс записи от 0 до InstanceCount-1, не Entity ID и не номер видимой поверхности.
Transform2DЛокальный Transform2D; identity в dummy/при диагностике.
GetMeshMesh
public Mesh GetMesh();Возвращает общую ссылку исходного Mesh либо null, не MeshInstance3D и не копию геометрии.
MeshОбщий Mesh либо null; не отдельная копия для раннего Dispose.
GetPhysicsInterpolationQualityMultiMesh.PhysicsInterpolationQualityEnum
public MultiMesh.PhysicsInterpolationQualityEnum GetPhysicsInterpolationQuality();Читает выбранное Fast/High; не показывает факт включения интерполяции или текущий physics FPS.
MultiMesh.PhysicsInterpolationQualityEnumСохранённый enum Fast/High.
GetTransformFormatMultiMesh.TransformFormatEnum
public MultiMesh.TransformFormatEnum GetTransformFormat();Читает формат 2D/3D, установленный до выделения записей.
MultiMesh.TransformFormatEnumСохранённый enum 2D/3D.
GetVisibleInstanceCountint
public int GetVisibleInstanceCount();Читает ограничение префикса: -1 все, 0 ни одного, N первые N. Это настройка, не подсчёт реально видимых пикселей.
intНастройка префикса, -1 для всех.
IsUsingColorsbool
public bool IsUsingColors();Читает факт выделения color-канала, не настройку материала на использование цвета.
booltrue при включённом color-канале.
IsUsingCustomDatabool
public bool IsUsingCustomData();Читает факт включения custom-канала; не означает наличие shader-логики для этих значений.
booltrue при включённом custom-канале.
ResetInstancePhysicsInterpolationvoid
public void ResetInstancePhysicsInterpolation(int instance);При активной интерполяции копирует current-запись в previous для одного индекса. Вызывайте после записи позиции телепорта, чтобы не интерполировать от старого места. Dummy не имеет интерполятора.
| Имя | Тип | По умолчанию |
|---|---|---|
instance | int | — |
instanceИндекс записи от 0 до InstanceCount-1, не Entity ID и не номер видимой поверхности.
ResetInstancesPhysicsInterpolationvoid
public void ResetInstancesPhysicsInterpolation();Сбрасывает историю всех записей к current. Не перемещает объекты и не включает интерполяцию; действует при наличии interpolator.
SetBuffer2 перегрузки
public void SetBuffer(ReadOnlySpan<float> buffer);Загружает полный float-буфер точной длины. Array/span имеют один layout. При count 0 вызов игнорируется; при положительном count неверная длина отклоняется. Changed не отправляется.
| Имя | Тип | По умолчанию |
|---|---|---|
buffer | ReadOnlySpan<float> | — |
bufferПолный float[]/span точного stride × InstanceCount; row layout описан во введении.
public void SetBuffer(float[] buffer);Загружает полный float-буфер точной длины. Array/span имеют один layout. При count 0 вызов игнорируется; при положительном count неверная длина отклоняется. Changed не отправляется.
| Имя | Тип | По умолчанию |
|---|---|---|
buffer | float[] | — |
bufferПолный float[]/span точного stride × InstanceCount; row layout описан во введении.
SetBufferInterpolated2 перегрузки
public void SetBufferInterpolated(ReadOnlySpan<float> bufferCurr, ReadOnlySpan<float> bufferPrev);Передаёт current и previous одинакового layout для physics interpolation, не два render draw calls. Требуется renderer interpolator; dummy ничего не делает. Метод не заменяет включение интерполяции у потребителя.
| Имя | Тип | По умолчанию |
|---|---|---|
bufferCurr | ReadOnlySpan<float> | — |
bufferPrev | ReadOnlySpan<float> | — |
bufferCurrCurrent physics buffer полного размера с тем же layout/count, что previous.
bufferPrevPrevious physics buffer полного размера; не velocity/delta и не другой набор экземпляров.
public void SetBufferInterpolated(float[] bufferCurr, float[] bufferPrev);Передаёт current и previous одинакового layout для physics interpolation, не два render draw calls. Требуется renderer interpolator; dummy ничего не делает. Метод не заменяет включение интерполяции у потребителя.
| Имя | Тип | По умолчанию |
|---|---|---|
bufferCurr | float[] | — |
bufferPrev | float[] | — |
bufferCurrCurrent physics buffer полного размера с тем же layout/count, что previous.
bufferPrevPrevious physics buffer полного размера; не velocity/delta и не другой набор экземпляров.
SetCustomAabbvoid
public void SetCustomAabb(Aabb aabb);Устанавливает общий CustomAabb и отправляет Changed. Охватите все локальные экземпляры и shader-деформацию; world-space bounds без преобразования здесь неверны.
| Имя | Тип | По умолчанию |
|---|---|---|
aabb | Aabb | — |
aabbЛокальные bounds всей группы; нулевая Aabb отключает renderer override.
SetInstanceColorvoid
public void SetInstanceColor(int instance, Color color);Записывает color одного индекса при UseColors = true. Материал должен использовать instance/vertex color; Changed не отправляется. Dummy запись не сохраняет.
| Имя | Тип | По умолчанию |
|---|---|---|
instance | int | — |
color | Color | — |
instanceИндекс записи от 0 до InstanceCount-1, не Entity ID и не номер видимой поверхности.
colorInstance color, используемый только при включённом канале и подходящем материале.
SetInstanceCountvoid
public void SetInstanceCount(int count);Выделяет неотрицательное число записей в заранее выбранном формате. После изменения заново заполните нужные данные и проверьте VisibleInstanceCount.
| Имя | Тип | По умолчанию |
|---|---|---|
count | int | — |
countНеотрицательное количество записей для выделения.
SetInstanceCustomDatavoid
public void SetInstanceCustomData(int instance, Color customData);Записывает четыре custom float одного индекса при включённом канале. Color — контейнер данных для shader INSTANCE_CUSTOM; Changed не отправляется.
| Имя | Тип | По умолчанию |
|---|---|---|
instance | int | — |
customData | Color | — |
instanceИндекс записи от 0 до InstanceCount-1, не Entity ID и не номер видимой поверхности.
customDataЧетыре конечных float в RGBA полях Color; смысл задаёт shader, не обязательно цвет.
SetInstanceTransformvoid
public void SetInstanceTransform(int instance, Transform3D transform);Записывает локальный Transform3D для 3D-формата и допустимого индекса. Не создаёт Entity/коллизию. Changed не отправляется; dummy не сохраняет запись.
| Имя | Тип | По умолчанию |
|---|---|---|
instance | int | — |
transform | Transform3D | — |
instanceИндекс записи от 0 до InstanceCount-1, не Entity ID и не номер видимой поверхности.
transformЛокальный Transform3D с finite-компонентами для 3D layout.
SetInstanceTransform2Dvoid
public void SetInstanceTransform2D(int instance, Transform2D transform);Записывает локальный Transform2D для 2D-формата. В отличие от 3D setter отправляет Changed. Dummy уведомляет, но transform не сохраняет.
| Имя | Тип | По умолчанию |
|---|---|---|
instance | int | — |
transform | Transform2D | — |
instanceИндекс записи от 0 до InstanceCount-1, не Entity ID и не номер видимой поверхности.
transformЛокальный Transform2D с finite-компонентами для 2D layout.
SetMeshvoid
public void SetMesh(Mesh mesh);Назначает общий Mesh либо null без копирования геометрии. Сам ресурс MultiMesh ещё нужно назначить отображающему потребителю.
| Имя | Тип | По умолчанию |
|---|---|---|
mesh | Mesh | — |
meshОбщий Mesh либо null. Сохраняйте ресурс живым, пока группа его использует.
SetPhysicsInterpolationQualityvoid
public void SetPhysicsInterpolationQuality(MultiMesh.PhysicsInterpolationQualityEnum quality);Выбирает Fast/High для интерполяции. Setter не включает её и не подтверждает гладкость результата; headless проверяет только сохранённое значение.
| Имя | Тип | По умолчанию |
|---|---|---|
quality | MultiMesh.PhysicsInterpolationQualityEnum | — |
qualityFast или High, без автоматического включения интерполяции.
SetTransformFormatvoid
public void SetTransformFormat(MultiMesh.TransformFormatEnum format);Задаёт 2D/3D только при InstanceCount = 0. Повторная запись даже того же значения при положительном count отклоняется.
| Имя | Тип | По умолчанию |
|---|---|---|
format | MultiMesh.TransformFormatEnum | — |
formatTransform2D или Transform3D при InstanceCount = 0.
SetUseColorsvoid
public void SetUseColors(bool enable);Включает color-канал только при InstanceCount = 0. Материал настраивается отдельно.
| Имя | Тип | По умолчанию |
|---|---|---|
enable | bool | — |
enableВключить/выключить соответствующий канал при InstanceCount = 0.
SetUseCustomDatavoid
public void SetUseCustomData(bool enable);Включает четыре custom float на запись только при InstanceCount = 0. Shader использует их отдельно.
| Имя | Тип | По умолчанию |
|---|---|---|
enable | bool | — |
enableВключить/выключить соответствующий канал при InstanceCount = 0.
SetVisibleInstanceCountvoid
public void SetVisibleInstanceCount(int count);Задаёт видимый префикс: -1 либо 0…InstanceCount. Не меняет ёмкость и не переставляет записи.
| Имя | Тип | По умолчанию |
|---|---|---|
count | int | — |
count-1 для всех либо 0…InstanceCount для видимого префикса.
MultiMesh.PhysicsInterpolationQualityEnum
| Значение | Описание |
|---|---|
Fast = 0 | Всегда выполняйте интерполяцию с использованием Basis lerping, что в некоторых ситуациях может приводить к появлению артефактов деформации. |
High = 1 | По возможности пытайтесь выполнить интерполяцию с использованием Basis slerping (сферической линейной интерполяции), в противном случае прибегните к lerping. |
MultiMesh.TransformFormatEnum
| Значение | Описание |
|---|---|
Transform2D = 0 | Используйте это при использовании 2D-преобразований. |
Transform3D = 1 | Используйте это при использовании 3D-преобразований. |