Взаимодействие с объектами и компонентами игр Unity
Удаленная отрисовка Azure (ARR) оптимизирована для большого числа объектов (см. раздел Ограничения). Хотя на узле можно управлять большими и сложными иерархиями, их репликация в Unity на устройствах с низким энергопотреблением неосуществима.
Поэтому при загрузке модели на узел Удаленная отрисовка Azure отражает сведения о структуре модели на клиентском устройстве (что приведет к расходу сетевого трафика), но не реплицирует объекты и компоненты в Unity. Вместо этого вы должны запросить необходимые объекты и компоненты игры Unity вручную, чтобы избежать лишних издержек. Таким образом вы лучше контролируете производительность на стороне клиента.
Следовательно, интеграция Удаленной отрисовки Azure с Unity обеспечивает дополнительные функции для репликации структуры Удаленной отрисовки по требованию.
Загрузка модели в Unity
При загрузке модели вы получаете ссылку на корневой объект загруженной модели. Эта ссылка не является объектом игры Unity, но ее можно сделать таким объектом с помощью метода расширения Entity.GetOrCreateGameObject()
. Эта функция принимает аргумент типа UnityCreationMode
. При передаче CreateUnityComponents
вновь созданный объект игры Unity будет дополнительно заполнен компонентами прокси-сервера для всех компонентов Удаленной отрисовки, существующих на узле. Рекомендуется, однако, использовать DoNotCreateUnityComponents
, чтобы избежать лишних издержек.
Загрузка модели с сопрограммами Unity
IEnumerator LoadModelWithCoroutine(RenderingSession session)
{
float currentProgress = 0.0f;
var task = session.Connection.LoadModelFromSasAsync(new LoadModelFromSasOptions("builtin://Engine"),
(float progress) =>
{
currentProgress = progress;
});
while (!task.IsCompleted && !task.IsFaulted)
{
int percentage = (int)(currentProgress * 100.0f);
yield return null;
}
if (!task.IsFaulted)
{
var gameObject = task.Result.Root?.GetOrCreateGameObject(UnityCreationMode.DoNotCreateUnityComponents);
}
}
Загрузка модели с шаблоном ожидания
async void LoadModelWithAwait(RenderingSession session)
{
var result = await session.Connection.LoadModelFromSasAsync(new LoadModelFromSasOptions("builtin://Engine"), null);
var gameObject = result.Root?.GetOrCreateGameObject(UnityCreationMode.DoNotCreateUnityComponents);
}
В приведенных выше примерах кода использовался путь загрузки модели через SAS, так как встроенная модель загружена. Обращение к модели через контейнеры BLOB-объектов (с помощью LoadModelAsync
и LoadModelOptions
) происходит немного иначе.
RemoteEntitySyncObject
Создание игрового объекта Unity неявно добавляет компонент RemoteEntitySyncObject
к игровому объекту. Этот компонент используется для синхронизации преобразования сущностей с сервером. По умолчанию RemoteEntitySyncObject
требует от пользователя явно вызвать SyncToRemote()
, чтобы синхронизировать локальное состояние Unity с сервером. При включении SyncEveryFrame
объект будет синхронизирован автоматически.
У объектов с RemoteEntitySyncObject
могут быть экземпляры удаленных дочерних элементов, которые отображаются в редакторе Unity с помощью кнопки Show children.
Компоненты-оболочки
Компоненты, подключенные к сущностям Удаленной отрисовки, предоставляются Unity через MonoBehavior
прокси. Эти прокси-серверы представляют удаленный компонент в Unity и перенаправляют все изменения на узел.
Чтобы создать компоненты Удаленной отрисовки прокси-сервера, используйте метод расширения GetOrCreateArrComponent
.
var cutplane = gameObject.GetOrCreateArrComponent<ARRCutPlaneComponent>(RemoteManagerUnity.CurrentSession);
Привязка времени существования
Время существования удаленной сущности и игрового объекта Unity связывается через RemoteEntitySyncObject
. При вызове UnityEngine.Object.Destroy(...)
для такого игрового объекта удаленная сущность также будет удалена.
Чтобы уничтожить объект игры Unity, не затрагивая удаленную сущность, необходимо сначала вызвать Unbind()
в RemoteEntitySyncObject
.
Это справедливо и для всех прокси-компонентов. Чтобы уничтожить только представление на стороне клиента, сначала необходимо вызвать Unbind()
для прокси-компонента.
var cutplane = gameObject.GetComponent<ARRCutPlaneComponent>();
if (cutplane != null)
{
cutplane.Unbind();
UnityEngine.Object.Destroy(cutplane);
}