You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中如何将Texture2D传入Android并保存为Bitmap?代码求助

解决Unity Texture2D传入Android保存为Bitmap的问题

咱们先捋清楚核心问题:直接用GetNativeTexturePtr()传递的是GPU纹理的句柄,不是CPU可直接读取的像素数据,而且Unity和Android的纹理内存布局、像素顺序、坐标原点都有差异,这些都是导致保存失败的常见坑点。下面给你分步拆解修正方案:

1. Unity端代码先调整(优先推荐字节数组传递)

GetNativeTexturePtr()拿到的是GPU纹理的指针,Android端没法直接读取,咱们先把纹理数据提取到CPU内存的字节数组里再传递,这样更稳定:

// 先确保Texture2D是可读的:动态生成的纹理创建时要设readable=true;导入的纹理在Inspector里勾选「Read/Write Enabled」
byte[] pixelBytes = testTexture.GetRawTextureData();
// 把像素数据、宽高、纹理格式一起传给Android
_pluginInterface.CallStatic("ProcessImage", pixelBytes, testTexture.width, testTexture.height, testTexture.format.ToString());

2. Android端完整实现代码

Java端需要处理像素格式转换、坐标翻转这些细节,以下是可直接运行的ProcessImage方法:

import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.os.Environment;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

public class YourPluginClass {
    public static void ProcessImage(byte[] pixelData, int width, int height, String textureFormat) {
        Bitmap.Config bitmapConfig;
        int bytesPerPixel;

        // 匹配Unity的纹理格式到Android Bitmap配置
        switch (textureFormat) {
            case "RGBA32":
                bitmapConfig = Bitmap.Config.ARGB_8888;
                bytesPerPixel = 4;
                break;
            case "RGB24":
                bitmapConfig = Bitmap.Config.RGB_565;
                bytesPerPixel = 3;
                break;
            default:
                bitmapConfig = Bitmap.Config.ARGB_8888;
                bytesPerPixel = 4;
                break;
        }

        // 关键:Unity是RGBA顺序,Android ARGB_8888是ARGB顺序,必须转换
        if (bitmapConfig == Bitmap.Config.ARGB_8888) {
            byte[] argbData = new byte[pixelData.length];
            for (int i = 0; i < pixelData.length; i += 4) {
                argbData[i] = pixelData[i + 3];     // 把Unity的A通道移到第一位
                argbData[i + 1] = pixelData[i];     // R通道
                argbData[i + 2] = pixelData[i + 1]; // G通道
                argbData[i + 3] = pixelData[i + 2]; // B通道
            }
            pixelData = argbData;
        }

        // 写入Buffer并创建Bitmap
        ByteBuffer buffer = ByteBuffer.wrap(pixelData);
        buffer.order(ByteOrder.LITTLE_ENDIAN); // Unity的像素数据是小端字节序
        Bitmap bitmap = Bitmap.createBitmap(width, height, bitmapConfig);
        bitmap.copyPixelsFromBuffer(buffer);

        // 翻转Bitmap:Unity纹理原点是左下角,Android Bitmap是左上角,不翻转会上下颠倒
        Matrix flipMatrix = new Matrix();
        flipMatrix.postScale(1, -1);
        bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, flipMatrix, true);

        // 保存到设备存储(注意Android 10+权限问题,可根据需求调整存储路径)
        try {
            String savePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/unity_bitmap.png";
            FileOutputStream fos = new FileOutputStream(savePath);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
            fos.flush();
            fos.close();
            bitmap.recycle(); // 记得释放Bitmap内存
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3. 必看的注意事项

  • 纹理可读性:Unity侧的Texture2D必须开启「Read/Write Enabled」,否则GetRawTextureData()会返回空数组。
  • 权限问题:Android 10及以上版本,直接写入外部存储可能会失败,建议使用MediaStore或者申请MANAGE_EXTERNAL_STORAGE权限(针对Android 11+)。
  • 格式匹配:如果你的Texture2D用的是其他格式(比如ETC压缩格式),需要先在Unity端转换成RGBA32/RGB24再传递,不然Android端无法解析。

内容的提问来源于stack exchange,提问作者PCoelho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:37:32