Adicionar suporte ao Android XR a um projeto do Godot XR

Dispositivos XR relevantes
Estas orientações ajudam você a criar experiências para esses tipos de dispositivos XR.
Headsets XR
Óculos XR com fio

Se você já tiver um projeto de RV no Godot, poderá adicionar suporte ao Android XR sem iniciar um novo projeto separado. Algumas etapas são obrigatórias para todos os projetos, enquanto outras são opcionais, dependendo dos recursos de XR usados. Ao longo das etapas, incluímos links para vários projetos do Godot XR de código aberto que adicionaram suporte ao Android XR, além de solicitações de pull relevantes que mostram as mudanças necessárias para ativar determinados recursos.

Etapas obrigatórias para todos os projetos

Conclua as etapas nos tópicos a seguir, não importa quais tipos de recursos de XR seu projeto ofereça suporte. Depois, revise os recursos descritos na lista de etapas opcionais para determinar se o projeto exige mais trabalho.

Atualizar o Godot e o plug-in OpenXR Vendors do Godot

Siga estas etapas para atualizar seu projeto com as versões mais recentes necessárias e configurar as definições do projeto para Android XR:

  1. Atualize a versão do Godot para 4.6.2 ou mais recente. Consulte a documentação sobre migração para uma nova versão se precisar de mais ajuda para seu projeto.
  2. Faça o download da versão 5.1 ou mais recente do plug-in Godot OpenXR Vendors na Asset Store, na Asset Library ou no repositório do GitHub.

  3. Configure as definições do projeto para Android XR:

    1. Adicione uma predefinição de exportação para o Android XR.
    2. Ative a opção Usar build do Gradle.

    Ative a

    1. Na seção Recursos de RV, selecione OpenXR para o Modo de RV e Ativar plug-in AndroidXR.

    Configure as opções no

Adicionar suporte para captura de movimentos das mãos

Embora os controladores possam estar disponíveis, o principal método de entrada em headsets e óculos XR do Android XR é a captura de movimentos das mãos. Se possível, adicione suporte ao rastreamento de mãos ao seu projeto do Godot.

Adicionar suporte à captura de movimentos das mãos: configurar as definições do projeto

Primeiro, siga estas etapas para configurar as configurações do projeto e ativar a captura de movimentos das mãos e as extensões OpenXR relacionadas.

  1. Abra as configurações do projeto e navegue até Geral > XR > OpenXR.
  2. Na seção Extensões, selecione Rastreamento de mãos e Perfil de interação com as mãos.

    Configure as opções no

  3. Encontre a subseção Meta na seção Extensões e selecione Malha de rastreamento das mãos e Mira de rastreamento das mãos.

    Configure as opções no

Adicionar suporte à captura de movimentos das mãos: adicionar e configurar nós de controle

Em vez de modificar dinamicamente os nós XRController3D atuais para o rastreamento das mãos, adicione nós de controlador para rastrear e mostrar os modelos de mãos, além de processar a entrada da extensão "Mira de rastreamento das mãos":

  1. Adicione mais três nós XRController3D ao nó XROrigin3D.

    1. Nomeie um como "HandTrackingLeft" e defina a propriedade do rastreador como /user/hand_tracker/left.
    2. Nomeie outro como "HandTrackingRight" e defina a propriedade do rastreador como /user/hand_tracker/right.
    3. Nomeie o último como "HandTrackingAimLeft" e defina a propriedade do rastreador como /user/fbhandaim/left.

    Se os nós XRController3D originais do seu projeto fossem chamados "XRController3D_left" e "XRController3D_right", sua cena ficaria assim:

    Como sua cena pode ficar depois de adicionar os nós do controlador.

  2. Conecte o sinal tracking_changed em HandTrackingLeft e HandTrackingRight a funções individuais que atualizam a visibilidade dos rastreadores de controle correspondentes (XRController3D_left e XRController3D_right no exemplo anterior).

    Por exemplo, a função conectada ao sinal em HandTrackingLeft pode ter esta aparência:

    func _on_hand_tracking_left_hand_tracking_changed(tracking):
        $XROrigin3D/XRController3D_left.visible = not tracking
    
  3. Ative a propriedade Mostrar quando rastreado nos nós do controlador de captura de movimentos das mãos.

    Agora, seu projeto pode trocar visualmente entre modelos de controlador e modelos de captura de movimentos das mãos, dependendo se o usuário está usando a captura de movimentos das mãos ou controladores.

  4. Adicione alguns nós OpenXRFbHandTrackingMesh como filhos aos nós do controlador de captura de movimentos das mãos.

  5. Adicione nós XRHandModifier3D como filhos desses nós OpenXRFbHandTrackingMesh, garantindo que a propriedade Hand Tracker correta esteja definida para aplicar dados de captura de movimentos das mãos em tempo real aos modelos.

    Como sua cena pode ficar depois que você adiciona os nós filhos aos nós controladores.

Adição de suporte à captura de movimentos das mãos: configure um perfil de interação com as mãos no mapa de ações do OpenXR.

Em seguida, configure o perfil Interação com as mãos no Mapa de ações do OpenXR:

  1. Abra o menu OpenXR Action Map na parte de baixo do editor.
  2. Exclua o perfil Simple Controller para evitar problemas de compatibilidade com controles do Galaxy XR.
  3. Clique em Adicionar perfil, selecione Interação com as mãos e clique em OK.
  4. Mapeie esse perfil para um ou mais conjuntos de ações da maneira que preferir.

Dependendo dos requisitos do app, talvez seja necessário ajustar como o app processa a entrada do usuário com captura de movimentos das mãos.

Adicionar suporte à captura de movimentos das mãos: configurar um gesto de menu para o Android XR

Por fim, você pode implementar um gesto de menu para o Android XR. Isso mostra um ícone quando a mão esquerda do jogador está na posição correta para fazer o gesto de menu, além de mostrar ou ocultar o menu quando o usuário faz o gesto. Você vai usar o nó HandTrackingAimLeft que você adicionou antes para processar isso.

  1. Adicione um quad de publicidade ao nó de captura de movimentos das mãos esquerdo mostrando um ícone que você escolheu. Consulte o nó MenuIcon na imagem a seguir dos nós de controlador adicionados anteriormente.

    Como sua cena pode ficar depois que você adiciona os nós filhos aos nós controladores.

  2. Conecte-se aos indicadores button_pressed e button_released em HandTrackingAimLeft a funções como esta:

    @onready var menu_icon: MeshInstance3D = $XROrigin3D/HandTrackingLeft/MenuIcon
    
    func _on_hand_tracking_aim_left_button_pressed(p_name):
      if p_name == "menu_pressed":
    toggle_menu()
      elif p_name == "menu_gesture":
        if OS.has_feature("androidxr"):
          menu_icon.visible = true
    
    func _on_hand_tracking_aim_left_button_released(p_name):
      if p_name == "menu_gesture":
        menu_icon.visible = false
    

Etapas opcionais para determinados recursos

Depois de concluir as etapas necessárias para seu projeto, decida se você precisa fazer mais trabalho para determinados recursos, dependendo dos requisitos e recursos do app. Para mais informações sobre cada um desses recursos opcionais, consulte as seções a seguir.

Registrar pinças como pressionamentos de botão

No Android XR, o gesto de pinça é usado para muitas ações básicas do sistema, como selecionar itens, rolar, mover ou redimensionar janelas e mover elementos ou objetos da interface em espaços 2D e 3D. Para se alinhar a esses padrões e promover uma experiência do usuário consistente, seu app precisa registrar os movimentos de pinça de maneira semelhante aos toques de botão em um controlador ao usar a captura de movimentos das mãos.

Para configurar seu app dessa forma, use os valores de ponto flutuante fornecidos pelo perfil de interação com as mãos que você criou para criar uma ação virtual:

const PRESSED_THRESHOLD := 0.8
const RELEASED_THRESHOLD := 0.6

@onready var left_controller: XRController3D = $XROrigin/XRController3D_left

func _on_xr_controller_3d_left_input_float_changed(p_name: String, value: float):
    if p_name == "pinch":
        var xr_tracker = XRServer.get_tracker(left_controller.tracker)
        if _left_hand_pinching:
            if value < RELEASED_THRESHOLD:
                _left_hand_pinching = false
                xr_tracker.set_input("pinch_pressed", false)
        else:
            if value > PRESSED_THRESHOLD:
                _left_hand_pinching = true
                xr_tracker.set_input("pinch_pressed", true)

Pontos principais sobre o código

  • Verifica se o valor float é maior ou menor que limites específicos nos indicadores XRController3D input_float_changed.
  • Cria uma ação virtual chamada pinch_pressed.

Usar as funções das ferramentas de XR com a captura de movimentos das mãos

Muitos projetos do Godot XR usam as Ferramentas do Godot XR, incluindo alguns dos projetos de código aberto vinculados nesta página. Para que algumas funções das Ferramentas de XR funcionem, como FunctionPointer para interações de menu, você vai precisar de um código adicional para trocar a ação que está procurando quando o usuário muda para a captura de movimentos das mãos.

Por exemplo, ao usar FunctionPointer para interações de menu, atualize a propriedade active_button_action para a ação de captura de movimentos das mãos com base no sinal tracking_changed dos nós XRController3D para captura de movimentos das mãos. Esses nós eram HandTrackingLeft e HandTrackingRight nas etapas de configuração de captura de movimentos das mãos anteriores.

const TRIGGER_POINTER_ACTION = "trigger_click"
const PINCH_POINTER_ACTION = "pinch_pressed"

@onready var func_point_left: XRToolsFunctionPointer = %FunctionPointerLeft

func _on_hand_tracking_left_tracking_changed(tracking: bool) -> void:
    if tracking:
        func_point_left.active_button_action = PINCH_POINTER_ACTION
else:
func_point_left.active_button_action = TRIGGER_POINTER_ACTION

Pontos principais sobre o código

Usar a captura de movimentos das mãos com a locomoção artificial

Se o projeto usar locomoção artificial, ainda será possível usar a captura de movimentos das mãos. Por exemplo, você pode criar um sistema de movimento que permita aos jogadores desenhar caminhos para atravessar com um gesto ou permitir que eles bombeiem as mãos para cima e para baixo para acelerar, com gestos adicionais para pular, escalar e planar.

O Museu de Todas as Coisas tem movimentação artificial usando os controles analógicos nos controles. A movimentação por captura de movimentos das mãos foi implementada adicionando "joysticks virtuais" que o jogador aciona ao fazer gesto de pinça aproximando os dedos no ar e mover a mão na direção em que quer que o joystick se mova.

Confira algumas das principais conclusões da solicitação de pull que implementou esse suporte:

  • Uma cena XRVirtualThumbstick é instanciada quando um gesto de pinça é detectado.
  • Enquanto o gesto de pinça é mantido, a distância e a direção relativas do local original são transformadas em um Vector2 e mapeadas virtualmente para a entrada normal do controle analógico.
  • O jogador também recebe feedback visual dessa entrada na forma de duas malhas quadriculadas em outdoors, ilustrando a posição do controle analógico.

Você pode tentar uma abordagem semelhante para fazer com que seu código de locomoção acionado por um controle analógico funcione com mudanças mínimas. No entanto, seu projeto ainda pode exigir uma solução de locomoção personalizada para captura de movimentos das mãos.

Adicionar suporte de transmissão

Você pode adicionar suporte de transmissão ao seu app para que os usuários possam ver o ambiente ao redor no mundo real.

Para fazer isso no seu app, faça as seguintes mudanças no código:

  • Defina o environment_blend_mode do XRInterface do OpenXR como XR_ENV_BLEND_MODE_ALPHA_BLEND.
  • Defina o background_mode do nó WorldEnvironment como BG_COLOR.
  • Defina o background_color do nó WorldEnvironment como qualquer cor totalmente transparente.
  • Defina a propriedade Viewport transparent_bg como true.

Usar a extensão de estimativa de iluminação

Ao ativar a visualização externa, considere usar a extensão OpenXR de estimativa de luz do Android XR. Essa extensão ajusta as propriedades do WorldEnvironment e do DirectionalLight3D para emular melhor a iluminação do ambiente real de um usuário. Assim, os objetos virtuais se misturam melhor com as condições de iluminação do mundo real. Você pode ativar essa extensão nas configurações do projeto.

  1. Abra as configurações do projeto e navegue até Geral > XR > OpenXR.
  2. Na seção Androidxr, selecione Estimação de luz.

    Configure as opções no

  3. Adicione um nó OpenXRAndroidLightEstimation à árvore de cenas e conecte-o ao WorldEnvironment e ao DirectionalLight3D da cena.

    Opções para o

Exemplo: ativar ou desativar a transmissão direta e a estimativa de iluminação

O código a seguir ativa ou desativa a transmissão direta e a estimativa de iluminação:

@onready var world_environment = $WorldEnvironment
@onready var directional_light = $DirectionalLight3D
@onready var directional_light_orig_transform: Transform3D = directional_light.transform

func set_passthrough_enabled(p_enabled: bool) -> void:
    var xr_interface = XRServer.find_interface("OpenXR")
    if xr_interface == null:
        return

    var supported_blend_modes = xr_interface.get_supported_environment_blend_modes()
    if not supported_blend_modes.has(XRInterface.XR_ENV_BLEND_MODE_ALPHA_BLEND):
        return

    # Passthrough
    if p_enabled:
        xr_interface.set_play_area_mode(XRInterface.XR_PLAY_AREA_STAGE)
        xr_interface.environment_blend_mode = XRInterface.XR_ENV_BLEND_MODE_ALPHA_BLEND
        world_environment.environment.background_mode = Environment.BG_COLOR
        world_environment.environment.background_color = Color(0.0, 0.0, 0.0, 0.0)
        get_viewport().transparent_bg = true
    else:
        xr_interface.set_play_area_mode(XRInterface.XR_PLAY_AREA_ROOMSCALE)
        xr_interface.environment_blend_mode = XRInterface.XR_ENV_BLEND_MODE_OPAQUE
        world_environment.environment.background_mode = Environment.BG_SKY
        get_viewport().transparent_bg = false

    # Light Estimation
    if OS.has_feature("androidxr"):
        var light_estimation = Engine.get_singleton("OpenXRAndroidLightEstimationExtension")
        if p_enabled and light_estimation.is_light_estimation_supported():
            light_estimation.start_light_estimation()
        elif light_estimation.is_light_estimation_started():
            light_estimation.stop_light_estimation()
            directional_light.transform = directional_light_orig_transform
Pontos principais sobre o código
  • Ao desativar a estimativa de iluminação, a direção original do DirectionalLight3D precisa ser restaurada manualmente.
  • Para um exemplo completo de um projeto que usa visualização externa e estimação de luz, confira Expedition to Blobotopia no GitLab.