Unity 发送游戏画面到 Winform
Posted 叶图的博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity 发送游戏画面到 Winform相关的知识,希望对你有一定的参考价值。
一、首先看一下Unity界面:
设了2个摄像机,位置重叠,旋转相同,父子关系,在父摄像机上加上脚本A.cs,并将子摄像机复制给A脚本中的变量Cam;
Cam用于为RenderTexture提供画面,Port是Socket监听的端口;
二、A.cs脚本代码(夜太深,改天再补充注释,直接贴代码)
using System; using System.Collections; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Threading; using UnityEngine; public class A : MonoBehaviour { public Camera cam; public int port = 10002; RenderTexture cameraView = null; Socket socket = null; Thread thread = null; bool success = true; /// <summary> /// 客户端列表 /// </summary> Dictionary<string, Client> clients = new Dictionary<string, Client>(); Vector3 old_position;//旧位置 Quaternion old_rotation;//旧旋转 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 = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), port)); socket.Listen(100); thread = new Thread(new ThreadStart(Accept)); thread.Start(); } int isNewAdd = 0; void Accept() { 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; Debug.LogError("连接……"); } } 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 isInit = 0) { if ((!old_position.Equals(transform.position) || !old_rotation.Equals(transform.rotation)) || isInit == 1) { if (null == screenShot) screenShot = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false); 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()); break; } } gc_count++; if (gc_count > 5000) { gc_count = 0; GC.Collect(2); } Debug.Log("发送数据:" + (float)bytes.Length / 1024f + "KB"); old_position = transform.position; old_rotation = transform.rotation; } success = true; } } class Client { public Socket socket = null; }
三、Winform端
直接拖了个PictureBox放到窗口上,停靠父窗体;
四、Winform代码
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace TransformViewClient { public partial class Form1 : Form { bool isOver = false; Socket socket = null; Thread thread = null; byte[] buffer = null; bool receState = true; int readTimes = 0; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { Control.CheckForIllegalCrossThreadCalls = true; buffer = new byte[1024 * 1024 * 10]; socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.Connect(IPAddress.Parse("127.0.0.1"), 10002); thread = new Thread(new ThreadStart(Receive)); thread.Start(); } void Receive() { while (thread.ThreadState == ThreadState.Running && socket.Connected) { 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); pictureBox1.Image = Image.FromStream(ms); readTimes++; if (readTimes > 5000) { readTimes = 0; GC.Collect(2); } } catch { } receState = true; } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { try { socket.Shutdown(SocketShutdown.Both); } catch { } try { thread.Abort(); } catch { } } } }
程序里或许有许多bug和缺陷,希望高手指点!
以上是关于Unity 发送游戏画面到 Winform的主要内容,如果未能解决你的问题,请参考以下文章