一、首先看一下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的更多相关文章

  1. 关于Unity的游戏的运行模式

    游戏有个入口main函数,执行完main函数就返回 main函数中的步骤 1.初始化 2.while(true){ a.检查有没有消息,包括鼠标有没有被点击,键盘有没有被点击,自定义事件等等,有消息就 ...

  2. 《Unity 3D游戏客户端基础框架》概述

    框架概述: 做了那么久的业务开发,也做了一年多的核心战斗开发,最近想着自己倒腾一套游戏框架,当然暂不涉及核心玩法类型和战斗框架,核心战斗的设计要根据具体的游戏类型而定制,这里只是一些通用的基础系统的框 ...

  3. [生活日记]参与unity非游戏行业开发者大会小结

    今天下午花了半天时间公司全体都去人民广场参与了一个unity非游戏行业开发者大会,主要了解到unity这款全球顶尖之一的游戏引擎的一个发展史,从05年三个美国人技术研发开始,一直到12年开始引进中国, ...

  4. 自制Unity小游戏TankHero-2D(5)声音+爆炸+场景切换+武器弹药

    自制Unity小游戏TankHero-2D(5)声音+爆炸+场景切换+武器弹药 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm ...

  5. 自制Unity小游戏TankHero-2D(4)关卡+小地图图标+碰撞条件分析

    自制Unity小游戏TankHero-2D(4)关卡+小地图图标+碰撞条件分析 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm ...

  6. 自制Unity小游戏TankHero-2D(3)开始玩起来

    自制Unity小游戏TankHero-2D(3)开始玩起来 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm)这个游戏制作的.仅 ...

  7. 自制Unity小游戏TankHero-2D(2)制作敌方坦克

    自制Unity小游戏TankHero-2D(2)制作敌方坦克 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm)这个游戏制作的. ...

  8. 自制Unity小游戏TankHero-2D(1)制作主角坦克

    自制Unity小游戏TankHero-2D(1)制作主角坦克 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm)这个游戏制作的. ...

  9. iOS端给unity发送消息,实现两者交互。

    上一篇我们简单说了一下unity发消息给iOS端.现在我们就来说一下iOS端给unity发送消息的简单使用. 首先iOS端做得事情其实很简单就一句话,直接上代码 /** * 第一个参数:是unity那 ...

随机推荐

  1. 【java】详解native方法的使用

    目录结构: contents structure [+] 关于native关键字 使用native关键字 使用步骤 案例 编写.java文件 编译.java文件 获得.h文件 编写hello.cpp文 ...

  2. apigateway-kong(七)配置说明

    这一部分应该在最开始介绍,但是我觉得在对kong有一定了解后再回头看下配置,会理解的更深刻.接下来对这个配置文件里的参数做个详细的解释便于更好的使用或优化kong网关. 目录 一.配置加载 二.验证配 ...

  3. Zookeeper客户端Curator---Getting Started

    先说个小插曲,前几天有个网站转载我的文章没有署名作者,我有点不开心就给他们留言了,然后今天一看他们把文章删了.其实我的意思并不是你允许转载,我想表达的是我的付出需要被尊重.也不知道是谁的错~ ==== ...

  4. NOIP 普及组 2014 比例简化

    传送门 https://www.cnblogs.com/violet-acmer/p/9898636.html 题解: 一开始想多了,以为得保证两者之间的相对比率,至少不能改变的太离谱啊. but,直 ...

  5. Tarjan 模板,高级并查集

    第一个模板有误!!!! 请见谅!!! 要怪就怪HDU吧,竟然让我过了 第二个模板是正确的.请翻到下面看更新 HDU 1269 评论区居然有人说用并查集过了,其实回想一下 求无向图的连通分量,就是并查集 ...

  6. idea去掉无效引用

    Mac版的idea,打开Preference->Editor->General,打勾红色框框. 然后使用快捷键 contrl + option + o 只能去掉当前文件没有引用的包,并不能 ...

  7. ffmpeg在asp.net 视频转换

    ffmpeg是一个源于Linux的工具软件,是FLV视频转换器,可以轻易地实现FLV向其它格式avi.asf. mpeg的转换或者将其它格式转换为flv.在视频播客中,我们通常使用它把我们上传的视频转 ...

  8. 20190313 org.apache.commons.lang3.builder.EqualsBuilder的两种典型用法

    org.apache.commons.lang3.builder.EqualsBuilder的两种典型用法 public boolean equals(Object obj) { if (obj == ...

  9. POJ 2127 Greatest Common Increasing Subsequence

    You are given two sequences of integer numbers. Write a program to determine their common increasing ...

  10. 八皇后问题动态演示_Qt5实现

    //核心代码如下 //Queen--放置皇后 #include "queue.h" queue::queue() { *; ; this->board = new bool[ ...