gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-03 20:59:53 26 4
gpt4 key购买 nike

我正在尝试使用 unity 创建一个小的测试应用程序。我正在构建应用程序的一个实例并将其设置为充当主机,然后在统一编辑器中作为客户端运行另一个实例。在当前的迭代中,我有一个按钮,按下时应该截取屏幕截图,然后将该屏幕截图发送给所有客户端。但似乎没有任何效果。我遇到的最初问题是 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");
}
}

最佳答案

等到当前帧结束后再截取屏幕截图或调用 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;
}

关于c# - 调用 ReadPixels 以从系统帧缓冲区读取像素,而不是在绘图帧内。 UnityEngine.Texture2D :ReadPixels,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46595055/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com