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 = ; 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, );
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();
thread = new Thread(new ThreadStart(Accept));
thread.Start();
} int isNewAdd = ; 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 = ;
Debug.LogError("连接……");
}
} void Update()
{
if (success && clients.Count > )
{
success = false;
SendTexture();
} if (isNewAdd > )
{
isNewAdd = ;
SendTexture();
}
} void OnGUI()
{
GUI.DrawTexture(new Rect(, , , ), cameraView, ScaleMode.StretchToFill);
} void OnApplicationQuit()
{
try
{
socket.Shutdown(SocketShutdown.Both);
}
catch { } try
{
thread.Abort();
}
catch { }
} Texture2D screenShot = null; int gc_count = ; void SendTexture(int isInit = )
{
if ((!old_position.Equals(transform.position) || !old_rotation.Equals(transform.rotation)) || isInit == )
{
if (null == screenShot)
screenShot = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
RenderTexture.active = cameraView;
screenShot.ReadPixels(new Rect(, , cameraView.width, cameraView.height), , );
RenderTexture.active = null;
byte[] bytes = screenShot.EncodeToJPG(); 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 > )
{
gc_count = ;
GC.Collect();
}
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 = ; public Form1()
{
InitializeComponent();
} private void Form1_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = true; buffer = new byte[ * * ]; socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(IPAddress.Parse("127.0.0.1"), );
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 > )
{
receState = false;
BytesToImage(count, buffer);
}
}
} MemoryStream ms = null;
public void BytesToImage(int count,byte[] bytes)
{
try
{
ms = new MemoryStream(bytes, , count);
pictureBox1.Image = Image.FromStream(ms);
readTimes++; if (readTimes > )
{
readTimes = ;
GC.Collect();
}
}
catch
{ }
receState = true;
} private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
try
{
socket.Shutdown(SocketShutdown.Both);
}
catch { } try
{
thread.Abort();
}
catch { }
}
}
}
程序里或许有许多bug和缺陷,希望高手指点!

Unity 发送游戏画面到 Winform的更多相关文章
- 关于Unity的游戏的运行模式
游戏有个入口main函数,执行完main函数就返回 main函数中的步骤 1.初始化 2.while(true){ a.检查有没有消息,包括鼠标有没有被点击,键盘有没有被点击,自定义事件等等,有消息就 ...
- 《Unity 3D游戏客户端基础框架》概述
框架概述: 做了那么久的业务开发,也做了一年多的核心战斗开发,最近想着自己倒腾一套游戏框架,当然暂不涉及核心玩法类型和战斗框架,核心战斗的设计要根据具体的游戏类型而定制,这里只是一些通用的基础系统的框 ...
- [生活日记]参与unity非游戏行业开发者大会小结
今天下午花了半天时间公司全体都去人民广场参与了一个unity非游戏行业开发者大会,主要了解到unity这款全球顶尖之一的游戏引擎的一个发展史,从05年三个美国人技术研发开始,一直到12年开始引进中国, ...
- 自制Unity小游戏TankHero-2D(5)声音+爆炸+场景切换+武器弹药
自制Unity小游戏TankHero-2D(5)声音+爆炸+场景切换+武器弹药 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm ...
- 自制Unity小游戏TankHero-2D(4)关卡+小地图图标+碰撞条件分析
自制Unity小游戏TankHero-2D(4)关卡+小地图图标+碰撞条件分析 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm ...
- 自制Unity小游戏TankHero-2D(3)开始玩起来
自制Unity小游戏TankHero-2D(3)开始玩起来 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm)这个游戏制作的.仅 ...
- 自制Unity小游戏TankHero-2D(2)制作敌方坦克
自制Unity小游戏TankHero-2D(2)制作敌方坦克 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm)这个游戏制作的. ...
- 自制Unity小游戏TankHero-2D(1)制作主角坦克
自制Unity小游戏TankHero-2D(1)制作主角坦克 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm)这个游戏制作的. ...
- iOS端给unity发送消息,实现两者交互。
上一篇我们简单说了一下unity发消息给iOS端.现在我们就来说一下iOS端给unity发送消息的简单使用. 首先iOS端做得事情其实很简单就一句话,直接上代码 /** * 第一个参数:是unity那 ...
随机推荐
- pyinstaller模块使用
目前pip install pyinstaller已经成熟 但是还是有一些坑,郁闷了好久,记一下注意点吧. 将py脚本打包成exe文件时,如果导入了非python自带库,则需要将导入的库从site-p ...
- HDU 3081 Marriage Match II (网络流,最大流,二分,并查集)
HDU 3081 Marriage Match II (网络流,最大流,二分,并查集) Description Presumably, you all have known the question ...
- HDU 4292 Food (网络流,最大流)
HDU 4292 Food (网络流,最大流) Description You, a part-time dining service worker in your college's dining ...
- Eclipse导入模板格式Xml配置文件
Eclipse一般常用的可以导入两处 *.xml 格式的模板,一个是常用的注释格式模板,另一个是代码格式化时用的模板,导入方法如下: 假设: 1.xml 是代码注释格式模板 2.xml 是代码 ...
- struct字节对齐原则
原则1:windows下,k字节基本类型以k字节倍数偏移量对齐,自定义结构体则以结构体中最高p字节基本类型的p字节倍数偏移量对齐,Linux下则以2或4字节对齐; 原则2:整体对齐原则,例如数组结构体 ...
- 使用gdb+core查看错误信息
core的使用Linux下core文件调试方法 ulimit -c xxx可以设置core文件的大小 proc/sys/kernel/core_pattern可以控制core文件保存位置和文件名格式. ...
- spoj QTREE - Query on a tree(树链剖分+线段树单点更新,区间查询)
传送门:Problem QTREE https://www.cnblogs.com/violet-acmer/p/9711441.html 题解: 树链剖分的模板题,看代码比看文字解析理解来的快~~~ ...
- (lower_bound)find the nth digit hdu1597
find the nth digit Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Other ...
- ubuntu14安装node0.12.7
1. 官网下载linux系统二进制文件, 链接如下: https://nodejs.org/ 2. 解压到/opt/目录 3. 设置node环境变量 export NODE_HOME=/opt/nod ...
- passat / maintenance / baoyang
s s 南京迎客隆汽车租赁有限公司 / 地址:常府街54号 / 电话:025-84546836 84507610 二手车养不起.修不起?果真如此吗?http://www.che168.com/list ...