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

问题描述:

我试图创建一个小测试应用程序,使用统一。我构建了一个应用程序实例并将其设置为主机,然后在Unity编辑器中作为客户端运行另一个实例。在当前的迭代中,我有一个按钮,当按下时是截图,然后将截图发送给所有客户端。但似乎没有任何工作。我遇到的最初问题是ReadPixels错误:ReadPixels被调用来从系统帧缓冲区读取像素,而不是在绘图框内。 UnityEngine.Texture2D:ReadPixels

ReadPixels was called to read pixels from system frame buffer, while not inside drawing frame. UnityEngine.Texture2D:ReadPixels(Rect, Int32, Int32) UNETChat:OnPostRender() (at Assets/Scripts/UNETChat.cs:50) <TakeSnapshot>c__Iterator0:MoveNext() (at Assets/Scripts/UNETChat.cs:42) UnityEngine.SetupCoroutine: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"); 
    } 
} 
+0

请改变你的问题的标题和正文,以反映你得到了错误。同时点击错误,并添加错误发生在你的问题的地方。 – Programmer

+0

只是对标题和错误消息进行了更改 – greyBow

等待,直到当前帧的考虑屏幕截图之前或调用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; 
} 

我注意到你在你的脚本采取截图之前等待0.2秒有yield return new WaitForSeconds(0.1F)。如果你必须等待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; 
}