Unity小地图功能(纯UI,不加相机)

需求分析

  1. 小地图图片可以用场景相机在高空,正交视图截图得到(如果不是多层地图);
  2. 缩略图需要遮罩。地图图片是它的子物体;
  3. 然后是确定显示区域显示地图图片的哪一块,玩家标在哪;
  4. 地图图片和玩家图标的朝向,可能是地图摆正,或者玩家图标摆正;
  5. 数据管理上,小地图图片和大地图预制体绑定,二者可放在一个文件夹,为了截图小地图需要一个放有大地图的专门场景;

小地图图片的制作

场景相机向下看,并且正交。保证所有地图在相机的旋转有统一的标准,比如默认是世界z轴朝相机上方。

制作小地图的场景需要光线充足,没有雾,没有影子。为了不破坏游戏场景,应该给每个地图专门建一个场景制作小地图。

地图、玩家图标的位置、朝向

小地图一般不会显示整个地图,小地图图片在遮罩里是移动的。如果玩家图标在遮罩里也是移动的,机制就比较复杂,把玩家图标固定在中心是个比较简单的机制。

旋转朝向,也有地图旋转和玩家旋转两种机制。一般玩家旋转用得比较多。

玩家图标在中心,小地图移动

计算小地图位置

玩家图标不是小地图的子对象。需要移动的是小地图,需要计算的是小地图的位置。找地图上两个点,得到场景里这两个点的世界位置(x、z坐标)和地图上的点在中心时小地图的局部位置,建立对应关系。手动定位参考点难免有误差,但是这两个参考点越远,误差就越小。这两个参考点应该尽量

世界位置小地图局部位置
(0,0)(59.5,194.4)
(20.265,28.48)(-234.3,-215.1)

计算世界位置到小地图局部位置的倍率

kx=(59.5-(-234.3))/(-20.265)=k1;

kz=(miniRef1.y-miniRef2.y)/(worldRef1.y-worldRef2.y)

小地图锚点坐标公式

x=miniRef1.x+(player.transform.position.x - worldRef1.x) * kx

y=miniRef1.y+(player.transform.position.z - worldRef1.y) * kz

这里倍率项是加号,尽管玩家在世界的移动方向和小地图的移动方向相反,但计算倍率时倍率已经是负数。

计算玩家图标旋转

是把玩家世界欧拉角的y轴复制给玩家图标局部欧拉角的z轴,加负号。

代码

public class Minimap : MonoSingleton<Minimap>
    {
        public Image imageMap, imagPlayerIcon;
        public Vector2 miniRef1, miniRef2;
        public Vector2 worldRef1, worldRef2;
        float kx, kz;
        RectTransform mapRect;
        Transform player;
        const int updatePeriod = 8;
        void Start()
        {
            kx = (miniRef1.x - miniRef2.x) / (worldRef1.x - worldRef2.x);
            kz = (miniRef1.y - miniRef2.y) / (worldRef1.y - worldRef2.y);
            mapRect = imageMap.transform as RectTransform;
            player = MyInput.Instance.player.transform;
        }

        void Update()
        {
            if (Time.frameCount % updatePeriod == 0)
            {
                mapRect.anchoredPosition = new Vector2(
                    miniRef1.x + (player.position.x - worldRef1.x) * kx,
                    miniRef1.y + (player.position.z - worldRef1.y) * kz);
                imagPlayerIcon.transform.localEulerAngles=new Vector3(0,0,-player.localEulerAngles.y);
            }
        }
    }

数据管理

一个场景的小地图数据需要一个图片和4个Vector2坐标,世界坐标和小地图局部坐标各2个。如果一个场景一个小地图,适合放在场景文件夹(也就是放光照烘焙数据、遮挡剔除的文件夹)。如果多个场景共用一个地图,小地图配置和地图放在一起。

把这一套数据做成ScriptableObject配置数据

[CreateAssetMenu(menuName = "Custom/小地图配置")]
    public class MiniMapSO : ScriptableObject
    {
        public Sprite minimap;
        public Vector2 miniRef1, miniRef2;
        public Vector2 worldRef1, worldRef2;
    }

然后发现直接把这些数据在场景里配置好,比读取ScriptableObject要方便。

扩展

现在我们想在小地图上标注更多东西,比如发现的敌人、关卡起始点。之前我们把玩家图标固定在小地图范围中心,让小地图图片移动。现在其他物体的图标应该放在什么层级?不妨放在小地图图片的子级。我们需要一个根据物体的世界坐标计算出小地图局部坐标的公式,还有该物体在小地图上图标的Sprite。小地图类的一个函数接受世界坐标和图标,显示。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值