Interagir com componentes e objetos de jogos do Unity
O Azure Remote Rendering (ARR) é otimizado para um grande número de objetos (consulte Limitações). Embora seja possível gerenciar hierarquias grandes e complexas no host, é inviável replicar todas elas no Unity em dispositivos de baixa potência.
Portanto, quando um modelo é carregado no host, o Azure Remote Rendering espelha as informações sobre a estrutura do modelo no dispositivo cliente (que incorrerá em tráfego de rede), mas não replica os objetos e componentes no Unity. Em vez disso, ele espera que você solicite manualmente os objetos e componentes de jogo necessários do Unity, de modo que você possa limitar a sobrecarga ao que realmente é necessário. Dessa forma, você tem mais controle sobre o desempenho do lado do cliente.
Consequentemente, a integração do Unity ao Azure Remote Rendering possui uma funcionalidade adicional para replicar a estrutura de Remote Rendering sob demanda.
Carregar um modelo no Unity
Ao carregar um modelo, você obterá uma referência ao objeto raiz do modelo carregado. Essa referência não é um objeto de jogo do Unity, mas você pode transformá-lo em um usando o método de extensão Entity.GetOrCreateGameObject()
. Essa função espera um argumento do tipo UnityCreationMode
. Se você aprovar CreateUnityComponents
, o objeto de jogo do Unity recém-criado será preenchido com componentes de proxy para todos os componentes de Remote Rendering existentes no host. No entanto, é recomendável preferir DoNotCreateUnityComponents
a fim de minimizar a sobrecarga.
Modelo de carga com as corrotinas do 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);
}
}
Modelo de carga com padrão await
async void LoadModelWithAwait(RenderingSession session)
{
var result = await session.Connection.LoadModelFromSasAsync(new LoadModelFromSasOptions("builtin://Engine"), null);
var gameObject = result.Root?.GetOrCreateGameObject(UnityCreationMode.DoNotCreateUnityComponents);
}
Os exemplos de código acima usaram o caminho de carregamento do modelo via SAS pois o modelo interno é carregado. O endereçamento do modelo por meio de contêineres de blob (usando LoadModelAsync
e LoadModelOptions
) funciona de forma totalmente análoga.
RemoteEntitySyncObject
A criação de um objeto de jogo do Unity adiciona, implicitamente, um componente RemoteEntitySyncObject
ao objeto de jogo. Esse componente é usado para sincronizar a transformação de entidade com o servidor. Por padrão, RemoteEntitySyncObject
exige que o usuário chame explicitamente SyncToRemote()
para sincronizar o estado local do Unity com o servidor. Ao habilitar SyncEveryFrame
, o objeto irá sincronizar automaticamente.
Os objetos com RemoteEntitySyncObject
podem ter seus filhos remotos com uma instância criada e mostrados no editor do Unity através do botão Show children.
Componentes do wrapper
Os componentes anexados às entidades do Remote Rendering são expostos ao Unity por meio de proxy MonoBehavior
s. Esses proxies representam o componente remoto no Unity e encaminham todas as modificações para o host.
Para criar componentes do Remote Rendering de proxy, use o método de extensão GetOrCreateArrComponent
:
var cutplane = gameObject.GetOrCreateArrComponent<ARRCutPlaneComponent>(RemoteManagerUnity.CurrentSession);
Tempos de vida acoplados
O tempo de vida de uma entidade remota e um objeto de jogo do Unity são acoplados enquanto estão vinculados por RemoteEntitySyncObject
. Se você chamar UnityEngine.Object.Destroy(...)
com esse objeto de jogo, a entidade remota também será removida.
Para destruir o objeto de jogo do Unity, sem afetar a entidade remota, primeiro, você precisará chamar Unbind()
no RemoteEntitySyncObject
.
O mesmo ocorre em todos os componentes de proxy. Para destruir apenas a representação do lado do cliente, você precisa, primeiramente, chamar Unbind()
no componente de proxy:
var cutplane = gameObject.GetComponent<ARRCutPlaneComponent>();
if (cutplane != null)
{
cutplane.Unbind();
UnityEngine.Object.Destroy(cutplane);
}