C# 调用ReadPixels从系统帧缓冲区读取像素,而不是在绘图帧内。UnityEngine.Texture2D:ReadPixels

C# 调用ReadPixels从系统帧缓冲区读取像素,而不是在绘图帧内。UnityEngine.Texture2D:ReadPixels,c#,unity3d,texture2d,C#,Unity3d,Texture2d,我正在尝试使用unity创建一个小测试应用程序。我正在构建应用程序的一个实例,并将其设置为主机,然后在unity editor中作为客户端运行另一个实例。在当前的迭代中,我有一个按钮,当按下这个按钮时,应该是截图,然后将截图发送给所有客户端。但似乎一切都不起作用。我遇到的第一个问题是ReadPixels错误: 调用ReadPixels从系统帧缓冲区读取像素,而不是在绘图帧内。UnityEngine.Texture2D:ReadPixels(Rect、Int32、Int32) UNETChat:O

我正在尝试使用unity创建一个小测试应用程序。我正在构建应用程序的一个实例,并将其设置为主机,然后在unity editor中作为客户端运行另一个实例。在当前的迭代中,我有一个按钮,当按下这个按钮时,应该是截图,然后将截图发送给所有客户端。但似乎一切都不起作用。我遇到的第一个问题是ReadPixels错误:

调用ReadPixels从系统帧缓冲区读取像素,而不是在绘图帧内。UnityEngine.Texture2D:ReadPixels(Rect、Int32、Int32) UNETChat:OnPostRender()(位于Assets/Scripts/UNETChat.cs:50) c__迭代器0:MoveNext()(位于Assets/Scripts/UNETChat.cs:42) UnityEngine.SetupCorroutine:InvokeMoveNext(IEnumerator,IntPtr)

除此之外,一旦解决了,我相信这里还有很多额外的工作,这是不恰当的。但我只是从这里开始。谢谢你的帮助

using System.Collections;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Networking.NetworkSystem;

public class MyMsgType
{
    public static short texture = MsgType.Highest + 1;
};

//Create a class that holds a variables to send
public class TextureMessage : MessageBase
{
    public byte[] textureBytes;
    public string message = "Test Received Message"; //Optional
}

public class UNETChat : Chat
{
    NetworkClient myClient;
    public Texture2D previewTexture;
    string messageToSend = "Screen Short Image";

    private void Start()
    {
        //if the client is also the server
        if (NetworkServer.active) 
        {
            // Register to connect event
            myClient.RegisterHandler(MsgType.Connect, OnConnected);
            // Register to texture receive event
            myClient.RegisterHandler(MyMsgType.texture, OnTextureReceive);
        }
        setupClient();
    }

    public IEnumerator TakeSnapshot(int width, int height)
    {
        yield return new WaitForSeconds(0.1F);
        Texture2D texture = new Texture2D(800, 800, TextureFormat.RGB24, true);
        texture.ReadPixels(new Rect(0, 0, 800, 800), 0, 0);
        texture.LoadRawTextureData(texture.GetRawTextureData());
        texture.Apply();

        sendTexture(texture, messageToSend);

        // gameObject.renderer.material.mainTexture = TakeSnapshot;

    }

    public void DoSendTexture()
    {
        StartCoroutine(TakeSnapshot(Screen.width, Screen.height));
    }

    // SERVER //////////////////////////

    //Call to send the Texture and a simple string message
    public void sendTexture(Texture2D texture, string message)
    {
        TextureMessage msg = new TextureMessage();

        //Convert Texture2D to byte array
        msg.textureBytes = texture.GetRawTextureData();
        msg.message = message;

        NetworkServer.SendToAll(MyMsgType.texture, msg);

        Debug.Log("Texture Sent!!");
    }

    // CLIENT //////////////////////////

    // Create a client and connect to the server port
    public void setupClient()
    {
        //Create new client
        myClient = new NetworkClient();
        //Register to connect event
        myClient.RegisterHandler(MsgType.Connect, OnConnected);
        //Register to texture receive event
        myClient.RegisterHandler(MyMsgType.texture, OnTextureReceive);
        //Connect to server
        myClient.Connect("localhost", 4444);
    }

    //Called when texture is received
    public void OnTextureReceive(NetworkMessage netMsg)
    {
        TextureMessage msg = netMsg.ReadMessage<TextureMessage>();

        //Your Received message
        string message = msg.message;
        Debug.Log("Texture Messsage " + message);

        //Your Received Texture2D
        Texture2D receivedtexture = new Texture2D(4, 4);
        receivedtexture.LoadRawTextureData(msg.textureBytes);
        receivedtexture.Apply();
    }

    public void OnConnected(NetworkMessage netMsg)
    {
        Debug.Log("Connected to server");
    }
}
使用系统集合;
使用System.IO;
使用UnityEngine;
使用UnityEngine。联网;
使用UnityEngine.Networking.NetworkSystem;
公共类MyMsgType
{
公共静态短纹理=MsgType.Highest+1;
};
//创建一个包含要发送的变量的类
公共类TextureMessage:MessageBase
{
公共字节[]纹理字节;
public string message=“Test Received message”;//可选
}
公共类UNETChat:Chat
{
网络客户端myClient;
公共纹理2D预览纹理;
string messageToSend=“屏幕短图像”;
私有void Start()
{
//如果客户端也是服务器
if(NetworkServer.active)
{
//注册以连接事件
myClient.RegisterHandler(MsgType.Connect,OnConnected);
//注册到纹理接收事件
myClient.RegisterHandler(MyMsgType.texture,OnTextureReceive);
}
setupClient();
}
公共IEnumerator快照(整数宽度、整数高度)
{
收益率返回新WaitForSeconds(0.1F);
Texture2D纹理=新的Texture2D(800,800,TextureFormat.RGB24,真);
读取像素(新的矩形(0,0,800,800),0,0);
加载RawTextureData(texture.GetRawTextureData());
纹理。应用();
sendTexture(纹理,messageToSend);
//gameObject.renderer.material.mainTexture=TakeSnapshot;
}
公共void DoSendTexture()
{
开始例行程序(拍摄快照(屏幕宽度、屏幕高度));
}
//服务器//////////////////////////
//调用以发送纹理和简单的字符串消息
公共void sendTexture(Texture2D纹理,字符串消息)
{
TextureMessage msg=新的TextureMessage();
//将Texture2D转换为字节数组
msg.textureBytes=texture.GetRawTextureData();
msg.message=消息;
NetworkServer.SendToAll(MyMsgType.texture,msg);
Log(“纹理已发送!!”);
}
//客户//////////////////////////
//创建客户端并连接到服务器端口
公共void setupClient()
{
//创建新客户端
myClient=新的NetworkClient();
//注册以连接事件
myClient.RegisterHandler(MsgType.Connect,OnConnected);
//注册到纹理接收事件
myClient.RegisterHandler(MyMsgType.texture,OnTextureReceive);
//连接到服务器
Connect(“localhost”,4444);
}
//接收纹理时调用
public void OnTextureReceive(NetworkMessage netMsg)
{
TextureMessage msg=netMsg.ReadMessage();
//您收到的信息
字符串消息=msg.message;
Debug.Log(“纹理消息”+消息);
//您收到的纹理2d
Texture2D receivedtexture=新的Texture2D(4,4);
接收Texture.LoadRawTextureData(msg.textureBytes);
receivedtexture.Apply();
}
未连接的公共无效(NetworkMessage netMsg)
{
Log(“连接到服务器”);
}
}

在拍摄屏幕截图或调用
Texture2D.ReadPixels
函数之前,请等待当前帧结束。这可以通过
WaitForEndOfFrame
类完成。请注意,我是如何缓存它的,以避免每次调用
TakeSnapshot
函数时创建新对象的

WaitForEndOfFrame frameEnd = new WaitForEndOfFrame();

public IEnumerator TakeSnapshot(int width, int height)
{
    yield return frameEnd;

    Texture2D texture = new Texture2D(800, 800, TextureFormat.RGB24, true);
    texture.ReadPixels(new Rect(0, 0, 800, 800), 0, 0);
    texture.LoadRawTextureData(texture.GetRawTextureData());
    texture.Apply();
    sendTexture(texture, messageToSend);

    // gameObject.renderer.material.mainTexture = TakeSnapshot;
}

我注意到您的脚本中有
yield return new WaitForSeconds(0.1F)
,它在截图前等待
0.2
秒。如果您必须等待
0.2
秒,则首先等待
0.2
秒,然后等待帧结束后再拍摄屏幕截图:

WaitForSeconds waitTime = new WaitForSeconds(0.1F);
WaitForEndOfFrame frameEnd = new WaitForEndOfFrame();

public IEnumerator TakeSnapshot(int width, int height)
{
    yield return waitTime;
    yield return frameEnd;

    Texture2D texture = new Texture2D(800, 800, TextureFormat.RGB24, true);
    texture.ReadPixels(new Rect(0, 0, 800, 800), 0, 0);
    texture.LoadRawTextureData(texture.GetRawTextureData());
    texture.Apply();
    sendTexture(texture, messageToSend);

    // gameObject.renderer.material.mainTexture = TakeSnapshot;
}

请更改问题的标题和正文,以反映您的错误。另外,单击错误并在问题中添加错误发生的位置。仅对标题和错误消息进行了更改。感谢您提及缓存。