如何在Unity3D项目中添加C# System.Drawing引用?
Unity中使用System.Drawing类的引用问题及解决方案
问题说明
在Unity3D项目的FindPoints方法中,尝试使用Bitmap、GraphicsPath、BitmapData、Rectangle等System.Drawing下的类时,始终提示缺少引用。修改Unity编辑器Project Settings>Player的API兼容性级别为.NET 2.1后,仅能获取部分System.Drawing内容,无法使用完整的GDI+相关功能,导致代码无法正常运行。原代码如下:
private void FindPoints() { Bitmap bmptest; GraphicsPath gp = new GraphicsPath(); int x, y, p, j, wdthHght; int bytes; byte[] rgbValuesWithClouds; byte[] rgbValuesWithoutClouds; IntPtr ptr; Rectangle rect; BitmapData bitmap_Data; Bitmap bmpWithClouds; //No memory is allocated Bitmap bmpWithoutClouds; //No memory is allocated gp.AddEllipse(new RectangleF(73, 72, 367, 367)); //using the using statement, bmpWithClouds bitmap is automatically disposed at the end of statement. No memory leaks :) using (bmpWithClouds = new Bitmap(mymem)) { rect = new Rectangle(0, 0, bmpWithClouds.Width, bmpWithClouds.Height); wdthHght = bmpWithClouds.Width; //Lock bitmap to copy its color information fast bitmap_Data = bmpWithClouds.LockBits(rect, ImageLockMode.ReadWrite, bmpWithClouds.PixelFormat); ptr = bitmap_Data.Scan0; bytes = bitmap_Data.Stride * bmpWithClouds.Height; rgbValuesWithClouds = new byte[bytes]; //copy color information to rgbValues array System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValuesWithClouds, 0, bytes); //we are done copying so unlock bitmap. We dont need it anymore bmpWithClouds.UnlockBits(bitmap_Data); } //using the using statement, bmpWithClouds bitmap is automatically disposed at the end of statement. No memory leaks :) using (bmpWithoutClouds = new Bitmap(@"F:\Drive Backup\Samsung Galaxy S9\Danny Backup\Recovered data 02-10 18_32_36\1 (D) NTFS\C-Sharp\Weather Radar\WithoutClouds.bmp")) //24 bit bitmap { rect = new Rectangle(0, 0, bmpWithoutClouds.Width, bmpWithoutClouds.Height); //Lock bitmap to copy its color information fast bitmap_Data = bmpWithoutClouds.LockBits(rect, ImageLockMode.ReadWrite, bmpWithoutClouds.PixelFormat); ptr = bitmap_Data.Scan0; bytes = bitmap_Data.Stride * bmpWithoutClouds.Height; rgbValuesWithoutClouds = new byte[bytes]; //copy color information to rgbValues array System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValuesWithoutClouds, 0, bytes); //we are done copying so unlock bitmap. We dont need it anymore bmpWithoutClouds.UnlockBits(bitmap_Data); } // Each position in these arrays, rgbValuesWithoutClouds and rgbValuesWithClouds, corresponds a color. eg // First pixel Second pixel Third pixel Forth pixel .... // bitmaps // B G R B G R B G R B G R .... // rgbValues arrays bmptest = new Bitmap(512, 512); cloudPoints = new List<Point>(); for (y = 0; y < wdthHght; y++) { j = 0; for (x = 0; x < wdthHght; x++) { p = y * wdthHght * 3 + j; if (rgbValuesWithClouds[p] != rgbValuesWithoutClouds[p]) { cloudPoints.Add(new Point(x, y)); bmptest.SetPixel(x, y, Color.Red); } j += 3; } } }
解决方案
1. 理解Unity对System.Drawing的限制
System.Drawing是Windows平台GDI+的实现,Unity的跨平台运行时(Mono/.NET Core)并未完整包含该库,仅提供了少量基础类型。因此即使修改API兼容性级别,也无法获取完整的GDI+功能,且该库在非Windows平台完全无法使用。
2. 推荐方案:使用Unity原生Texture2D替代Bitmap
Unity提供了Texture2D类用于图像操作,完全跨平台,且能无缝集成到Unity的渲染系统中。以下是用Texture2D重写的FindPoints方法:
using UnityEngine; using System.Collections.Generic; using System.IO; private List<Vector2> cloudPoints; // 用Unity的Vector2替代System.Drawing.Point private void FindPoints() { // 读取带云层的图片(替换原mymem为实际路径或Texture2D对象) Texture2D bmpWithClouds = LoadTextureFromPath("你的带云层图片路径"); Texture2D bmpWithoutClouds = LoadTextureFromPath(@"F:\Drive Backup\Samsung Galaxy S9\Danny Backup\Recovered data 02-10 18_32_36\1 (D) NTFS\C-Sharp\Weather Radar\WithoutClouds.bmp"); if (bmpWithClouds == null || bmpWithoutClouds == null) { Debug.LogError("图片加载失败"); return; } int width = bmpWithClouds.width; int height = bmpWithClouds.height; // 获取像素数据(RGBA格式,每个像素4字节) Color32[] pixelsWithClouds = bmpWithClouds.GetPixels32(); Color32[] pixelsWithoutClouds = bmpWithoutClouds.GetPixels32(); cloudPoints = new List<Vector2>(); Texture2D bmptest = new Texture2D(width, height); Color32[] testPixels = bmptest.GetPixels32(); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int index = y * width + x; // 对比蓝色通道(对应原代码的B分量) if (pixelsWithClouds[index].b != pixelsWithoutClouds[index].b) { cloudPoints.Add(new Vector2(x, y)); testPixels[index] = Color.red; } else { testPixels[index] = Color.clear; } } } bmptest.SetPixels32(testPixels); bmptest.Apply(); // 释放临时Texture资源(如果不再使用) Object.Destroy(bmpWithClouds); Object.Destroy(bmpWithoutClouds); } // 辅助方法:从本地路径加载Texture2D private Texture2D LoadTextureFromPath(string path) { if (!File.Exists(path)) { Debug.LogError($"文件不存在:{path}"); return null; } byte[] fileData = File.ReadAllBytes(path); Texture2D texture = new Texture2D(2, 2); texture.LoadImage(fileData); // 自动识别图片格式 return texture; }
3. 临时方案:仅Windows平台使用System.Drawing
如果必须保留原有System.Drawing代码,仅在Windows平台运行项目,可按以下步骤操作:
- 在Unity项目的
Assets文件夹下创建Plugins目录; - 从本地.NET框架目录(如
C:\Windows\Microsoft.NET\Framework\v4.0.30319)复制System.Drawing.dll、System.Drawing.Design.dll到Plugins文件夹; - 选中复制的DLL文件,在Inspector面板中设置Platform Settings:勾选
Windows,其他平台设为Exclude; - 重新打开Unity,即可使用完整的
System.Drawing类。注意此方法仅支持Windows编辑器和Windows打包版本,跨平台项目请勿使用。
内容的提问来源于stack exchange,提问作者Daniel Lip
相关产品推荐
相关产品推荐

