Unity中接入高德地图时的消息处理(IOS)
blazeandice
blazeandice 11484 33
精华热门加亮 脚本 2016-10-13 16: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临时保存。
详细代码
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
40
- (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。
2条评分, 鲜花+55
分享:
游客
要评论请先登录 或者 注册
33条回应 只看楼主 最新
赢泽天下 学徒 2016-11-01 16:08 1楼
好。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
feifirkiss 学徒 2016-11-16 17:27 2楼
楼主牛,现在项目正在研究这个,以后遇见问题要请教楼主了。
datian123 学徒 2016-11-30 13:10 3楼
发个非官方广告覆盖
锈掉的螺丝钉 新手 2016-12-14 14:21 4楼
怎么才能让高德地图的界面显示在最底层呢?并且还能显示unity中的控件呢
ycxdr02 学徒 2016-12-17 15:46 5楼
鬼地方个功夫功夫给对方搞定给对方
sunlwendy 学徒 2016-12-23 12:09 6楼
楼主有研究高德Android与unity的交互么
cgatian 新手 2016-12-27 16:42 7楼
楼主牛,现在项目正在研究这个,以后遇见问题要请教楼主了。
yxriyin 师者 2017-01-03 10:34 8楼
有安卓版吗 楼主
13701644318 学徒 2017-01-04 15:53 9楼
楼主厉害,标记一下,以后用得到~
1 2 3 4
返回顶部