Unity中接入高德地图时的消息处理(IOS)
发表于2017-05-16
最近LBS很火,研究了一下Unity中接入高德地图,普通接入都很简单,按照高德地图官方API逐步实现即可,最后在处理点击消息的时候费了点劲,最后终于找到找到了接入高德地图时的消息处理方法,在这里和大家交流一下。抛砖引玉。
问题
程序中有两个UIView,高德地图的View在下层,Unity的View在上层,当鼠标点击到Unity中的UI或其他对象时,Unity截获点击消息,否则高德地图处理点击消息。
环境
unity 5+ 底层渲染接口为metal(默认)
基本思路
1:因为通常情况下Unity界面总是需要在高德地图的上层,所以只要实现UnityView的PointInside接口。
2:在点击坐标处判断metal texture的透明度,如果透明度大于0,则表示点击了Unity对象,返回TRUE,响应消息。否则返回FALSE,这样下层的高德地图继续响应消息。
3:注意两点,一是要对PointInside传入的坐标做转换处理。二是Unity是不保存每次渲染的Metal Texture的,所以我们需要将上一帧的Texture临时保存。
详细代码
2:在Classes/Unity/UnityRendering.h中的UnityDisplaySurfaceMTL结构声明中,添加 OBJC_OBJECT_PTR MTLTextureRef lastSystemColorRB,用来保存上一帧渲染Texture。
3: 在每次渲染前保存lastSystemColorRB。修改Classes/Unity/MetalHelper.mm的StartFrameRenderingMTL函数
在 surface->systemColorRB = [surface->drawable texture] 后面添加
surface->lastSystemColorRB = surface->systemColorRB。
问题
程序中有两个UIView,高德地图的View在下层,Unity的View在上层,当鼠标点击到Unity中的UI或其他对象时,Unity截获点击消息,否则高德地图处理点击消息。
环境
unity 5+ 底层渲染接口为metal(默认)
基本思路
1:因为通常情况下Unity界面总是需要在高德地图的上层,所以只要实现UnityView的PointInside接口。
2:在点击坐标处判断metal texture的透明度,如果透明度大于0,则表示点击了Unity对象,返回TRUE,响应消息。否则返回FALSE,这样下层的高德地图继续响应消息。
3:注意两点,一是要对PointInside传入的坐标做转换处理。二是Unity是不保存每次渲染的Metal Texture的,所以我们需要将上一帧的Texture临时保存。
详细代码
1:在Classes/UI/UnityView.mm中添加函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *) event { //判断一下渲染API是否为metal,OpenGLES暂未实现 if (UnitySelectedRenderingAPI() == apiMetal) { // 获取渲染surface UnityDisplaySurfaceMTL* surf = (UnityDisplaySurfaceMTL*)GetMainDisplaySurface(); // 渲染surface尺寸 CGSize s = c.drawableSize; // 得到点击坐标 CGPoint p = [self convertPoint:point toView:self]; // 坐标转换 CGFloat bw = self.bounds.size.width; CGFloat bh = self.bounds.size.height; CGFloat box = self.bounds.origin.x; CGFloat boy = self.bounds.origin.y; CGFloat x = (p.x - box)/bw * s.width; CGFloat y = (p.y - boy)/bh * s.height; // 得到上一次渲染的Texture MTLTextureRef lastTex = surf->lastSystemColorRB; // 获取Texture中此坐标的颜色值 MTLRegion region = MTLRegionMake2D(x, y, 1, 1); Byte byteBuff[4]; [lastTex getBytes:byteBuff bytesPerRow:_surfaceSize.width*4 fromRegion:region mipmapLevel:0]; // 判断Alpha值 int a = byteBuff[3]; if (a > 0 ) { return YES; } else { return NO; } } return YES; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | // Metal display surface START_STRUCT(UnityDisplaySurfaceMTL, UnityDisplaySurfaceBase) OBJC_OBJECT_PTR CAMetalLayer* layer; OBJC_OBJECT_PTR MTLDeviceRef device; OBJC_OBJECT_PTR MTLCommandQueueRef commandQueue; OBJC_OBJECT_PTR CAMetalDrawableRef drawable; OBJC_OBJECT_PTR MTLTextureRef systemColorRB; OBJC_OBJECT_PTR MTLTextureRef targetColorRT; OBJC_OBJECT_PTR MTLTextureRef targetAAColorRT; OBJC_OBJECT_PTR MTLTextureRef depthRB; OBJC_OBJECT_PTR MTLTextureRef stencilRB; unsigned colorFormat; // [MTLPixelFormat] unsigned depthFormat; // [MTLPixelFormat] // add here OBJC_OBJECT_PTR MTLTextureRef lastSystemColorRB; END_STRUCT(UnityDisplaySurfaceMTL) |
在 surface->systemColorRB = [surface->drawable texture] 后面添加
surface->lastSystemColorRB = surface->systemColorRB。