最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Unity Sockect實現(xiàn)畫面實時傳輸案例原理解析

 更新時間:2021年08月24日 14:33:38   作者:yq_sprite  
Socket是比較常用的一種通信方式,本文通過案例給大家介紹Unity Sockect實現(xiàn)畫面實時傳輸功能,感興趣的朋友一起看看吧

前言

提示:這里可以添加本文要記錄的大概內(nèi)容:
例如:隨著人工智能的不斷發(fā)展,機器學(xué)習(xí)這門技術(shù)也越來越重要,很多人都開啟了學(xué)習(xí)機器學(xué)習(xí),本文就介紹了機器學(xué)習(xí)的基礎(chǔ)內(nèi)容。

提示:以下是本篇文章正文內(nèi)容,下面案例可供參考

一、Socket通信原理

Socket是比較常用的一種通信方式。有關(guān)介紹可以點擊查看Socket通信原理

二、畫面?zhèn)鬏斣O(shè)計

 1.邏輯設(shè)計圖

邏輯圖

2.Unity服務(wù)端

首先創(chuàng)建一個Unity工程,然后新建Server場景,用于接受數(shù)據(jù),展示畫面。
然后再場景中創(chuàng)建一個RawImage并設(shè)置為全屏。

如圖:

在這里插入圖片描述

然后創(chuàng)建一個腳本,命名為UnityServer,再創(chuàng)建一個UnityServer.cs
在Start函數(shù)中創(chuàng)建Socket服務(wù)器,并開啟一個線程用于接受數(shù)據(jù)。
這里要注意一點,不能在接受數(shù)據(jù)線程中處理數(shù)據(jù),需要在主線程中進(jìn)行處理。
因為Unity主線程里面的資源不允許其他線程進(jìn)行訪問。
在Update函數(shù)中處理數(shù)據(jù),并展示圖片。

UnityServer .cs代碼如下:

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using UnityEngine;
using UnityEngine.UI;

public class UnityServer : MonoBehaviour {

	Socket socket = null;
	Thread thread = null;
	byte[] buffer = null;
	bool receState = true;

	int readTimes = 0;

    public RawImage rawImage;

    private Queue<byte[]> datas;

    void Start () {
		buffer = new byte[1024 * 1024 * 10];

        // 創(chuàng)建服務(wù)器, 以Tcp的方式
		socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
		socket.Connect(IPAddress.Parse("192.168.1.87"), 10002);

        // 開啟一個線程, 用于接受數(shù)據(jù)
		thread = new Thread(new ThreadStart(Receive));
		thread.Start();

        datas = new Queue<byte[]>();
    }

    private void Receive()
    {
        while (thread.ThreadState == ThreadState.Running && socket.Connected)
        {
            // 接受數(shù)據(jù)Buffer count是數(shù)據(jù)的長度
			int count = socket.Receive(buffer);
            if (receState && count > 0)
            {
				receState = false;
                BytesToImage(count, buffer);
            }
        }
    }

	MemoryStream ms = null;
	public void BytesToImage(int count, byte[] bytes)
    {
        try
        {
            ms = new MemoryStream(bytes, 0, count);
            datas.Enqueue(ms.ToArray());    // 將數(shù)據(jù)存儲在一個隊列中,在主線程中解析數(shù)據(jù)。這是一個多線程的處理。

            readTimes++;

            if (readTimes > 5000)
            {
                readTimes = 0;
                GC.Collect(2);  // 達(dá)到一定次數(shù)的時候,開啟GC,釋放內(nèi)存
            }
        }
        catch
        {

        }
        receState = true;
    }

    void Update()
    {
        if (datas.Count > 0)
        {
            // 處理紋理數(shù)據(jù),并顯示
            Texture2D texture2D = new Texture2D(Screen.width, Screen.height);
            texture2D.LoadImage(datas.Dequeue());
            rawImage.texture = texture2D;
        }
    }

    void OnDestroy()
    {
        try
        {
            if (socket != null)
            {
                socket.Shutdown(SocketShutdown.Both);
            }
        }
        catch { }

        try
        {
            if (thread != null)
            {
                thread.Abort();
            }
        }
        catch { }

        datas.Clear();
    }
}

然后在場景中創(chuàng)建一個GameObject,將腳本掛載上,并將創(chuàng)建的RawImage拖拽到Inspector面板上對應(yīng)的位置。

如圖:

在這里插入圖片描述

3.Unity客戶端

然后我們創(chuàng)建一個客戶端工程,創(chuàng)建一個Client場景。
選中Main Camera,用Ctrl+D復(fù)制一個攝像機,放在Main Camera下面。
設(shè)置localPosition 和 localRotation為零。
這個相機的主要作用抓取屏幕渲染紋理。

如圖:

在這里插入圖片描述

然后再創(chuàng)建一個腳本,命名為UnityClient.cs腳本。在Start中開啟Socket,然后開啟一個線程發(fā)送數(shù)據(jù)。
將其掛載在Main Camera上面,并將渲染攝像機拖拽到相應(yīng)的位置。

UnityClient.cs代碼如下:

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using UnityEngine;

public class UnityClient : MonoBehaviour {

	public Camera cam;
	public int port = 10002;

	RenderTexture cameraView = null;

	Socket socket = null;

	Thread thread = null;

	bool success = true;

	Dictionary<string, Client> clients = new Dictionary<string, Client>();

	Vector3 old_position;   // 舊位置
	Quaternion old_rotation;	// 舊旋轉(zhuǎn)

	void Start () {
		cameraView = new RenderTexture(Screen.width, Screen.height, 24);
		cameraView.enableRandomWrite = true;

		cam.targetTexture = cameraView;
		old_position = transform.position;
		old_rotation = transform.rotation;

        // 開啟Socket
		socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
		socket.Bind(new IPEndPoint(IPAddress.Parse("192.168.1.87"), port));
		socket.Listen(100);

        // 開啟一個線程發(fā)送渲染數(shù)據(jù)
		thread = new Thread(new ThreadStart(OnStart));
		thread.Start();
	}

	int isNewAdd = 0;

	void OnStart()
    {
        Debug.Log("Socket創(chuàng)建成功");
        while (thread.ThreadState == ThreadState.Running)
        {
			Socket _socket = socket.Accept();
            if (clients.ContainsKey(_socket.RemoteEndPoint.ToString()))
            {
                try
                {
					clients[_socket.RemoteEndPoint.ToString()].socket.Shutdown(SocketShutdown.Both);
                }
                catch
                {
                }
				clients.Remove(_socket.RemoteEndPoint.ToString());
            }

			Client client = new Client
			{
				socket = _socket
			};

			clients.Add(_socket.RemoteEndPoint.ToString(), client);

			isNewAdd = 1;
        }
    }

	void Update()
    {
        if (success && clients.Count > 0)
        {
			success = false;
            SendTexture();
        }

        if (isNewAdd > 0)
        {
            isNewAdd = 0;
            SendTexture(1);
        }
    }

	void OnGUI()
    {
		GUI.DrawTexture(new Rect(10, 10, 240, 135), cameraView, ScaleMode.StretchToFill);
    }

	void OnApplicationQuit()
    {
        try
        {
			socket.Shutdown(SocketShutdown.Both);
        }
        catch { }

        try
        {
			thread.Abort();
        }
        catch { }
    }

	Texture2D screenShot = null;
	int gc_count = 0;

	void SendTexture(int isInt = 0)
    {
        if ((!old_position.Equals(transform.position) || !old_rotation.Equals(transform.rotation)) || isInt == 1)
        {
            if (null == screenShot)
            {
				screenShot = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
            }

            // 讀取屏幕像素進(jìn)行渲染
			RenderTexture.active = cameraView;
			screenShot.ReadPixels(new Rect(0, 0, cameraView.width, cameraView.height), 0, 0);
			RenderTexture.active = null;
			byte[] bytes = screenShot.EncodeToJPG(100);

            foreach (var val in clients.Values)
            {
                try
                {
					val.socket.Send(bytes);
                }
                catch
                {
                    if (!val.socket.Connected)
                    {
                        clients.Remove(val.socket.RemoteEndPoint.ToString());
                    }
                }
            }
            gc_count++;
            if (gc_count > 5000)
            {
                gc_count = 0;
                GC.Collect(2);
            }
            Debug.Log("發(fā)送數(shù)據(jù):" + (float)bytes.Length / 1024f + "KB");

            old_position = cam.transform.position;
            old_rotation = cam.transform.rotation;
        }
        success = true;
    }

    void OnDestroy()
    {
        try
        {
            socket.Shutdown(SocketShutdown.Both);
        }
        catch { }

        try
        {
            thread.Abort();
        }
        catch { }
    }
}

class Client {
	public Socket socket = null;
}

4.最終效果

在這里插入圖片描述

到此這篇關(guān)于Unity Sockect實現(xiàn)畫面實時傳輸?shù)奈恼戮徒榻B到這了,更多相關(guān)Unity Sockect畫面實時傳輸內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 淺析c# 接口

    淺析c# 接口

    這篇文章主要介紹了c# 接口的相關(guān)資料,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下。
    2020-07-07
  • 解決在Unity中使用FairyGUI遇到的坑

    解決在Unity中使用FairyGUI遇到的坑

    這篇文章主要介紹了解決在Unity中使用FairyGUI遇到的坑,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • 二叉樹的遍歷算法(詳細(xì)示例分析)

    二叉樹的遍歷算法(詳細(xì)示例分析)

    以下代碼是對二叉樹的遍歷算法進(jìn)行了分析介紹,需要的朋友可以參考下
    2013-05-05
  • C#線程委托BeginInvoke與EndInvoke的用法

    C#線程委托BeginInvoke與EndInvoke的用法

    這篇文章介紹了C#線程委托BeginInvoke與EndInvoke的用法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07
  • C#控制臺模擬電梯工作原理

    C#控制臺模擬電梯工作原理

    簡單的模擬一下電梯的運行,電梯內(nèi)部和外部樓層呼叫的優(yōu)先級判斷。以前學(xué)硬件的時候做這個不成問題,現(xiàn)在用軟件來模擬對我來說比較難,要C#的圖形界面。求高手賜教。
    2015-06-06
  • C#將Excel中的數(shù)據(jù)轉(zhuǎn)換成DataSet

    C#將Excel中的數(shù)據(jù)轉(zhuǎn)換成DataSet

    這篇文章主要介紹了C#將Excel中的數(shù)據(jù)轉(zhuǎn)換成DataSet的方法,非常簡單實用,從本人項目中提取出來的,推薦給大家,希望對大家學(xué)習(xí)C#能夠有所幫助。
    2015-03-03
  • C#?PaddleOCRSharp?OCR進(jìn)行疲勞測試

    C#?PaddleOCRSharp?OCR進(jìn)行疲勞測試

    PaddleOCRSharp?是百度飛槳封裝的.NET版本?OCR?dll?類庫,OCR可以將圖像文件中的文本內(nèi)容進(jìn)行識別,下面我們就來看看如何通過它們實現(xiàn)疲勞測試吧
    2024-11-11
  • 如何使用C# 捕獲進(jìn)程輸出

    如何使用C# 捕獲進(jìn)程輸出

    這篇文章主要介紹了如何使用C# 捕獲進(jìn)程輸出,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下
    2020-08-08
  • C# 多態(tài)性的深入理解

    C# 多態(tài)性的深入理解

    本篇文章是對C#中的多態(tài)性進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06
  • 詳解C#實現(xiàn)MD5加密的示例代碼

    詳解C#實現(xiàn)MD5加密的示例代碼

    本篇文章主要介紹了C#實現(xiàn)MD5加密的示例代碼,詳細(xì)的介紹了幾種方法,具有一定的參考價值,有興趣的可以了解一下。
    2016-12-12

最新評論

兴化市| 裕民县| 灯塔市| 寿宁县| 蕉岭县| 阿城市| 沙河市| 定陶县| 乌兰察布市| 株洲县| 太谷县| 姚安县| 克山县| 安阳市| 宜宾县| 黔西| 商城县| 祥云县| 托克逊县| 长泰县| 宜黄县| 泗水县| 嘉黎县| 宁乡县| 霞浦县| 藁城市| 五峰| 府谷县| 阳春市| 普兰店市| 怀仁县| 黄梅县| 塔城市| 沂南县| 荃湾区| 原阳县| 陕西省| 通河县| 济源市| 昂仁县| 沽源县|