Unity Render Streaming 클라우드 렌더링 엔터프라이즈 프로젝트 솔루션

Unity 렌더 스트리밍

머리말

원본 링크
UnityRenderStreaming 공식 문서
Unity: 2021.3.8f1c1
RenderStreaming: 3.1.0-exp.4(시험판)
RenderStreaming WebServer: 3.1.0-exp.3

결과 보여줘

비디오 데모
여기에 이미지 설명 삽입

외부 네트워크 비디오 데모
여기에 이미지 설명 삽입

열린 장면

테스트 시나리오로 HDRP 샘플 템플릿 사용
여기에 이미지 설명 삽입

버전 선택

이 RenderStreamingPackage는3.1.0-exp.4, 그리고 공식 버전은 없지만 exp.4는 exp.3 버전에 비해 비디오 스트림 인코딩, 프레임 속도, 비트 전송률, 줌 비율 및 기타 설정을 개방했으며 매우 안정적으로 사용하기 때문에 편리합니다. 자신의 프로젝트 요구에 따라 조정합니다.
웹서버 사용3.1.0-exp.3, 서버의 exp.4 버전으로 인해 웹 페이지 접근 경로 확인에 문제가 있습니다.
Git 주소: UnityRenderStreaming
여기에 이미지 설명 삽입
여기에 이미지 설명 삽입

웹 서버

1. 서버 다운로드, Node.js 설치

자신의 플랫폼에 따라 서버를 선택하십시오. Node.js를 설치하여 다운로드
하고 node -v npm -v설치 성공 여부를 확인하는 데 사용해야 합니다.
여기에 이미지 설명 삽입

2. 서버 시작

Windows 시작 방법은 다음과 같습니다.(기타 플랫폼 시작 방법은 공식 문서 참조 )
webserver.exe를 찾아 주소 표시줄에 cmd를 입력하고 Enter 키를 누릅니다.
여기에 이미지 설명 삽입

입력 .\webserver.exe -w, WebSocket으로 시작
여기에 이미지 설명 삽입

브라우저를 열고 로컬 IP를 입력하십시오. 다음 그림은 WebSocket을 시작한 후의 내용입니다.
여기에 이미지 설명 삽입

Unity 프로젝트 설정

1. 렌더 스트리밍 설치

소스코드 압축 해제 후 com.unity.renderstreaming파일을 복사하여 샘플 프로젝트의 Packages 하위에 넣고 새 폴더를 생성합니다. (기호에 따라 보관)
여기에 이미지 설명 삽입
여기에 이미지 설명 삽입

PackageManager를 열고
여기에 이미지 설명 삽입
+를 클릭하고 Add package from disk
여기에 이미지 설명 삽입
지금 파일을 찾기 위해 선택하고 package.json열고
여기에 이미지 설명 삽입
다음과 같이 엽니다.
여기에 이미지 설명 삽입

2. WebRTC 설치

Add package by name
여기에 이미지 설명 삽입
입력을 선택하고 com.unity.webrtc추가를 클릭하여
여기에 이미지 설명 삽입
다음과 같이 설치합니다.
여기에 이미지 설명 삽입

3. 렌더링 스트리밍 설정

빈 개체를 만들고 이름을 RenderStreaming으로 지정
여기에 이미지 설명 삽입
하고 RenderStreaming, BroadcastVideoStreamSender구성 요소를 추가합니다.
다음과 같이 매개 변수를 수정합니다.
여기에 이미지 설명 삽입

4. 오디오 전송(필요에 따라 추가)

AudioStreamSender위의 구성 요소를 추가하십시오 AudioListener. 이 구성 요소는 개체 구성 요소에 있어야 합니다 . 구성 요소를
여기에 이미지 설명 삽입
Broadcast추가해야 합니다.AudioStreamSender
여기에 이미지 설명 삽입

5. Unity 테스트 시작

선택 의 효과는 다음과 같습니다. ReceiverSample
여기에 이미지 설명 삽입
필요에 따라 VideoStreamSender매개변수를 조정할 수 있습니다.
여기에 이미지 설명 삽입
여기에 이미지 설명 삽입

상호 작용하다

1. 기본 인터랙티브 프로젝트 설정

InputSystem을 설치
하고 다음 설정 중 일부는 다음을 목표로 합니다.Unity2021.2상위 버전, 하위 버전 참조 링크
(이 HDRP 예시에서는 기본적으로 InputSystem이 사용되었습니다.)
여기에 이미지 설명 삽입
팝업 창이 나타나면 다음을 선택합니다., 새 입력 시스템 사용에 동의하거나
여기에 이미지 설명 삽입
ProjectSettings/Player/OtherSettings/ActiveInputHanding에서 신규 또는 둘 다
여기에 이미지 설명 삽입
백그라운드에서 실행을 선택하여(2021.2)
ProjectSettings/Player/Resolution and Presentation/Run in background
여기에 이미지 설명 삽입
입력 시스템 패키지 설정 수정(2021.2)을 엽니다.
여기에 이미지 설명 삽입

2. 장면 상호 작용 설정

공식 문서 참조 구성
요소 추가 InputReceiverBroadcast추가
여기에 이미지 설명 삽입

3. 키보드 및 마우스 상호 작용

InputActions 생성 후 열기, 작업: Create/InputActions
여기에 이미지 설명 삽입
자신의 프로젝트 요구 사항에 따라 작업
여기에 이미지 설명 삽입
구성 구성된 InputActions 파일을 끌어다 놓고 InputReceiver/Actions이벤트를 확장하면 구성된 작업에 해당하는 이벤트를 볼 수 있으며 필요에 따라 바인딩할 수 있습니다.
여기에 이미지 설명 삽입

4. UI 상호작용

EventSystem은 그것과 일치 InputSystemUIInputModule
여기에 이미지 설명 삽입
하도록 디스플레이 해상도를 사용합니다 . 그렇지 않으면 인식 포인트가 이동됩니다.VideoStreamSenderStreamingSize
여기에 이미지 설명 삽입
여기에 이미지 설명 삽입

엑스트라넷 서버 배포

대부분의 WebRTC 응용 프로그램의 경우 클라이언트 간에 직접 소켓이 불가능하기 때문에 서버는 피어 간에 트래픽을 릴레이해야 합니다(응용 프로그램이 동일한 로컬 네트워크에 있지 않는 한). 이 문제에 대한 일반적인 해결책은 TURN 서버를 사용하는 것입니다 . 이 용어는 네트워크 트래픽을 릴레이하기 위한 프로토콜인 릴레이 NAT를 사용한 순회를 나타냅니다. Unity 문서의 TURN 서버 설정을
참조하십시오.

TURN 서버가 사용하는 포트는 public이어야 하며 최대값과 최소값을 설정할 수 있습니다.

규약 포트
TCP 32355-65535, 3478-3479
UDP 32355-65535, 3478-3479

웹 사이드에서 config.js파일 변경config.iceServers

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

RenderStreamingUnity에서 구성 요소 수정Ice Server
사진 설명을 추가해주세요

커스텀 웹서버

다음은 자신만의 WebServer를 만드는 방법입니다. 자세한 내용은 공식 문서를 참조하세요.
1. exp.3 소스 코드 다운로드
여기에 이미지 설명 삽입
2. 압축 해제 후 WebApp 찾기 3.
여기에 이미지 설명 삽입
주소 표시줄에 cmd 입력
여기에 이미지 설명 삽입
4. 종속 항목 입력 npm install또는npm i
여기에 이미지 설명 삽입
설치 설치가 너무 느리거나 시간 초과로 실패하는 경우 먼저 입력하여
npm config set registry https://registry.npm.taobao.org
npm 설치 이미지 소스를 국내 이미지 소스로 대체 있습니다 .
여기에 이미지 설명 삽입
npm config set legacy-peer-deps truenpm installnpm i
여기에 이미지 설명 삽입

5. Build Server 입력 npm run build
여기에 이미지 설명 삽입
6. Start Server 입력 6. Start Server 입력npm run start -- -w
여기에 이미지 설명 삽입
아래 그림과 같이 시작이 비정상인 경우 npm run dev -- -wStart를 이용하여
여기에 이미지 설명 삽입
다음과 같이 시작합니다. 나, 고마워.
여기에 이미지 설명 삽입
7. 시작 바로가기 만들기
향후 빠른 시작을 위해 다음과 같은 파일을 만들 수 있습니다.
여기에 이미지 설명 삽입
8. 압축하고npm run pack 진행이 완료될 때까지 기다린 다음 위와 같이
exe 시작 방법에 압축
여기에 이미지 설명 삽입
여기에 이미지 설명 삽입
.\webserver.exe -w
여기에 이미지 설명 삽입

9. 필요에 따라 웹 파일 수정
여기에 이미지 설명 삽입

Web과 Unity는 서로에게 맞춤 메시지를 보냅니다.

메시지를 보낼 때 WebRTC사용 RTCDataChannel하는 기능 Send, 메시지를 받을 때 사용하는 기능OnMessage

1. Unity는 웹에 메시지를 보냅니다.

Unity 프로젝트에서 생성한 스크립트는 다음과 inputReceiver같습니다 Channel.Send

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


여기에 이미지 설명 삽입
다음과 같이 수신할 프로젝트 웹에 추가하십시오. 파일에서 객체를
찾아 수신된 정보를 사용하십시오 . 수신된 메시지의 내용은 다음과 같으며 문자열은 데이터에 있습니다.receiver.jsinputSenderChannelonmessage
여기에 이미지 설명 삽입

여기에 이미지 설명 삽입

2. 웹은 Unity에 메시지를 보냅니다.

보내기 기능을 사용하여 웹에서 메시지 보내기

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

Unity의 OnMessage에서는 Receiver.cs웹에서 보낸 메시지를 RTCDataChannel을 통해 수신합니다.
여기에 이미지 설명 삽입

엔터프라이즈 프로젝트가 적용되는 방법

1. 명확하고 원활한 외부 네트워크 액세스 중 선택

서버 대역폭이 허용한다는 전제하에 다음과 같이 전송 품질을 최대한 향상시킵니다. 이는 프로젝트의 내 설정입니다.
여기에 이미지 설명 삽입

자신의 대역폭에 따라 조정할 수 있습니다 DepathBuffer,StreamingSize,Framerate,Bitrate,ScaleResolution.
또한 VideoStreamSender 구성 요소를 얻고 런타임 중에 해당 매개 변수를 수정하여 출시 후 테스트를 용이하게 할 수 있습니다.

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. Unity의 버튼 동작을 대체하는 웹 버튼

현재 해상도 변경 제한으로 인해 Unity 버튼을 올바르게 클릭할 수 없는 경우가 많기 때문에 웹 학생은 해당 버튼을 만들고 웹을 통해 Unity에 메시지를 보내 해당 버튼 작업에 응답합니다.
내 쪽은 모든 버튼에 대한 id를 구성하고, 웹은 버튼 id를 보내고, Unity는 그것을 받은 후 구성 테이블을 순회하고 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. 해상도 동기화, 아래 iOS 및 Android의 해상도 동기화 방법 참조

서로 다른 장치 해상도를 일치시키고, 웹을 통해 현재 장치 해상도를 얻고, 연결이 성공한 후 Unity에 장치 너비 및 높이 메시지를 보내고, 웹 장치가 완전히 표시되도록 Unity에서 출력 해상도를 재설정합니다.

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

4. 휴대폰에서 기본 세로화면으로 접속하여 가로화면 표시 시 주의사항

휴대폰의 세로 화면 표시 화면이 너무 작기 때문에 일반적으로 세로 화면 상태에서 가로 화면 내용을 표시합니다.따라서:
1. 이전 지점에서 언급한 해상도를 설정할 때 장치가 있는지 여부에 주의해야 합니다. 웹에서는 가로 화면 또는 세로 화면으로
2. 프로젝트 에서 슬라이딩 동작이 있을 경우 가로 화면과 세로 화면에 따라 반전 동작에 주의가 필요합니다.

5. Unity 측이 서비스에서 연결 해제되었는지 감지

프로젝트에서 서비스는 30분~1시간 간격으로 끊기므로 하트비트 감지 기능을 추가하고 재접속 동작은
다음과 같이 ISignaling추가한다 .OnHeartBeatHandler

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

오류 보고 WebSocketSignaling에서 SendHeartBeat 기능을 수정하고
여기에 이미지 설명 삽입
다음 콘텐츠를 추가합니다.

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

여기에 이미지 설명 삽입

스크립트를 생성합니다 RenderStreamingManager. 코드는 다음과 같습니다.

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
}

Unity가 WebSocket을 통해 서버와 하트비트 메시지를 보내고 받을 수 있도록 다음 콘텐츠를 닫고 찾아 추가해야 합니다 RenderStreaming. RunOnAwake
여기에 이미지 설명 삽입
WebServer서비스 를 다시 빌드하고 서버를 시작합니다 websocket.ts.websockethandler.ts
여기에 이미지 설명 삽입
여기에 이미지 설명 삽입

여기에 이미지 설명 삽입

6. 사용자 연결 성공 여부 확인

RenderStreamingManager이벤트 바인드

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

iOS와 Android를 만드는 방법

1. 샘플의 리시버 장면 참고

여기에 이미지 설명 삽입

2. 수신기 장면 콘텐츠 사용자 지정

샘플의 구성에 따라 그림과 같이 객체를 생성하고, 사운드 관련 RenderStreaming SingleConnection VideoStreamReceiver InputSender컴포넌트를 추가하고, 필요에 따라 새로운 Canvas를 추가하고, RawImage를 생성하여 Texture Audio 관련 콘텐츠를 수신하기 위한 캐리어로 사용합니다. , 필요하지 않은 소리 관련 콘텐츠는 무시할 수 있습니다.
AudioStreamReceiver
여기에 이미지 설명 삽입

여기에 이미지 설명 삽입

여기에 이미지 설명 삽입

3. 관리 스크립트 생성

Awake에서 구성 요소 및 바인딩 이벤트를 가져오고
StartConnect를 호출하여 websocket에 연결을 시작합니다. 연결이 성공한 후 webrtc 연결을 시작하면 VideoStreamReceiver에 바인딩된 OnUpdateReceiveTexture 이벤트가 RawImage의 그림을 업데이트합니다.
OnStartedChannel에는 현재 디바이스 해상도 정보가 추가되고 메시지 구조를 커스터마이즈할 수 있는데, 여기서 ScreenMessage를 생성하고 너비와 높이 정보를 추가하여 클라이언트에 전송했습니다.
스크립트는 다음과 같습니다.
여기에 이미지 설명 삽입

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

메시지는 구조를 정의하고 자신의 기본 설정에 따라 작성합니다.

    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. 클라이언트가 ScreenMessage를 수신한 후 화면 적응 처리

메시지를 받은 후 파싱하여 너비와 높이를 가져오고 모바일 장치의 해상도에 따라 적절한 해상도를 계산합니다. _videoStreamSender.SetTextureSize를 사용하여 출력
해상도를 수정합니다.
웹 측의 해상도 수정은 이와 일치합니다.

    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. 게시 전 프로젝트 설정

WebRTC 문서 에서 요청한 대로 변경
여기에 이미지 설명 삽입

6. 출시 테스트

여기에 이미지 설명 삽입

업데이트 계획

1. Mac 및 iOS 릴리스 버그 공유

Supongo que te gusta

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