Unity Render Streaming solution de projet d'entreprise de rendu cloud

Streaming de rendu de l'unité

Annuaire d'articles

avant-propos

Lien d'origine
Document officiel UnityRenderStreaming
Unity : 2021.3.8f1c1
RenderStreaming : 3.1.0-exp.4 (pré-version)
RenderStreaming WebServer : 3.1.0-exp.3

Montrer les résultats

démo vidéo
insérez la description de l'image ici

Démonstration vidéo réseau externe
insérez la description de l'image ici

scène ouverte

Utilisez l'exemple de modèle HDRP comme scénario de test
insérez la description de l'image ici

sélection des versions

Ce RenderStreamingPackage utilise3.1.0-exp.4, et il n'y a pas de version officielle, mais exp.4 a ouvert l'encodage du flux vidéo, la fréquence d'images, le débit binaire, le rapport de zoom et d'autres paramètres par rapport à la version exp.3, et il est également très stable à utiliser, donc c'est pratique à ajuster en fonction des besoins de votre propre projet.
WebServer utilise3.1.0-exp.3, en raison de la version exp.4 de Server, il y a un problème avec la vérification du chemin d'accès à la page Web.
Adresse Git : UnityRenderStreaming
insérez la description de l'image ici
insérez la description de l'image ici

serveur Web

1. Téléchargement du serveur, installation de Node.js

Choisissez le serveur en fonction de votre propre plate-forme, vous devez installer Node.js à télécharger
et à utiliser node -v npm -vpour vérifier si l'installation est réussie
insérez la description de l'image ici

2. Démarrage du serveur

La méthode de démarrage de Windows est la suivante (reportez-vous à la documentation officielle pour les autres méthodes de démarrage de la plate-forme )
Recherchez webserver.exe, entrez cmd dans la barre d'adresse et appuyez sur Entrée
insérez la description de l'image ici

Entrée .\webserver.exe -w, commencez par WebSocket
insérez la description de l'image ici

Ouvrez le navigateur, entrez l'adresse IP locale, la figure suivante est le contenu après avoir démarré avec WebSocket
insérez la description de l'image ici

Paramètres du projet Unity

1. Installez le rendu en continu

Une fois le code source décompressé, copiez com.unity.renderstreamingle fichier et placez-le sous les packages de l'exemple de projet, puis créez un nouveau dossier. (Stocker selon votre préférence)
insérez la description de l'image ici
insérez la description de l'image ici

Ouvrez PackageManager
insérez la description de l'image ici
et cliquez sur +, sélectionnez Add package from disk
insérez la description de l'image ici
pour trouver le fichier tout à l'heure package.json, ouvrez-le
insérez la description de l'image ici
et ouvrez-le comme suit
insérez la description de l'image ici

2. Installez WebRTC

Sélectionnez Add package by name
insérez la description de l'image ici
input com.unity.webrtc, cliquez sur Add
insérez la description de l'image ici
pour installer comme suit :
insérez la description de l'image ici

3. Rendre les paramètres de streaming

Créez un objet vide, nommez-le RenderStreaming
insérez la description de l'image ici
et ajoutez les composants RenderStreaming, Broadcastet Modifiez les paramètres comme suit :VideoStreamSender

insérez la description de l'image ici

4. Transmission audio (ajouter selon vos besoins)

Ajoutez AudioStreamSenderle composant ci-dessus AudioListener, ce composant doit être dans un
insérez la description de l'image ici
Broadcastcomposant objet pensez à ajouter AudioStreamSenderle composant
insérez la description de l'image ici

5. Unity lance le test

L'effet de la sélection est le suivant, vous pouvez ajuster les paramètres en ReceiverSample
insérez la description de l'image ici
fonction de vos propres besoinsVideoStreamSender
insérez la description de l'image ici
insérez la description de l'image ici

interagir

1. Paramètres de base du projet interactif

Installez InputSystem
et certains des paramètres suivants visent àUnité2021.2Version ci-dessus, lien de référence de version basse
(InputSystem a été utilisé par défaut dans cet exemple HDRP)
insérez la description de l'image ici
Après l'apparition de la fenêtre contextuelle, sélectionnezOui, acceptez d'utiliser New Input Sytem ou sélectionnez New ou Both Run In Background
insérez la description de l'image ici
dans ProjectSettings/Player/OtherSettings/ActiveInputHanding pour ouvrir (2021.2) la modification des paramètres du package du système d'entrée (2021.2)
insérez la description de l'image ici

ProjectSettings/Player/Resolution and Presentation/Run in background
insérez la description de l'image ici

insérez la description de l'image ici

2. Paramètres d'interaction avec la scène

Référence de la documentation officielle
Ajouter InputReceiverdes composants et ajouter Broadcastà
insérez la description de l'image ici

3. Interaction clavier et souris

Ouvrir après avoir créé InputActions, opération : Create/InputActions
insérez la description de l'image ici
Configurer les actions en fonction des exigences de votre propre projet
insérez la description de l'image ici
Faites glisser le fichier InputActions configuré dedans InputReceiver/Actions, développez Événements, vous pouvez voir les événements correspondant aux actions configurées et les lier en fonction de vos besoins
insérez la description de l'image ici

4. Interaction de l'interface utilisateur

EventSystem utilise InputSystemUIInputModule
insérez la description de l'image ici
la résolution d'affichage pour être cohérent VideoStreamSenderavec cela StreamingSize, sinon le point de reconnaissance sera décalé
insérez la description de l'image ici
insérez la description de l'image ici

Déploiement du serveur extranet

Pour la plupart des applications WebRTC, le serveur doit relayer le trafic entre pairs, car les sockets directs ne sont généralement pas possibles entre les clients (sauf si les applications se trouvent sur le même réseau local). Une solution courante à ce problème consiste à utiliser un serveur TURN . Le terme désigne la traversée à l'aide de relais NAT, un protocole de relais du trafic réseau.
Reportez-vous aux paramètres du serveur TURN dans la documentation Unity

Le port utilisé par le serveur TURN doit être public et les valeurs maximale et minimale peuvent être définies

protocole port
TCP 32355-65535, 3478-3479
UDP 32355-65535, 3478-3479

config.jsModifier le fichier dans le côté Webconfig.iceServers

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

Modification RenderStreamingdes composants dans UnityIce Server
Veuillez ajouter une description de l'image

Serveur Web personnalisé

Voici comment créer votre propre serveur Web, consultez la documentation officielle pour plus de détails
1. Téléchargez le code source de exp.3
insérez la description de l'image ici
2. Trouvez la WebApp après décompression 3.
insérez la description de l'image ici
Entrez cmd dans la barre d'adresse
insérez la description de l'image ici
4. Saisissez npm installou npm iinstallez les dépendances
insérez la description de l'image ici
Si le l'installation est trop lente ou échoue en raison d'un délai d'attente, vous pouvez d'abord l'entrer
npm config set registry https://registry.npm.taobao.org
pour remplacer la source de l'image d'installation npm par une source domestique.
insérez la description de l'image ici
Si les erreurs suivantes se produisent, vous pouvez l'entrer npm config set legacy-peer-deps true, puis l'entrer à nouveau npm installou npm iinstaller les dépendances **
insérez la description de l'image ici

5. Build Server, entrez npm run build
insérez la description de l'image ici
6. Start Server, entreznpm run start -- -w
insérez la description de l'image ici
Si le démarrage est anormal, comme illustré dans la figure ci-dessous, utilisez npm run dev -- -wDémarrer
insérez la description de l'image ici
pour démarrer comme suit. La raison de la situation ci-dessus n'est pas claire. Si vous en connaissez la raison, veuillez indiquer moi, merci.
insérez la description de l'image ici
7. Créez un raccourci de démarrage.
Afin de faciliter le démarrage rapide à l'avenir, vous pouvez créer les fichiers suivants.
insérez la description de l'image ici
8. Pack,npm run pack
attendez que la progression soit terminée et compressez-le dans une
insérez la description de l'image ici
insérez la description de l'image ici
méthode de démarrage exe comme ci-dessus..\webserver.exe -w
insérez la description de l'image ici

9. Modifiez les fichiers Web selon vos besoins
insérez la description de l'image ici

Web et Unity s'envoient des messages personnalisés

La fonction utilisée WebRTCpour envoyer un message , utilisez la fonction pour recevoir un messageRTCDataChannelSendOnMessage

1. Unity envoie un message au Web

Le script créé dans le projet Unity est le suivant, en utilisant les objets inputReceiverduChannelSend

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");
        }
    }
}

N'oubliez pas de l'ajouter au projet
insérez la description de l'image ici
Web pour recevoir comme suit
Trouvez l'objet receiver.jsdans le fichier et utilisez les informations reçues Le contenu du message reçu est le suivant, la chaîne sera en donnéesinputSenderChannelonmessage
insérez la description de l'image ici

insérez la description de l'image ici

2. Le Web envoie un message à Unity

Utilisez la fonction d'envoi pour envoyer des messages sur le Web

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

Dans OnMessage dans Unity Receiver.cs, le message envoyé par le Web est reçu via RTCDataChannel
insérez la description de l'image ici

Comment les projets d'entreprise sont appliqués

1. Le choix entre un accès réseau externe clair et fluide

En partant du principe que la bande passante du serveur le permet, améliorez la qualité de transmission autant que possible, comme suit, quels sont mes paramètres dans le projet
insérez la description de l'image ici

Vous pouvez l'ajuster en fonction de votre propre bande passante DepathBuffer,StreamingSize,Framerate,Bitrate,ScaleResolution.
Vous pouvez également obtenir le composant VideoStreamSender et modifier les paramètres correspondants pendant l'exécution pour faciliter les tests après la publication.

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. Bouton Web pour remplacer le fonctionnement du bouton de Unity

En raison de la limitation actuelle des changements de résolution, il est souvent impossible de cliquer correctement sur les boutons Unity. Les étudiants Web créent donc les boutons correspondants et envoient des messages à Unity via le Web pour répondre aux opérations des boutons correspondants.
Mon côté est de configurer l'identifiant de tous les boutons, le Web envoie l'identifiant du bouton, Unity parcourt la table de configuration après l'avoir reçu et effectue 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. Synchronisation de la résolution, reportez-vous à la méthode de synchronisation de la résolution dans iOS et Android ci-dessous

Faites correspondre différentes résolutions de périphérique, obtenez la résolution actuelle du périphérique via le Web et envoyez un message de largeur et de hauteur de périphérique à Unity une fois la connexion établie, puis réinitialisez la résolution de sortie dans Unity pour que le périphérique Web reste entièrement affiché.

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

4. Précautions lors de l'accès à l'écran vertical par défaut sur le téléphone mobile et de l'affichage de l'écran horizontal

Étant donné que l'écran d'affichage vertical du téléphone mobile est trop petit, il affiche généralement le contenu de l'écran horizontal à l'état d'écran vertical. Par conséquent : 1.
Lors du réglage de la résolution mentionnée au point précédent, vous devez faire attention à savoir si l'appareil côté web se trouve un écran horizontal ou un écran vertical
2. Projeter S'il y a une opération de glissement dans , il faut faire attention à inverser l'opération selon les écrans horizontaux et verticaux.

5. Détecter si le côté Unity est déconnecté du service

Dans le projet, le service sera déconnecté toutes les demi-heures à une heure, donc la détection du rythme cardiaque est ajoutée, et l'opération de reconnexion est
la suivante, ISignalingajoutezOnHeartBeatHandler

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();
    }
}

Modifiez
insérez la description de l'image ici
la fonction SendHeartBeat dans le rapport d'erreur WebSocketSignaling et ajoutez le contenu suivant

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

insérez la description de l'image ici

Créez RenderStreamingManagerun script, le code est le suivant

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
}

N'oubliez pas de fermer RenderStreaminget de rechercher et RunOnAwake
insérez la description de l'image ici
WebServerd'ajouter le contenu suivant Reconstruisez le service et démarrez le serveur, afin que Unity puisse envoyer et recevoir des messages de pulsation avec le serveur via WebSocketwebsocket.tswebsockethandler.ts
insérez la description de l'image ici
insérez la description de l'image ici

insérez la description de l'image ici

6. Vérifiez s'il existe une connexion utilisateur réussie

RenderStreamingManagerLier les événements dans

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

Comment faire iOS et Android

1. Reportez-vous à la scène du récepteur dans l'exemple

insérez la description de l'image ici

2. Personnalisez le contenu de la scène du récepteur

Créez un objet comme indiqué sur la figure, ajoutez RenderStreaming SingleConnection VideoStreamReceiver InputSenderdes composants
AudioStreamReceiverliés au son, ajoutez
insérez la description de l'image ici
un nouveau canevas en fonction de vos propres besoins, créez un RawImage et utilisez-le comme support pour recevoir
insérez la description de l'image ici
le contenu lié à Texture Audio, selon la configuration dans l'exemple , n'ont pas besoin de contenu lié au son peut être ignoré
insérez la description de l'image ici

3. Créez le script de gestion

Obtenez des composants et des événements de liaison dans Awake et
appelez StartConnect pour démarrer la connexion au websocket. Une fois la connexion établie, démarrez la connexion webrtc, puis l'événement OnUpdateReceiveTexture lié à VideoStreamReceiver met à jour l'image dans RawImage.
Dans OnStartedChannel, les informations de résolution de l'appareil actuel sont ajoutées et la structure du message peut être personnalisée. J'ai créé un ScreenMessage ici, ajouté des informations sur la largeur et la hauteur et l'ai envoyé au client.
Le script est le suivant :
insérez la description de l'image ici

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);
    }
}

Le message définit la structure, écrivez selon vos propres préférences

    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. Traitement adaptatif de l'écran après que le client a reçu le ScreenMessage

Après avoir reçu le message, analysez pour obtenir la largeur et la hauteur, et calculez la résolution appropriée en fonction de la résolution de l'appareil mobile. Utilisez
_videoStreamSender.SetTextureSize pour modifier la résolution de sortie.
Utilisez _inputReceiver.SetInputRange et _inputReceiver.SetEnableInputPositionCorrection(true) pour corriger La résolution La modification de la résolution sur le côté Web est cohérente avec cela.

    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. Paramètres du projet avant la publication

Modifications demandées dans les documents WebRTC
insérez la description de l'image ici

6. Test de libération

insérez la description de l'image ici

plan de mise à jour

1. Partage de bogues de versions Mac et iOS

Je suppose que tu aimes

Origine blog.csdn.net/qq_22955617/article/details/127052164
conseillé
Classement