Unity中接入高德地图时的消息处理(IOS)

发表于2017-05-16
评论3 4.7k浏览
最近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临时保存。 
详细代码 
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;
}
2:在Classes/Unity/UnityRendering.h中的UnityDisplaySurfaceMTL结构声明中,添加 OBJC_OBJECT_PTR MTLTextureRef lastSystemColorRB,用来保存上一帧渲染Texture。 
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)
3: 在每次渲染前保存lastSystemColorRB。修改Classes/Unity/MetalHelper.mm的StartFrameRenderingMTL函数 
在 surface->systemColorRB = [surface->drawable texture] 后面添加 
surface->lastSystemColorRB = surface->systemColorRB。

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引