如何将iOS端的id<MTLTexture>发送至Unity并实现接收?
解决iOS端传递MTLTexture到Unity的问题
Hey,我来帮你搞定这个跨端纹理传递的问题——你现在直接把id<MTLTexture>对象传给UnitySendMessage肯定不行,因为它只接受C风格的char*参数。核心思路是把Metal纹理的内存地址转换成字符串传递,再在Unity端解析回指针,具体步骤如下:
一、iOS端代码修改
在OC中,我们可以通过__bridge把Objective-C对象转为void*,再把指针地址格式化为十六进制字符串,最后转成char*传给Unity:
// iOS side id<MTLTexture> _texture = CVMetalTextureGetTexture(texture); // 将MTLTexture的内存地址格式化为十六进制字符串 NSString *textureAddrStr = [NSString stringWithFormat:@"%p", _texture]; // 转成C风格字符串传给UnitySendMessage UnitySendMessage(CALLBACK_OBJECT, CALLBACK_TEXTURE_READY, [textureAddrStr UTF8String]);
这里%p是OC中格式化指针地址的标准方式,UTF8String方法刚好能把NSString转换成UnitySendMessage需要的char*类型。
二、Unity端接收逻辑调整
你之前用Int32.Parse会有大问题——iOS设备都是64位系统,指针长度是8字节,用32位解析会直接截断地址导致崩溃。正确的做法是把十六进制字符串解析成long类型再转IntPtr:
// Unity side private void OnTextureReady(string texture_str) { // 把十六进制字符串解析为64位整数,再转成IntPtr IntPtr texturePtr = new IntPtr(long.Parse(texture_str, System.Globalization.NumberStyles.HexNumber)); // 建议不要硬编码宽高,最好从iOS端同步获取(下面会说怎么实现) int width = (int)GetMetalTextureWidth(texturePtr); int height = (int)GetMetalTextureHeight(texturePtr); // 创建外部纹理,注意格式要和Metal纹理匹配! rawImage.texture = Texture2D.CreateExternalTexture(width, height, TextureFormat.ARGB32, false, false, texturePtr); } // 通过C#调用iOS原生方法获取纹理宽高 [DllImport("__Internal")] private static extern uint GetMetalTextureWidth(IntPtr texturePtr); [DllImport("__Internal")] private static extern uint GetMetalTextureHeight(IntPtr texturePtr);
对应的,iOS端需要新增两个C风格的导出方法,供Unity调用:
// iOS side 新增方法 extern "C" uint GetMetalTextureWidth(void* texturePtr) { // 把void*转回到MTLTexture对象 id<MTLTexture> texture = (__bridge id<MTLTexture>)texturePtr; return texture.width; } extern "C" uint GetMetalTextureHeight(void* texturePtr) { id<MTLTexture> texture = (__bridge id<MTLTexture>)texturePtr; return texture.height; }
三、必须注意的几个关键点
- 生命周期管理:Unity创建的外部纹理依赖iOS端的MTLTexture,所以一定要确保在Unity用完这个纹理之前,iOS端不要释放它。可以在Unity端不再使用时,调用iOS的方法手动释放纹理,或者用OC的引用计数来管理。
- 纹理格式匹配:Unity的
TextureFormat必须和Metal纹理的像素格式对应,比如Metal的MTLPixelFormatBGRA8Unorm对应Unity的TextureFormat.BGRA32,格式不匹配会出现花屏或者黑屏。 - 64位兼容性:一定要用
long.Parse而不是Int32.Parse,这是很多人踩坑的点,64位系统下指针是8字节,32位解析会直接导致地址无效崩溃。
这样就能完美实现iOS端把MTLTexture传递到Unity并显示的需求了。
内容的提问来源于stack exchange,提问作者uchar
相关产品推荐
相关产品推荐

