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
相关产品推荐
相关产品推荐

