【Unity】二维坐标映射成ID

        在平面上,格子坐标通常是个二维坐标(X,Y),但是二维坐标有很多不方便的地方,且如果作为键值,其取值效率不高。因此大部分情况下,需要将二维坐标转换成ID来使用(且能从ID转换回坐标)。

        常用的方式就是X*N+Y,N为一个足够大的数。但是这种方式有问题,其只能支持全正数或者全负数,一旦有正有负,就会坐标转换失败。因此需要一种较为便捷的算法,能将二维坐标映射成ID,且能互相转换。

1、简述

        基本原理如下图所示:

         这就是ID的生成顺序,以一个螺旋形状进行生成。

        这种生成方式的优点之一,便是可以仅仅通过转换出来的ID就能判定其里坐标原点的距离,存数组的时候可以视作有序。缺点便是其性能并不是最优。

2、代码

        原理没什么好说的,就是纯计算。直接上代码:

        2.1 : 坐标转成ID

        public int ToInt(Vector2Int grid)
        {
            if (grid.x == 0 && grid.y == 0) return 0;

            int k = math.max(math.abs(grid.x), math.abs(grid.y));
            if (grid.x > grid.y)
                return 4 * k * k + 1 + 2 * k + grid.x + grid.y;
            else
                return 4 * k * k + 1 - 2 * k - grid.x - grid.y;
        }

        2.2: ID转换回坐标

        ID转换回坐标略复杂一些,代码如下:

        public Vector2Int GetMapGrid(int index)
        {
            if (index == 0) return Vector2Int.zero;
            float sqrtX = math.sqrt(index);
            int k = (int)((sqrtX + 1) / 2);
            if (sqrtX > 2 * k)
            {
                int xAy = index - (4 * k * k + 1) - 2 * k;
                if (xAy < 0)
                {
                    int y = -1 * k;
                    int x = xAy - y;
                    return new Vector2Int(x, y);
                }
                else
                {
                    int x = k;
                    int y = xAy - x;
                    return new Vector2Int(x, y);
                }
            }
            else
            {
                int xAy = (4 * k * k + 1) - index - 2 * k;
                if (xAy < 0)
                {
                    int x = -k;
                    int y = xAy - x;
                    return new Vector2Int(x, y);
                }
                else
                {
                    int y = k;
                    int x = xAy - y;
                    return new Vector2Int(x, y);
                }
            }
        }

3、使用Long实现

        当然,还有一种其他的方法可以实现二维坐标转ID。原理简单,就是用一个long(int64)来储存,前32存x,后32位存y。这种处理方式很重要的一点,就是要避免进行加减法计算,只能使用位运算进行拼接。

        代码如下:

        public long GetID(int q, int r)
        {
            long rt = (long)q << 32;
            rt = rt | (r & 0xffffffff);
            return rt;
        }

        public Vector2Int GetCoordinate(long id)
        {
            int x = (int)(id >> 32);
            int y = (int)id;
            return new Vector2Int(x, y);
        }

        这个方法的缺点,就是转换后的值会变得特别大,而且不能仅通过观察数值大小就能确定其距离坐标原点的远近。

        优点是理解容易,且性能更佳。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Unity中,将三维坐标转换为二维坐标需要使用Camera的ScreenToWorldPoint函数。该函数可以将屏幕上的点转换为世界坐标。 首先,你需要获取相机的引用。可以使用Camera.main来获取场景中的主摄像机,或者通过其他方式获取你想要使用的摄像机。 然后,使用Camera.WorldToScreenPoint函数将目标三维坐标转换为屏幕坐标。这个函数接受一个Vector3参数,表示世界坐标。例如,如果你有一个名为targetPosition的Vector3变量,你可以这样调用函数: ```csharp Vector3 screenPoint = Camera.main.WorldToScreenPoint(targetPosition); ``` 这将把目标位置从世界坐标系转换为屏幕坐标系。 最后,如果你需要将屏幕坐标转换为UI坐标(Canvas坐标),你还需要考虑到Canvas的缩放因素。可以使用RectTransformUtility.ScreenPointToLocalPointInRectangle函数将屏幕坐标转换为UI坐标。这个函数接受一个RectTransform参数,表示UI元素的RectTransform组件,以及一个屏幕坐标。 例如,如果你有一个名为canvas的Canvas对象,并且有一个名为uiElement的UI元素,你可以这样调用函数: ```csharp Vector2 localPoint; RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.transform as RectTransform, screenPoint, Camera.main, out localPoint); ``` 现在,localPoint将包含UI元素的坐标,可以在Canvas上使用它来定位UI元素。 这样,你就可以将三维坐标转换为二维坐标,并在Unity中实现相应的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值