Pular para o conteúdo principal
Este tópico fornece um breve passo a passo do uso da API C++ do Game Chat 2 para adicionar comunicação por voz e texto ao seu jogo.

Pré-requisitos

O Game Chat 2 exige que seu projeto tenha sido configurado para o GDK. Para obter detalhes sobre como fazer essa configuração, consulte Introdução ao Microsoft Game Development Kit. Compilar o Game Chat 2 exige incluir o cabeçalho principal GameChat2.h. Para vincular corretamente, seu projeto também precisa incluir GameChat2Impl.h em pelo menos uma unidade de compilação (recomendamos um cabeçalho pré-compilado comum, pois essas implementações de funções stub são pequenas e fáceis para o compilador gerar como “inline”). A interface do Game Chat 2 não exige que o projeto escolha entre compilar com C++/CX ou com C++ tradicional. Ela pode ser usada com qualquer um dos dois. A implementação também não lança exceções como meio de relatar erros não fatais. Você pode consumi-la facilmente em projetos sem exceções, se preferir. No entanto, a implementação lança exceções como meio de relatar erros fatais. (Para obter mais detalhes, consulte a seção Modelo de falhas mais adiante neste tópico.)

Inicialização

Comece a interagir com a biblioteca inicializando a instância singleton do Game Chat 2 com parâmetros que se aplicam ao tempo de vida da inicialização do singleton. A instância singleton é inicializada chamando chat_manager::initialize, conforme mostrado a seguir.
Você precisa se registrar para os eventos de suspensão e retomada por meio de RegisterAppStateChangeNotification. Na suspensão, você precisa limpar o Game Chat 2 com chat_manager::cleanup(). Na retomada, você deve reinicializar o Game Chat 2. Ele pode travar se você tentar usá-lo ao longo de um ciclo de suspensão/retomada.

Configurando usuários

Adicionando usuários ao seu título do Microsoft Game Development Kit (GDK)

Antes de adicionar usuários à instância do Game Chat 2, verifique se eles foram adicionados ao título do GDK. Isso é feito usando a API XUserAddAsync. Para obter mais informações sobre como usar essa API, consulte Identidade do usuário e XUser. Depois de obter o XUserHandle do usuário que você deseja adicionar ao Game Chat 2, você precisa obter o ID de usuário do XBOX (XUID) do usuário usando a API XUserGetId. O usuário precisa estar online, e você precisa ter o consentimento do usuário para esta etapa. XUserGetId fornece o XUID como um uint64_t. Você precisa converter o XUID em um std::wstring para uso com o Game Chat 2. Veja a seguir um exemplo de código que mostra como adicionar um usuário ao Game Chat 2 depois de obter um XUserHandle.
Lembre-se de que chamar XUserResolveIssueWithUiAsync exibe uma caixa de diálogo do sistema.

Adicionando usuários ao Game Chat 2

Depois que a instância for inicializada, você precisará adicionar os usuários locais à instância do Game Chat 2 usando chat_manager::add_local_user. Neste exemplo, o Usuário A representa um usuário local.
Em seguida, adicione os usuários remotos e os identificadores usados para representar o “ponto de extremidade” remoto em que o usuário está. Um ponto de extremidade é uma instância do aplicativo em execução em um dispositivo remoto. Neste exemplo, o Usuário B está no ponto de extremidade X. Os Usuários C e D estão no ponto de extremidade Y. O ponto de extremidade X recebe arbitrariamente o identificador “1”. O ponto de extremidade Y recebe arbitrariamente o identificador “2”. Informe o Game Chat 2 sobre os usuários remotos com as chamadas a seguir.
Em seguida, configure o relacionamento de comunicação entre cada usuário remoto e o usuário local. Neste exemplo, suponha que o Usuário A e o Usuário B estejam na mesma equipe. A comunicação bidirecional é permitida. c_communicationRelationshipSendAndReceiveAll é uma constante definida em GameChat2.h para representar a comunicação bidirecional. Defina o relacionamento do Usuário A com o Usuário B usando chat_user_local::set_communication_relationship.
Suponha que os Usuários C e D sejam “espectadores” e devam poder ouvir o Usuário A, mas não falar. c_communicationRelationshipSendAll é uma constante definida em GameChat2.h para representar essa comunicação unidirecional. Defina os relacionamentos da seguinte forma.
Para ver exemplos com as configurações de relacionamento dos quatro usuários locais, consulte a seção de cenários mais adiante neste tópico. Se, em algum momento, houver usuários remotos que foram adicionados à instância singleton, mas não foram configurados para se comunicar com nenhum usuário local, não há problema. Isso é esperado em cenários em que os usuários estão definindo as equipes ou podem trocar arbitrariamente de canal de fala. O Game Chat 2 só armazena em cache informações (por exemplo, relacionamentos de privacidade e reputação) dos usuários que foram adicionados à instância; por isso, é útil informar o Game Chat 2 sobre todos os usuários possíveis, mesmo que eles não possam falar com nenhum usuário local em um determinado momento. Por fim, suponha que o Usuário D tenha saído do jogo e deva ser removido da instância local do Game Chat 2. Isso pode ser feito usando chat_manager::remove_user, conforme mostrado a seguir.
Chamar chat_manager::remove_user() pode invalidar o objeto de usuário. Se você estiver usando a manipulação de áudio em tempo real, consulte Tempo de vida dos usuários do chat para obter mais informações. Caso contrário, o objeto de usuário é invalidado imediatamente quando chat_manager::remove_user() é chamado. Uma restrição sutil sobre quando os usuários podem ser removidos é detalhada na seção Processando alterações de estado mais adiante neste tópico.

Processando quadros de dados

O Game Chat 2 não tem uma camada de transporte própria. Ela precisa ser fornecida pelo aplicativo. Esse plug-in é gerenciado pelas chamadas regulares e frequentes do aplicativo ao par de métodos chat_manager::start_processing_data_frames() e chat_manager::finish_processing_data_frames(). Esses métodos são a forma como o Game Chat 2 fornece os dados de saída ao aplicativo. Esses métodos foram projetados para operar rapidamente. Eles podem ser consultados com frequência em uma thread de rede dedicada. Isso oferece um lugar conveniente para recuperar todos os dados enfileirados sem se preocupar com a imprevisibilidade do tempo de rede ou com a complexidade de callbacks multithread. Quando chat_manager::start_processing_data_frames() é chamado, todos os dados enfileirados são informados em uma matriz de ponteiros de estrutura game_chat_data_frame. Os aplicativos devem iterar pela matriz, inspecionar os pontos de extremidade de destino e usar a camada de rede do aplicativo para entregar os dados às instâncias remotas apropriadas do aplicativo. Depois que a matriz for concluída com todas as estruturas game_chat_data_frame, ela deverá ser passada de volta ao Game Chat 2 para liberar os recursos chamando chat_manager:finish_processing_data_frames(). Isso é mostrado no exemplo a seguir.
Quanto mais frequentemente os quadros de dados forem processados, menor será a latência de áudio percebida pelo usuário. O áudio é agrupado em quadros de dados de 40 ms. Esse é o período de consulta sugerido.

Processando alterações de estado

O Game Chat 2 fornece atualizações ao aplicativo, como mensagens de texto recebidas, por meio das chamadas regulares e frequentes do aplicativo ao par de métodos chat_manager::start_processing_state_changes() e chat_manager::finish_processing_state_changes(). Esses métodos operam rapidamente, de modo que podem ser chamados a cada quadro gráfico no loop de renderização da interface. Isso oferece um lugar conveniente para recuperar todas as alterações enfileiradas sem se preocupar com a imprevisibilidade do tempo de rede ou com a complexidade de callbacks multithread. Quando chat_manager::start_processing_state_changes() é chamado, todas as atualizações enfileiradas são informadas em uma matriz de ponteiros de estrutura game_chat_state_change. Os aplicativos devem iterar pela matriz, inspecionar a estrutura base para identificar seu tipo mais específico, converter a estrutura base no tipo mais detalhado correspondente e, em seguida, tratar essa atualização conforme apropriado. Depois que a matriz for concluída com todos os objetos game_chat_state_change disponíveis no momento, ela deverá ser passada de volta ao Game Chat 2 para liberar os recursos chamando chat_manager::finish_processing_state_changes(). Isso é mostrado no exemplo a seguir.
Como chat_manager::remove_user() invalida imediatamente a memória associada a um objeto de usuário, e as alterações de estado podem conter ponteiros para objetos de usuário, chat_manager::remove_user() não pode ser chamado durante o processamento das alterações de estado.

Chat de texto

Para enviar chat de texto, use chat_user::chat_user_local::send_chat_text(). Isso é mostrado no exemplo a seguir.
O Game Chat 2 gera um quadro de dados que contém essa mensagem. Os pontos de extremidade de destino do quadro de dados são aqueles associados aos usuários configurados para receber texto do usuário local. Quando os dados são processados pelos pontos de extremidade remotos, a mensagem é exposta por meio de game_chat_text_chat_received_state_change. Assim como no chat de voz, as restrições de privilégio e privacidade são respeitadas no chat de texto. Se um par de usuários tiver sido configurado para permitir o chat de texto, mas restrições de privilégio ou privacidade impedirem essa comunicação, a mensagem de texto será descartada.

Acessibilidade

A acessibilidade exige suporte à entrada e à exibição de chat de texto. A entrada de texto é obrigatória porque, mesmo em plataformas ou gêneros de jogo que historicamente não tiveram uso difundido de teclados físicos, os usuários podem configurar o sistema para usar tecnologias assistivas de conversão de texto em fala. Da mesma forma, a exibição de texto é obrigatória porque os usuários podem configurar o sistema para usar a conversão de fala em texto. Essas preferências podem ser detectadas nos usuários locais chamando os métodos chat_user::chat_user_local::text_to_speech_conversion_preference_enabled() e chat_user::chat_user_local::speech_to_text_conversion_preference_enabled(), respectivamente. Recomendamos que você habilite o texto condicionalmente, com base nas preferências do usuário.

Conversão de texto em fala

Quando um usuário tem a conversão de texto em fala habilitada, chat_user::chat_user_local::text_to_speech_conversion_preference_enabled() retorna true. Quando esse estado é detectado, o aplicativo precisa fornecer um método de entrada de texto. Depois de obter a entrada de texto fornecida por um teclado real ou virtual, passe a cadeia de caracteres para o método chat_user::chat_user_local::synthesize_text_to_speech(). O Game Chat 2 detecta e sintetiza dados de áudio com base na cadeia de caracteres e na preferência de voz de acessibilidade do usuário. Isso é mostrado no exemplo a seguir.
O áudio sintetizado como parte dessa operação é transportado para todos os usuários configurados para receber áudio desse usuário local. Se chat_user::chat_user_local::synthesize_text_to_speech() for chamado para um usuário que não tem a conversão de texto em fala habilitada, o Game Chat 2 não fará nada.

Conversão de fala em texto

Quando um usuário tem a conversão de fala em texto habilitada, chat_user::chat_user_local::speech_to_text_conversion_preference_enabled() retorna true. Quando esse estado é detectado, o aplicativo precisa estar preparado para fornecer uma interface associada às mensagens de chat transcritas. O Game Chat 2 transcreve automaticamente o áudio de cada usuário remoto e o expõe por meio de uma struct game_chat_transcribed_chat_received_state_change.

Considerações de desempenho da conversão de fala em texto

Quando a conversão de fala em texto está habilitada, a instância do Game Chat 2 em cada dispositivo remoto inicia uma conexão WebSocket com o ponto de extremidade dos serviços de fala. Cada cliente remoto do Game Chat 2 carrega o áudio no ponto de extremidade dos serviços de fala por meio desse WebSocket. O ponto de extremidade dos serviços de fala retorna ocasionalmente uma mensagem de transcrição ao dispositivo remoto. Em seguida, o dispositivo remoto envia a mensagem de transcrição (ou seja, uma mensagem de texto) ao dispositivo local. A mensagem transcrita é entregue pelo Game Chat 2 ao aplicativo para renderização. Portanto, o principal custo de desempenho da conversão de fala em texto é o uso da rede. A maior parte do tráfego de rede é o upload do áudio codificado. O WebSocket carrega o áudio que já foi codificado pelo Game Chat 2 no caminho “normal” do chat de voz. O aplicativo controla a taxa de bits por meio de chat_manager::set_audio_encoding_bitrate.

Interface do usuário

Recomendamos que, em todos os lugares em que a interface for mostrada aos usuários, especialmente em uma lista de gamertags, como um placar, você também exiba ícones de silenciado/falando como feedback para o usuário. Isso é feito chamando chat_user::chat_indicator() para recuperar uma enumeração game_chat_user_chat_indicator que representa o status atual e instantâneo do chat desse usuário. O exemplo a seguir demonstra a recuperação do valor do indicador de um objeto chat_user apontado pela variável chatUserA para determinar um valor de constante de ícone específico a ser atribuído a uma variável iconToShow.
Espera-se que o valor informado por chat_user::chat_indicator() mude com frequência, por exemplo, à medida que os jogadores começam e param de falar. Por isso, ele foi projetado para que os aplicativos o consultem a cada quadro da interface.

Silenciamento

O método chat_user::chat_user_local::set_microphone_muted() pode ser usado para alternar o estado de silenciamento do microfone de um usuário local. Quando o microfone está silenciado, nenhum áudio desse microfone é capturado. Se o usuário estiver em um dispositivo compartilhado, como o Kinect, o estado de silenciamento se aplicará a todos os usuários. O método chat_user::chat_user_local::microphone_muted() pode ser usado para recuperar o estado de silenciamento do microfone de um usuário local. Esse método reflete apenas se o microfone do usuário local foi silenciado no software por meio de uma chamada a chat_user::chat_user_local::set_microphone_muted(). Esse método não reflete um silenciamento controlado pelo hardware, por exemplo, por meio de um botão no headset do usuário. Não há nenhum método para recuperar o estado de silenciamento por hardware do dispositivo de áudio de um usuário por meio do Game Chat 2. O método chat_user::chat_user_local::set_remote_user_muted() pode ser usado para alternar o estado de silenciamento de um usuário remoto em relação a um usuário local específico. Quando o usuário remoto está silenciado, o usuário local não ouve nenhum áudio nem recebe nenhuma mensagem de texto do usuário remoto.

Silenciamento automático por má reputação

Normalmente, os usuários remotos começam sem silenciamento. O Game Chat 2 inicia os usuários em um estado silenciado quando:
  1. O usuário remoto não é amigo do usuário local.
  2. O usuário remoto tem um sinalizador de má reputação.
Quando os usuários são silenciados devido a essa operação, chat_user::chat_indicator() retorna game_chat_user_chat_indicator::reputation_restricted. Esse estado é substituído pela primeira chamada a chat_user::chat_user_local::set_remote_user_muted() que inclua o usuário remoto como usuário de destino.

Privilégios e privacidade

Além do relacionamento de comunicação configurado pelo jogo, o Game Chat 2 aplica restrições de privilégio e privacidade. O Game Chat 2 faz consultas de restrições de privilégio e privacidade quando um usuário é adicionado pela primeira vez. O chat_user::chat_indicator() do usuário sempre retorna game_chat_user_chat_indicator::silent até que essas operações sejam concluídas. Se a comunicação com um usuário for afetada por uma restrição de privilégio ou privacidade, o chat_user::chat_indicator() do usuário retornará game_chat_user_chat_indicator::platform_restricted. As restrições de comunicação da plataforma se aplicam tanto ao chat de voz quanto ao de texto. Nunca haverá um caso em que o chat de texto seja bloqueado por uma restrição da plataforma e o chat de voz não, ou vice-versa. chat_user::chat_user_local::get_effective_communication_relationship() pode ser usado para ajudar a distinguir quando os usuários não conseguem se comunicar devido a operações de privilégio e privacidade incompletas. Ele retorna o relacionamento de comunicação aplicado pelo Game Chat 2 na forma de game_chat_communication_relationship_flags e o motivo pelo qual o relacionamento pode não ser igual ao relacionamento configurado, na forma de uma enumeração game_chat_communication_relationship_adjuster. Por exemplo, se as operações de consulta ainda estiverem em andamento, o game_chat_communication_relationship_adjuster será game_chat_communication_relationship_adjuster::initializing. Esse método não deve ser usado para influenciar a interface. (Para obter mais informações, consulte a seção Interface do usuário anteriormente neste tópico.) Se o Game Chat 2 encontrar um problema de privilégio, ele será informado na alteração de estado communication_relationship_adjuster_changed. Se o Game Chat 2 não conseguir recuperar o privilégio do usuário por um motivo irrecuperável, isso será informado como um ajustador game_chat_communication_relationship_adjuster::privilege_check_failure. Se o Game Chat 2 não conseguir recuperar o privilégio do usuário por um motivo que o usuário talvez consiga resolver, isso será informado como um ajustador game_chat_communication_relationship_adjuster::resolve_user_issue. Se o usuário não tiver privilégios que possam ser resolvidos com a interface, isso será informado como um ajustador game_chat_communication_relationship_adjuster::privilege. Nesses casos, a comunicação será restrita. Aqui está um exemplo de como verificar se um usuário tem um dos problemas comuns a seguir.
  1. Os usuários precisam dar consentimento aos serviços do XBOX para que o Game Chat 2 verifique os privilégios.
  2. A conta do usuário está configurada para negar privilégios (por exemplo, por ser uma conta de criança e, portanto, não poder usar o chat).
Para problemas informados com o ajustador game_chat_communication_relationship_adjuster::privilege, você pode chamar XUserResolvePrivilegeWithUiAsync com XUserPrivilegeOptions::None e XUserPrivilege::Communications para tentar resolver o problema. Para problemas informados com o ajustador game_chat_communication_relationship_adjuster::resolve_user_issue, você pode chamar XUserResolveIssueWithUiAsync com nullptr como URL para tentar resolver o problema. Recomendamos que você mostre uma interface que indique que há um problema de privilégio. Permita que o usuário decida se deseja tentar resolver o problema, por meio do pressionamento de um botão ou de uma opção de menu. O usuário pode não conseguir ou não querer resolver o problema. Se o usuário resolver o problema, a solução entrará em vigor na próxima vez que o usuário for adicionado ao Game Chat 2.
chat_manager::remove_user() não pode ser chamado durante o processamento das alterações de estado (ou seja, depois que chat_manager::start_processing_state_changes() tiver sido chamado e antes da chamada correspondente a chat_manager::finish_processing_state_changes()). Chamar chat_manager::remove_user() enquanto as alterações de estado estão sendo processadas pode invalidar a memória associada ao usuário removido. Se você vir um ajustador game_chat_communication_relationship_adjuster::privilege e quiser tentar resolver os privilégios do usuário, deverá aguardar até depois do processamento das alterações de estado para fazer isso.
Para obter o XUserHandle a partir de um XUID, o que é necessário para chamar XUserResolvePrivilegeWithUiAsync, você pode usar a API XUserFindUserById para obter um novo XUserHandle. Como alternativa, você pode manter aquele que obteve com XUserAddAsync e acompanhar qual XUID corresponde a ele. Aqui está um exemplo de como resolver esses problemas.

Limpeza

Quando o aplicativo não precisar mais de comunicações por meio do Game Chat 2, você deverá chamar chat_manager::cleanup(). Isso permite que o Game Chat 2 recupere os recursos alocados para gerenciar as comunicações.

Modelo de falhas

A implementação do Game Chat 2 não lança exceções como meio de relatar erros não fatais. Você pode consumi-la facilmente em projetos sem exceções, se preferir. No entanto, o Game Chat 2 lança exceções para informar você sobre erros fatais. Esses erros resultam do uso indevido da API, como adicionar um usuário à instância do Game Chat antes de inicializá-la ou acessar um objeto de usuário depois que ele foi removido da instância do Game Chat 2. Espera-se que esses erros sejam detectados no início do desenvolvimento, e eles podem ser corrigidos modificando o padrão usado para interagir com o Game Chat 2. Quando esse erro ocorre, uma dica sobre a causa do erro é impressa no depurador antes que a exceção seja lançada.

Como configurar cenários populares

Pressionar para falar

O recurso de pressionar para falar deve ser implementado com chat_user::chat_user_local::set_microphone_muted(). Chame set_microphone_muted(false) para permitir a fala e set_microphone_muted(true) para restringi-la. Esse método oferece a resposta de menor latência do Game Chat 2.

Equipes

Suponha que o Usuário A e o Usuário B estejam na Equipe Azul e que o Usuário C e o Usuário D estejam na Equipe Vermelha. Cada usuário está em uma instância exclusiva do aplicativo. No dispositivo do Usuário A:
No dispositivo do Usuário B:
No dispositivo do Usuário C:
No dispositivo do Usuário D:

Transmissão

Suponha que o Usuário A seja o líder e esteja dando ordens. Os Usuários B, C e D só podem ouvir. Cada jogador está em um dispositivo exclusivo. No dispositivo do Usuário A:
No dispositivo do Usuário B:
No dispositivo do Usuário C:
No dispositivo do Usuário D:

Documentação de referência da API

Confira também

Introdução ao Game Chat 2 Manipulação de áudio em tempo real Conteúdo da API (GameChat2) Microsoft Game Development Kit
Última modificação em 8 de outubro de 2026