如何通过脚本使Texture2D可读

如何通过脚本使Texture2D可读性


又踩了一个Unity比较坑的地方:就是在代码里访问Texture2D的时候,不可读。

看了很多博客,例如:https://blog.csdn.net/emoonight/article/details/18002913,通过设置纹理的导入设置中的Raad/Wtire改为true。

或者:https://blog.csdn.net/qq617119142/article/details/50085677,通过代码设置Texture的可读性。

但是注意了,这都是Texture,并不是Texture2D,那我们改怎么做呢?看到国外的一片文章完美解决这个问题:https://stackoverflow.com/questions/44733841/how-to-make-texture2d-readable-via-script


首先不可读的原因:
Unity将其设置为不可读的原因是因为使它不可读的话,它的访问速度将变得非常快,而使它具有可读性是以牺牲内存和性能为代价的。这样做的原因是,使其不可读那么纹理将在GPU上。如果您使其可读性,CPU也可以访问它,但是操作缓慢。GPU的访问速度是很快的,假如它运行在GPU上的话,那么自然速度会更快。

原文:By making it unreadable, it becomes very very fast. Making it readable comes at a cost of memory and performance. The reason for this is because making it unreadable will make the texture on the GPU. If you make it readable, the CPU can also access it making the operation slow. GPU is extremely fast. That’s the thing. I think you should study “Compute shader” in Unity. You will see how fast you can do stuff with it just because it’s running on the GPU instead of CPU. Note that this is an advanced topic. It’s similar to making Texture2D unreadable.


解决办法

1.使用RenderTexture(建议):

使用RenderTexture。把源Texture2D放进RenderTexture带着Graphics.Blit然后使用Texture2D.ReadPixels若要从RenderTexture进入新的Texture2D.

附上代码:

private Texture2D duplicateTexture(Texture2D source)
{
    RenderTexture renderTex = RenderTexture.GetTemporary(
                source.width,
                source.height,
                0,
                RenderTextureFormat.Default,
                RenderTextureReadWrite.Linear);

    Graphics.Blit(source, renderTex);
    RenderTexture previous = RenderTexture.active;
    RenderTexture.active = renderTex;
    Texture2D readableText = new Texture2D(source.width, source.height);
    readableText.ReadPixels(new Rect(0, 0, renderTex.width, renderTex.height), 0, 0);
    readableText.Apply();
    RenderTexture.active = previous;
    RenderTexture.ReleaseTemporary(renderTex);
    return readableText;
}

使用:

Texture2D copy = duplicateTexture(sourceTextFromPlugin);

这个方法不会报出任何错误,亲测有效。


2.使用Texture2D.GetRawTextureData() + Texture2D.LoadRawTextureData():

你不能用GetPixels32()因为Texture2D是不可读的。你差点就用了GetRawTextureData().

当你用Texture2D.LoadImage()从GetRawTextureData().

Texture2D.LoadImage()是只用于加载PNG/JPG数组字节,而不是Transture2D数组字节。

如果你用Texture2D.GetRawTextureData(),你必须用Texture2D.LoadRawTextureData()不Texture2D.LoadImage()。

附上代码:

private Texture2D duplicateTexture(Texture2D source)
{
    byte[] pix = source.GetRawTextureData();
    Texture2D readableText = new Texture2D(source.width, source.height, source.format, false);
    readableText.LoadRawTextureData(pix);
    readableText.Apply();
    return readableText;
}

编辑器中的代码不会出现错误,但是独立构建时应该会出现错误。此外,即使在独立构建中出现错误,它仍然可以工作。
报的错误为:Texture needs to be marked as Read/Write to be able to GetRawTextureData in player。


建议使用第一种方法,因为它不会报错,第二种方法亲测有的时候会导致Texture2D丢失。

  • 8
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
好的,针对您的问题,我可以给您提供以下的代码实现: 首先,我们需要创建一个用于编辑地图的脚本,以下是一个示例: ```csharp using UnityEngine; public class MapEditor : MonoBehaviour { public Texture2D mapTexture; public int brushSize = 1; public Color brushColor = Color.white; private Color[] mapColors; private int mapWidth; private int mapHeight; private void Awake() { mapWidth = mapTexture.width; mapHeight = mapTexture.height; mapColors = mapTexture.GetPixels(); } private void Update() { if (Input.GetMouseButton(0)) { Vector2 mousePosition = Input.mousePosition; int x = (int)(mousePosition.x / Screen.width * mapWidth); int y = (int)(mousePosition.y / Screen.height * mapHeight); BrushMap(x, y); } } private void BrushMap(int x, int y) { for (int i = -brushSize; i <= brushSize; i++) { for (int j = -brushSize; j <= brushSize; j++) { int px = x + i; int py = y + j; if (px >= 0 && px < mapWidth && py >= 0 && py < mapHeight) { mapColors[py * mapWidth + px] = brushColor; } } } mapTexture.SetPixels(mapColors); mapTexture.Apply(); } } ``` 上面的代码中,我们首先获取了一个用于编辑的地图纹理,然后通过 `GetPixels()` 方法获取到了纹理中的所有像素点的颜色值。在 `Update()` 方法中,我们检测鼠标左键是否被按下,如果是的话,就获取当前鼠标的位置,计算出对应的像素点坐标,然后调用 `BrushMap()` 方法来绘制笔刷。 在 `BrushMap()` 方法中,我们首先使用两个嵌套循环来遍历笔刷的大小,然后根据当前像素点坐标以及笔刷的大小计算出需要修改的像素点坐标。注意,我们需要判断计算出来的坐标是否在地图范围内,如果在的话,就将对应的像素点颜色修改为笔刷的颜色值。最后,我们调用 `SetPixels()` 方法将修改后的颜色数组重新赋值给地图纹理,并调用 `Apply()` 方法更新纹理。 以上就是一个基本的通过 `Texture2D` 刷地图行走区域的笔刷的形式的代码实现,您可以根据实际需求进行修改和扩展。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值