Взаимодействие с объектами и компонентами игр 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.

RemoteEntitySyncObject

Компоненты-оболочки

Компоненты, подключенные к сущностям Удаленной отрисовки, предоставляются 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);
}

Следующие шаги