需求分析
- 小地图图片可以用场景相机在高空,正交视图截图得到(如果不是多层地图);
- 缩略图需要遮罩。地图图片是它的子物体;
- 然后是确定显示区域显示地图图片的哪一块,玩家标在哪;
- 地图图片和玩家图标的朝向,可能是地图摆正,或者玩家图标摆正;
- 数据管理上,小地图图片和大地图预制体绑定,二者可放在一个文件夹,为了截图小地图需要一个放有大地图的专门场景;
小地图图片的制作
场景相机向下看,并且正交。保证所有地图在相机的旋转有统一的标准,比如默认是世界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。小地图类的一个函数接受世界坐标和图标,显示。
1万+

被折叠的 条评论
为什么被折叠?



