Solução de projeto empresarial de renderização em nuvem Unity Render Streaming

Fluxo de renderização do Unity

Diretório de artigos

prefácio

Link original
UnityRenderStreaming documento oficial
Unity: 2021.3.8f1c1
RenderStreaming: 3.1.0-exp.4 (Pré-lançamento)
RenderStreaming WebServer: 3.1.0-exp.3

Mostrar resultados

vídeo de demonstração
insira a descrição da imagem aqui

Demonstração de vídeo de rede externa
insira a descrição da imagem aqui

cena aberta

Use o modelo de amostra HDRP como um cenário de teste
insira a descrição da imagem aqui

seleção de versão

Este RenderStreamingPackage usa3.1.0-exp.4, e não há versão oficial, mas exp.4 abriu codificação de fluxo de vídeo, taxa de quadros, taxa de bits, taxa de zoom e outras configurações em comparação com a versão exp.3, e também é muito estável em uso, por isso é conveniente para ajustar de acordo com suas próprias necessidades de projeto.
WebServer usa3.1.0-exp.3, devido à versão exp.4 do servidor, há um problema com a verificação do caminho de acesso à página da web.
Endereço Git: UnityRenderStreaming
insira a descrição da imagem aqui
insira a descrição da imagem aqui

servidor web

1. Download do servidor, instalação do Node.js

Escolha o servidor de acordo com sua própria plataforma, você precisa instalar o Node.js para baixar
e usar node -v npm -vpara verificar se a instalação foi bem-sucedida
insira a descrição da imagem aqui

2. Início do servidor

O método de inicialização do Windows é o seguinte (consulte a documentação oficial para outros métodos de inicialização da plataforma )
: Encontre webserver.exe, digite cmd na barra de endereços e pressione Enter
insira a descrição da imagem aqui

Entrada .\webserver.exe -w, comece com WebSocket
insira a descrição da imagem aqui

Abra o navegador, digite o IP local, a figura a seguir é o conteúdo após iniciar com WebSocket
insira a descrição da imagem aqui

Configurações do projeto do Unity

1. Instale o Render Streaming

Depois que o código-fonte for descompactado, copie com.unity.renderstreamingo arquivo e coloque-o nos Pacotes do projeto de amostra e crie uma nova pasta. (Guarde de acordo com sua preferência)
insira a descrição da imagem aqui
insira a descrição da imagem aqui

Abra o PackageManager
insira a descrição da imagem aqui
e clique em + , selecione Add package from disk
insira a descrição da imagem aqui
para encontrar o arquivo agora package.json, abra-o
insira a descrição da imagem aqui
e abra-o da seguinte maneira
insira a descrição da imagem aqui

2. Instale o WebRTC

Selecione Add package by name
insira a descrição da imagem aqui
a entrada com.unity.webrtc, clique em Adicionar
insira a descrição da imagem aqui
para instalar da seguinte maneira:
insira a descrição da imagem aqui

3. Configurações de renderização de streaming

Crie um objeto vazio, nomeie-o como RenderStreaming
insira a descrição da imagem aqui
e adicione RenderStreaming, Broadcaste VideoStreamSendercomponentes.
Modifique os parâmetros da seguinte maneira:
insira a descrição da imagem aqui

4. Transmissão de áudio (adicione de acordo com suas necessidades)

Adicione AudioStreamSendero componente acima AudioListener, este componente deve estar em um
insira a descrição da imagem aqui
Broadcastcomponente de objeto lembre-se de adicionar AudioStreamSendero componente
insira a descrição da imagem aqui

5. O Unity inicia o teste

O efeito da seleção é o seguinte, você pode ajustar os parâmetros ReceiverSample
insira a descrição da imagem aqui
de acordo com suas próprias necessidadesVideoStreamSender
insira a descrição da imagem aqui
insira a descrição da imagem aqui

interagir

1. Configurações básicas do projeto interativo

Instale o InputSystem
e algumas das configurações a seguir destinam-se aUnity2021.2Versão acima, link de referência de versão inferior
(o InputSystem foi usado por padrão neste exemplo de HDRP)
insira a descrição da imagem aqui
Após a janela pop-up aparecer, selecioneSim, concorde em usar o novo sistema de entrada ou selecione novo ou ambos executados em segundo plano
insira a descrição da imagem aqui
em ProjectSettings/Player/OtherSettings/ActiveInputHanding para abrir (2021.2) modificação de configuração do pacote do sistema de entrada (2021.2)
insira a descrição da imagem aqui

ProjectSettings/Player/Resolution and Presentation/Run in background
insira a descrição da imagem aqui

insira a descrição da imagem aqui

2. Configurações de interação de cena

Referência de documentação oficial
Adicionar InputReceivercomponentes e adicionar Broadcasta
insira a descrição da imagem aqui

3. Interação de teclado e mouse

Abrir depois de criar InputActions, operação: Create/InputActions
insira a descrição da imagem aqui
Configurar ações de acordo com os requisitos do seu projeto
insira a descrição da imagem aqui
Arraste o arquivo InputActions configurado para ele InputReceiver/Actions, expanda Eventos, você pode ver os eventos correspondentes às Ações configuradas e vinculá-los de acordo com suas necessidades
insira a descrição da imagem aqui

4. Interação da interface do usuário

EventSystem usa InputSystemUIInputModule
insira a descrição da imagem aqui
a resolução de exibição para ser consistente VideoStreamSendercom isso StreamingSize, caso contrário, o ponto de reconhecimento será deslocado
insira a descrição da imagem aqui
insira a descrição da imagem aqui

Implantação de servidor extranet

Para a maioria dos aplicativos WebRTC, o servidor precisa retransmitir o tráfego entre os pares, pois os soquetes diretos geralmente não são possíveis entre os clientes (a menos que os aplicativos estejam na mesma rede local). Uma solução comum para esse problema é usar um servidor TURN . O termo denota passagem usando relé NAT, um protocolo para retransmitir o tráfego de rede.
Consulte as configurações do servidor TURN na documentação do Unity

A porta utilizada pelo servidor TURN precisa ser pública, podendo ser configurados os valores máximo e mínimo

protocolo porta
TCP 32355-65535, 3478-3479
UDP 32355-65535, 3478-3479

config.jsAltere o arquivo no lado da webconfig.iceServers

config.iceServers = [{
    
    
    urls: ['stun:stun.l.google.com:19302']
    }, {
    
    
    urls: ['turn:xx.xx.xx.xx:3478?transport=tcp'], 
    username: 'username', 
    credential: 'password'
  }
];

Modificando RenderStreamingcomponentes no UnityIce Server
Adicione uma descrição da imagem

Servidor Web Personalizado

Veja a seguir como criar seu próprio WebServer, consulte a documentação oficial para obter mais detalhes
1. Baixe o código-fonte do exp.3
insira a descrição da imagem aqui
2. Encontre o WebApp após a descompactação 3.
insira a descrição da imagem aqui
Digite cmd na barra de endereços
insira a descrição da imagem aqui
4. Insira npm installou npm iinstale dependências
insira a descrição da imagem aqui
Se o a instalação é muito lenta ou falha devido ao tempo limite, você pode inseri-la primeiro
npm config set registry https://registry.npm.taobao.org
para substituir a fonte da imagem de instalação npm por uma doméstica.
insira a descrição da imagem aqui
Se ocorrerem os seguintes erros, você pode inseri-la npm config set legacy-peer-deps truee, em seguida, inseri-la novamente npm installou npm iinstalar dependências**
insira a descrição da imagem aqui

5. Build Server, digite npm run build
insira a descrição da imagem aqui
6. Start Server, digitenpm run start -- -w
insira a descrição da imagem aqui
Se a inicialização for anormal, conforme mostrado na figura abaixo, use npm run dev -- -wIniciar
insira a descrição da imagem aqui
para iniciar da seguinte maneira. Não está claro por que a situação acima ocorre. Se você souber o motivo, informe eu, obrigado.
insira a descrição da imagem aqui
7. Crie um atalho de inicialização.
Para facilitar a inicialização rápida no futuro, você pode criar os seguintes arquivos.
insira a descrição da imagem aqui
8. Empacote,npm run pack
aguarde o progresso ser concluído e empacote-o em um
insira a descrição da imagem aqui
insira a descrição da imagem aqui
método de inicialização exe conforme acima.\webserver.exe -w
insira a descrição da imagem aqui

9. Modifique arquivos da web de acordo com suas necessidades
insira a descrição da imagem aqui

Web e Unity enviam mensagens personalizadas entre si

WebRTCA função em RTCDataChanneluso para enviar uma mensagem Send, use a função para receber uma mensagemOnMessage

1. O Unity envia uma mensagem para a Web

O script criado no projeto Unity é o seguinte, utilizando os objetos inputReceiverdoChannelSend

using Unity.RenderStreaming;
using UnityEngine;

public class RenderStreamingManager : MonoBehaviour
{
    
    
    private InputReceiver inputReceiver;

    private void Awake()
    {
    
    
        inputReceiver = transform.GetComponent<InputReceiver>();
    }

    public void SendMsg(string msg)
    {
    
    
        inputReceiver.Channel.Send(msg);
    }

    private void Update()
    {
    
    
        if (Input.GetKeyDown(KeyCode.P))
        {
    
    
            SendMsg("Send Msg to web");
        }
    }
}

Lembre-se de adicioná-lo ao projeto
insira a descrição da imagem aqui
Web para receber da seguinte maneira
Encontre o objeto receiver.jsno arquivo e use as informações recebidas O conteúdo da mensagem recebida é o seguinte, a string estará em dadosinputSenderChannelonmessage
insira a descrição da imagem aqui

insira a descrição da imagem aqui

2. A web envia uma mensagem para Unity

Use a função enviar para enviar mensagens na web

      this.inputSenderChannel.send("msg to unity");

No OnMessage no Unity Receiver.cs, a mensagem enviada pela web é recebida por meio do RTCDataChannel
insira a descrição da imagem aqui

Como os projetos corporativos são aplicados

1. A escolha entre acesso à rede externa claro e suave

Sob a premissa de que a largura de banda do servidor permite, melhore ao máximo a qualidade da transmissão, conforme segue, quais são minhas configurações no projeto
insira a descrição da imagem aqui

Você pode ajustá-lo de acordo com sua própria largura de banda DepathBuffer,StreamingSize,Framerate,Bitrate,ScaleResolution.
Você também pode obter o componente VideoStreamSender e modificar os parâmetros correspondentes durante o tempo de execução para facilitar o teste pós-lançamento.

VideoStreamSender videoStreamSender = transform.GetComponent<VideoStreamSender>();
videoStreamSender.SetTextureSize(new Vector2Int(gameConfig.RSResolutionWidth,gameConfig.RSResolutionHeight));
videoStreamSender.SetFrameRate(gameConfig.RSFrameRate);
videoStreamSender.SetScaleResolutionDown(gameConfig.RSScale);
videoStreamSender.SetBitrate((uint)gameConfig.RSMinBitRate,(uint)gameConfig.RSMaxBitRate);

2. Botão Web para substituir o botão de operação do Unity

Devido à limitação atual das alterações de resolução, os botões do Unity muitas vezes não podem ser clicados corretamente, então os alunos da Web criam os botões correspondentes e enviam mensagens para o Unity pela Web para responder às operações dos botões correspondentes.
Meu lado é configurar o id para todos os botões, a web envia o id do botão, o Unity percorre a tabela de configuração após recebê-lo e executa o Invoke

    private void OnClickButton(int elementId)
    {
    
    
        // 在配置表中根据id,获取UIName,FunctionName,Para
        List<UIMatchFuncModel> uiMatchFuncModels = UniversalConfig.Instance.GetUIMatchModels();
        foreach (var item in uiMatchFuncModels.Where(item => item.id == elementId))
        {
    
    
            ExecuteFunction(item);
            break;
        }
    }
    private void ExecuteFunction(UIMatchFuncModel matchFuncModel)
    {
    
    
        UIPanel uiPanel = UIKit.GetPanel(matchFuncModel.uiName);
        if (uiPanel == null)
        {
    
    
            uiPanel = UIKit.OpenPanel(matchFuncModel.uiName);
        }
        uiPanel.Invoke(matchFuncModel.functionName,0);
    }

3. Sincronização de resolução, consulte o método de sincronização de resolução em iOS e Android abaixo

Combine diferentes resoluções de dispositivos, obtenha a resolução atual do dispositivo por meio da Web e envie uma mensagem de largura e altura do dispositivo para o Unity após a conexão ser bem-sucedida e redefina a resolução de saída no Unity para manter o dispositivo da Web totalmente exibido.

public void ChangeScreenSize(int width,int height)
{
    
        
	videoStreamSender.SetTextureSize(new Vector2Int(width,height));
}

4. Precauções ao acessar a tela vertical padrão no celular e exibir a tela horizontal

Como a tela de exibição da tela vertical no telefone celular é muito pequena, geralmente exibe o conteúdo da tela horizontal no estado da tela vertical. Portanto:
1. Ao definir a resolução mencionada no ponto anterior, você precisa prestar atenção se o dispositivo do lado web é uma tela horizontal ou uma tela vertical
2. Projeto Se houver uma operação de deslizamento em , é preciso ficar atento para inverter a operação de acordo com as telas horizontal e vertical.

5. Detecte se o lado do Unity está desconectado do serviço

No projeto, o serviço será desconectado a cada meia hora a uma hora, então a detecção de pulsação é adicionada e a operação de reconexão é a
seguinte, ISignalingadicione emOnHeartBeatHandler

using Unity.WebRTC;

namespace Unity.RenderStreaming.Signaling
{
    
    
    public delegate void OnStartHandler(ISignaling signaling);
    public delegate void OnConnectHandler(ISignaling signaling, string connectionId, bool polite);
    public delegate void OnDisconnectHandler(ISignaling signaling, string connectionId);
    public delegate void OnOfferHandler(ISignaling signaling, DescData e);
    public delegate void OnAnswerHandler(ISignaling signaling, DescData e);
    public delegate void OnIceCandidateHandler(ISignaling signaling, CandidateData e);
    // add
    public delegate void OnHeartBeatHandler(ISignaling signaling);

    public interface ISignaling
    {
    
    
        void Start();
        void Stop();

        event OnStartHandler OnStart;
        event OnConnectHandler OnCreateConnection;
        event OnDisconnectHandler OnDestroyConnection;
        event OnOfferHandler OnOffer;
        event OnAnswerHandler OnAnswer;
        event OnIceCandidateHandler OnIceCandidate;
        // add
        event OnHeartBeatHandler OnHeartBeat;

        string Url {
    
     get; }

        float Interval {
    
     get; }

        void OpenConnection(string connectionId);
        void CloseConnection(string connectionId);
        void SendOffer(string connectionId, RTCSessionDescription offer);
        void SendAnswer(string connectionId, RTCSessionDescription answer);
        void SendCandidate(string connectionId, RTCIceCandidate candidate);
        // add
        void SendHeartBeat();
    }
}

Modifique
insira a descrição da imagem aqui
a função SendHeartBeat no relatório de erros WebSocketSignaling e adicione o seguinte conteúdo

public void SendHeartBeat()
{
    
    
   this.WSSend($"{
     
     {\"type\":\"heart\"}}");
}

insira a descrição da imagem aqui

Crie RenderStreamingManagerum script, o código é o seguinte

using System.Collections;
using System.Threading;
using Unity.RenderStreaming;
using Unity.RenderStreaming.Signaling;
using UnityEngine;

public class RenderStreamingManager : MonoBehaviour
{
    
    
    private RenderStreaming _renderStreaming;
    private VideoStreamSender _videoStreamSender;
    private ISignaling _signaling;
    private InputReceiver _inputReceiver;
    
    // heartbeat check
    private Coroutine _heartBeatCoroutine;
    private bool _isReceiveHeart;
    private float _heartBeatInterval;

    private void Awake()
    {
    
    
        // websocket
        _signaling =  new WebSocketSignaling($"{
      
      "ws"}://{
      
      "192.0.0.0"}", 5, SynchronizationContext.Current);
        
        if (_signaling != null)
        {
    
    
            _renderStreaming = transform.GetComponent<RenderStreaming>();
            _videoStreamSender = transform.GetComponent<VideoStreamSender>();
            _inputReceiver = transform.GetComponent<InputReceiver>();
            
            _renderStreaming.Run(_signaling);
            
            // heart beat
            _signaling.OnStart += OnWebSocketStart;
            _signaling.OnHeartBeat += OnHeatBeat;
        }
    }

    #region HeartBeat
    private void OnWebSocketStart(ISignaling signaling)
    {
    
    
        StartHeartCheck();
    }

    private void OnHeatBeat(ISignaling signaling)
    {
    
    
        _isReceiveHeart = true;
    }
    
    private void StartHeartCheck()
    {
    
    
        _isReceiveHeart = false;
        _signaling.SendHeartBeat();
        _heartBeatCoroutine = StartCoroutine(HeartBeatCheck());
    }
    
    private IEnumerator HeartBeatCheck()
    {
    
    
        yield return new WaitForSeconds(5);
        if (!_isReceiveHeart)
        {
    
    
            // not receive msg
            Reconnect();   
        }
        else
        {
    
    
            StartHeartCheck();
        }
    }

    private void Reconnect()
    {
    
    
        StartCoroutine(ReconnectDelay());
    }

    private IEnumerator ReconnectDelay()
    {
    
    
        _signaling.Stop();
        yield return new WaitForSeconds(1);
        _signaling.Start();
    }
    #endregion
}

Lembre-se de fechar RenderStreaming, localizar e RunOnAwake
insira a descrição da imagem aqui
WebServeradicionar o seguinte conteúdo Reconstruir o serviço e iniciar o servidor, para que o Unity possa enviar e receber mensagens de heartbeat com o servidor por meio do WebSocketwebsocket.tswebsockethandler.ts
insira a descrição da imagem aqui
insira a descrição da imagem aqui

insira a descrição da imagem aqui

6. Obtenha se há uma conexão de usuário bem-sucedida

RenderStreamingManagerVincular eventos em

private void Awake()
{
    
    
	// connect & disconnect
    _inputReceiver.OnStartedChannel += OnStartChannel;
    _inputReceiver.OnStoppedChannel += OnStopChannel;
}
private void OnStartChannel(string connectionid)
{
    
    
        
}
private void OnStopChannel(string connectionid)
{
    
    
        
}

Como fazer iOS e Android

1. Consulte a cena do Receptor na Amostra

insira a descrição da imagem aqui

2. Personalize o conteúdo da cena do receptor

Crie um objeto como mostrado na figura, adicione RenderStreaming SingleConnection VideoStreamReceiver InputSendercomponentes
AudioStreamReceiverrelacionados ao som, adicione
insira a descrição da imagem aqui
um novo Canvas de acordo com suas necessidades, crie um RawImage e use-o como um suporte para receber
insira a descrição da imagem aqui
conteúdo relacionado ao áudio de textura, de acordo com a configuração na amostra , não precisa de conteúdo relacionado a som pode ser ignorado
insira a descrição da imagem aqui

3. Crie o script de gerenciamento

Obtenha componentes e eventos de ligação em Awake e
chame StartConnect para iniciar a conexão com o websocket. Após a conexão ser bem-sucedida, inicie a conexão webrtc e, em seguida, o evento OnUpdateReceiveTexture vinculado a VideoStreamReceiver atualiza a imagem em RawImage.
No OnStartedChannel, são adicionadas as informações de resolução do dispositivo atual, e a estrutura da mensagem pode ser personalizada.Eu criei uma ScreenMessage aqui, adicionei informações de largura e altura e enviei para o cliente.
O roteiro é o seguinte:
insira a descrição da imagem aqui

using System;
using System.Threading;
using Unity.RenderStreaming;
using Unity.RenderStreaming.Signaling;
using UnityEngine;
using UnityEngine.UI;

public class RenderStreamingReceiverManager : MonoSingleton<RenderStreamingReceiverManager>
{
    
    
    private RenderStreaming _renderStreaming;
    private VideoStreamReceiver _videoStreamReceiver;
    private AudioStreamReceiver _audioStreamReceiver;
    private InputSender _inputSender;
    private SingleConnection _connection;

    [SerializeField] private RawImage remoteVideoImage;
    [SerializeField] private AudioSource remoteAudioSource;

    private ISignaling _signaling;
    private string _connectionId;

    private void Awake()
    {
    
    
        // Get Component
        _renderStreaming = transform.GetComponent<RenderStreaming>();
        _videoStreamReceiver = transform.GetComponent<VideoStreamReceiver>();
        _inputSender = transform.GetComponent<InputSender>();
        _connection = transform.GetComponent<SingleConnection>();

        // Connect DisConnect
        _inputSender.OnStartedChannel += OnStartedChannel;
        _inputSender.OnStoppedChannel += OnStopChannel;

        _videoStreamReceiver.OnUpdateReceiveTexture += OnUpdateReceiveTexture;

        _audioStreamReceiver = transform.GetComponent<AudioStreamReceiver>();
        if (_audioStreamReceiver)
        {
    
    
            _audioStreamReceiver.OnUpdateReceiveAudioSource += source =>
            {
    
    
                source.loop = true;
                source.Play();
            };
        }
    }
	// 外部调用Start	
    public void StartConnect()
    {
    
    
        _signaling = new WebSocketSignaling(
            $"{
      
      "ws"}://172.0.0.1:80",
            5, SynchronizationContext.Current);
        _signaling.OnStart += OnWebSocketStart;
        _renderStreaming.Run(_signaling);
    }
	// 外部调用Stop
    public void StopConnect()
    {
    
    
        StopRenderStreaming();
        _signaling.OnStart -= OnWebSocketStart;
        _renderStreaming.Stop();
    }

    private void OnWebSocketStart(ISignaling signaling)
    {
    
    
        StartRenderStreaming();
    }

    private void StartRenderStreaming()
    {
    
    
        if (string.IsNullOrEmpty(_connectionId))
        {
    
    
            _connectionId = Guid.NewGuid().ToString("N");
        }

        if (_audioStreamReceiver)
        {
    
    
            _audioStreamReceiver.targetAudioSource = remoteAudioSource;
        }

        _connection.CreateConnection(_connectionId);
    }

    private void StopRenderStreaming()
    {
    
    
        _connection.DeleteConnection(_connectionId);
        _connectionId = String.Empty;
    }

    void OnUpdateReceiveTexture(Texture texture)
    {
    
    
        remoteVideoImage.texture = texture;
        SetInputChange();
    }

    void OnStartedChannel(string connectionId)
    {
    
    
        Debug.Log("连接成功:" + connectionId);
        // 发送当前设备的分辨率到Client
        SendScreenToClient();
        SetInputChange();
    }

    private void OnStopChannel(string connectionId)
    {
    
    
        Debug.Log("断开连接:" + connectionId);
    }

    void SetInputChange()
    {
    
    
        if (!_inputSender.IsConnected || remoteVideoImage.texture == null)
            return;
        // correct pointer position
        Vector3[] corners = new Vector3[4];
        remoteVideoImage.rectTransform.GetWorldCorners(corners);
        Camera camera = remoteVideoImage.canvas.worldCamera;
        var corner0 = RectTransformUtility.WorldToScreenPoint(camera, corners[0]);
        var corner2 = RectTransformUtility.WorldToScreenPoint(camera, corners[2]);
        var region = new Rect(
            corner0.x,
            corner0.y,
            corner2.x - corner0.x,
            corner2.y - corner0.y
        );
        var size = new Vector2Int(remoteVideoImage.texture.width, remoteVideoImage.texture.height);
        _inputSender.SetInputRange(region, size);
        _inputSender.EnableInputPositionCorrection(true);
    }

    private void SendScreenToClient()
    {
    
    
        ScreenMessage screenMessage = new ScreenMessage(MessageType.Screen, Screen.width, Screen.height);
        string msg = JsonUtility.ToJson(screenMessage);
        SendMsg(msg);
    }

    private void SendMsg(string msg)
    {
    
    
        _inputSender.Channel.Send(msg);
    }
}

A mensagem define a estrutura, escreva de acordo com suas próprias preferências

    public enum MessageType
    {
    
    
        Screen
    }

    public class RenderStreamingMessage
    {
    
    
        public MessageType MessageType;
    }

    public class ScreenMessage : RenderStreamingMessage
    {
    
    
        public int Width;
        public int Height;
    
        public ScreenMessage(MessageType messageType, int width, int height)
        {
    
    
            MessageType = messageType;
            Width = width;
            Height = height;
        }
    }   

4. Processamento adaptativo de tela após o cliente receber a ScreenMessage

Depois de receber a mensagem, analise para obter a largura e a altura e calcule a resolução apropriada de acordo com a resolução do dispositivo móvel.
Use _videoStreamSender.SetTextureSize para modificar a resolução de saída.
Use _inputReceiver.SetInputRange e _inputReceiver.SetEnableInputPositionCorrection(true) para corrigir a resolução. A modificação da resolução no lado da web é consistente com isso.

    private void OnMessage(byte[] bytes)
    {
    
    
        string msg = System.Text.Encoding.Default.GetString(bytes);
        if (string.IsNullOrEmpty(msg) || !msg.Contains("MessageType"))
        {
    
    
            return;
        }

        RenderStreamingMessage messageObject = JsonUtility.FromJson<RenderStreamingMessage>(msg);
        if (messageObject == null)
        {
    
    
            return;
        }

        switch (messageObject.MessageType)
        {
    
    
            case MessageType.Screen:
                ScreenMessage screenMessage = JsonUtility.FromJson<ScreenMessage>(msg);
                ResetOutputScreen(screenMessage);
                break;
            default:
                break;
        }
    }

    private void ResetOutputScreen(ScreenMessage screenMessage)
    {
    
    
        int width = screenMessage.Width;
        int height = screenMessage.Height;
        float targetWidth, targetHeight;

        int configWidth = 1920;
        int configHeight = 1080;
        float configRate = (float) configWidth / configHeight;
        float curRate = (float) width / height;
        if (curRate > configRate)
        {
    
    
            targetWidth = configWidth;
            targetHeight = targetWidth / curRate;
        }
        else
        {
    
    
            targetHeight = configHeight;
            targetWidth = targetHeight * curRate;
        }

        _videoStreamSender.SetTextureSize(new Vector2Int((int) targetWidth, (int) targetHeight));

        // 这一步是分辨率偏移修正的关键代码
        _inputReceiver.SetInputRange(
            new Vector2Int((int) _videoStreamSender.width, (int) _videoStreamSender.height),
            new Rect(0, 0, Screen.width, Screen.height));
        _inputReceiver.SetEnableInputPositionCorrection(true);
    }

5. Configurações do projeto antes de publicar

Alterações conforme solicitado nos documentos do WebRTC
insira a descrição da imagem aqui

6. Teste de liberação

insira a descrição da imagem aqui

plano de atualização

1. Mac e iOS liberam compartilhamento de bugs

Acho que você gosta

Origin blog.csdn.net/qq_22955617/article/details/127052164
Recomendado
Clasificación