飞道的博客

Unity游戏副本地图制作

474人阅读  评论(0)

之前所讲到的制作地图方式都是使用在全局大地图中。因为人物永远都在地图的中心。如图:

  

更多内容关注:unity风雨路

但是有些游戏副本中的主角人物不是一直处在地图中心,而是可以看到副本的整个地图。角色只是处在大地图中的某个坐标位置。这种地图的制作实现也有所不同。

接下来讲如何实现:看到副本的整个地图场景,角色可以移动到与地图相对的任何坐标位置并非一直在地图中心。如下图:

 

举个例子:有一个场景是副本内的场景。副本场景就是下图中的的建筑区(绿色草地只是背景)

 

因此副本的地图是这样:就是建筑物区域的俯视图,一张图片而已。如下:

 

新建一个Plane和材质球,将该图赋值给材质球,然后材质球给Plane上。并且将Plane的layer设置为Map。

将plane位置放置对齐到该场景。但一定要放置到场景地下,这样就不会干扰场景显示。

 

接着选择MiniMapCamera设置大小和位置恰好看到整个场景。可以从预览里调整位置大小来参考。

注意:一定要调整到可以看到地图的全貌。这是最佳位置。如下:

      

 

一定要记住这个时候的相机size。因为这个值就是我们之前讲到的大地图的尺寸。把它拷贝过来。

 

 

这个时候运行测试发现:显示出小地图中的plan位置变了。。。因为我们的代码中小地图相机是时刻跟随主角的。现在主角的位置在场景的边沿,相机当然会跟随的到这个位置。

    

本节我们关心的是大地图,小地图不做处理。但此时点开大地图也是和小地图中显示的相同的。

因此我们要将大地图中相机位置代码删除。删这句 minicamera.transform.position = new Vector3(player.position.x, minicamera.transform.position.y, player.position.z);。

并且给大地图初始化赋值。

所以我们需要在每一次打开大地图的时候对相机位置进行初始化。定义变量public Vector3 startPos = Vector3.zero;//相机初始位置

然后初始化的时候赋值。 startPos = minicamera.transform.position;//初始化小地图位置。

全部代码如下:


  
  1. using UnityEngine;
  2. using System.Collections;
  3. public class testmin : MonoBehaviour {
  4. public Camera minicamera;
  5. public Transform player;
  6. public Transform miniplayerIcon; //小地图人物图标
  7. public Transform maxplayerIcon;
  8. private float mapSize; //小地图的orthographicSize大小
  9. public float Maxmapsize; //大地图的orthographicSize大小
  10. public float minSize; //小地图的orthographicSize最小值
  11. public float maxSize; //小地图的orthographicSize最大值
  12. public GameObject maxmap; //大地图
  13. public GameObject minimap; //小地图
  14. public Vector3 startPos = Vector3.zero; //小地图初始位置
  15. public bool isMaxmap = false; //是否打开大地图
  16. void Awake()
  17. {
  18. mapSize = minicamera.orthographicSize;
  19. }
  20. // Use this for initialization
  21. void Start () {
  22. }
  23. // Update is called once per frame
  24. void Update () {
  25. if (isMaxmap)
  26. {
  27. minicamera.transform.position = startPos;初始化大地图位置
  28. maxplayerIcon.eulerAngles = new Vector3( 0, 0, -player.eulerAngles.y); //地图中的人物图标会根据3D物体的人物转动而转动
  29. }
  30. else
  31. {
  32. minicamera.transform.position = new Vector3(player.position.x, minicamera.transform.position.y, player.position.z);
  33. miniplayerIcon.eulerAngles = new Vector3( 0, 0, -player.eulerAngles.y);
  34. }
  35. }
  36. //打开大地图
  37. public void OpenMaxmap()
  38. {
  39. maxmap.gameObject.SetActive( true);
  40. minimap.gameObject.SetActive( false);
  41. minicamera.orthographicSize = Maxmapsize;
  42. isMaxmap = true;
  43. }
  44. //打开小地图
  45. public void OpenMinimap()
  46. {
  47. maxmap.gameObject.SetActive( false);
  48. minimap.gameObject.SetActive( true);
  49. minicamera.orthographicSize = mapSize;
  50. isMaxmap = false;
  51. }
  52. //缩放地图方法
  53. public void ChangeMapSize(float value)
  54. {
  55. mapSize += value;
  56. mapSize = Mathf.Clamp(mapSize, minSize, maxSize);
  57. minicamera.orthographicSize = mapSize;
  58. }
  59. }

注意要给初始位置赋值,赋值就是上面提到的相机最佳位置坐标

 

所以现在打开大地图后会显示最佳位置。

但是此时的大地图中人物标记只能旋转,不能移动。因为我们此刻只有旋转代码 maxplayerIcon.eulerAngles = new Vector3(0, 0, -player.eulerAngles.y);//地图中的人物图标会根据3D物体的人物转动而转动。

接下来就是让图标跟着3D场景人物移动而移动。

要知道,现在我们能够看到的界面是2D的,是一个窗口UI界面。而相机看到的主角是在3D的场景中。。。要让相机中主角的位置从3D的位置转化到2D的相对位置需要用到一个方法WorldToViewportPoint(player.position)。

关键语句:minicamera.WorldToViewportPoint(player.position);//从世界坐标变成viewport坐标 

所以定义一个变量ptScreen ,一个3D场景转化为窗口视图坐标: private Vector3 ptScreen = Vector3.zero;//转化为窗口视图坐标

而3D场景中转化到界面上的坐标就是:

 ptScreen = minicamera.WorldToViewportPoint(player.position);//从世界坐标变成viewport坐标

注意:2D窗口指的是整个UI窗口。它是从左下角为起点(0,0),右上角为(1,1)

因此ptScreen的坐标最大就是(1,1),也就是UI的右上角。

现在要做的是让角色图标显示在大地图中的位置,而不是整个UI中的位置。所以我们要通过大地图的尺寸与整个UI坐标的比例来算出角色图标显示在大地图中的比例位置

注意是比例位置。

用X轴来做例子

整个UI的位置是从0到1,也就是大小是1*1,而大地图的尺寸是700*700。也就是说按比例算大地图是转化过来的坐标长度的700倍

但是大地图是处在整个UI的分辨率中的,而且大地图现在是在整个UI的中心,假如整个UI的分辨率是1366*768。

拿UI起止点(0,0)做例子

  因为大地图在UI中心,所以大地图的起始点是从整个UI界面起始点加上这个:(1366-700)/2;Y是(768-700)/2           

如下图:两个起始点直接的距离。

 

那么角色图标最终位置就是:

maxplayerIcon.position = new Vector3(ptScreen.x * 700 + (1366-700)/2, ptScreen.y * 700 +(768-700)/2);

上面只是一个具体的例子用1366*768的分辨率做例子方便理解。

通用的代码是

 maxplayerIcon.position = new Vector3((ptScreen.x * maxmap.GetComponent<RectTransform>().sizeDelta.x)+(Screen.width - maxmap.GetComponent<RectTransform>().sizeDelta.x)/2,
                 (ptScreen.y * maxmap.GetComponent<RectTransform>().sizeDelta.y+(Screen.height - maxmap.GetComponent<RectTransform>().sizeDelta.y)/2), 0);//大地图人物图标的位置

 

解释就是在转化过来的坐标点乘以大地图的尺寸,然后加上大地图与整个UI起始点的差值。

所以最终代码是:


  
  1. using UnityEngine;
  2. using System.Collections;
  3. public class testmin : MonoBehaviour {
  4. public Camera minicamera;
  5. public Transform player;
  6. public Transform miniplayerIcon; //小地图人物图标
  7. public Transform maxplayerIcon;
  8. private float mapSize; //小地图的orthographicSize大小
  9. public float Maxmapsize; //大地图的orthographicSize大小
  10. public float minSize; //小地图的orthographicSize最小值
  11. public float maxSize; //小地图的orthographicSize最大值
  12. public GameObject maxmap; //大地图
  13. public GameObject minimap; //小地图
  14. public Vector3 startPos = Vector3.zero; //小地图初始位置
  15. private Vector3 ptScreen = Vector3.zero; //转化为窗口视图坐标
  16. public bool isMaxmap = false; //是否打开大地图
  17. void Awake()
  18. {
  19. mapSize = minicamera.orthographicSize;
  20. }
  21. // Use this for initialization
  22. void Start () {
  23. }
  24. // Update is called once per frame
  25. void Update () {
  26. if (isMaxmap)
  27. {
  28. minicamera.transform.position = startPos;初始化大地图位置
  29. ptScreen = minicamera.WorldToViewportPoint(player.position); //从世界坐标变成viewport坐标
  30. //大地图在中心,所以大地图的起始点的x是从整个界面起始点加上这个:(1366-700)/2;Y是(768-700)/2
  31. Debug.Log( "屏幕大小" + Screen.width + Screen.height);
  32. // maxplayerIcon.position = new Vector3(ptScreen.x * 700 + (1366-700)/2, ptScreen.y * 700 + (768-700)/2);//1366*768的例子
  33. //通用分辩率
  34. maxplayerIcon.position = new Vector3((ptScreen.x * maxmap.GetComponent<RectTransform>().sizeDelta.x) + (Screen.width - maxmap.GetComponent<RectTransform>().sizeDelta.x) / 2,
  35. (ptScreen.y * maxmap.GetComponent<RectTransform>().sizeDelta.y + (Screen.height - maxmap.GetComponent<RectTransform>().sizeDelta.y) / 2), 0); //大地图人物图标的位置
  36. Debug.Log( "地图大小" + maxmap.GetComponent<RectTransform>().sizeDelta.x);
  37. maxplayerIcon.eulerAngles = new Vector3( 0, 0, -player.eulerAngles.y); //地图中的人物图标会根据3D物体的人物转动而转动
  38. }
  39. else
  40. {
  41. minicamera.transform.position = new Vector3(player.position.x, minicamera.transform.position.y, player.position.z);
  42. miniplayerIcon.eulerAngles = new Vector3( 0, 0, -player.eulerAngles.y);
  43. }
  44. }
  45. //打开大地图
  46. public void OpenMaxmap()
  47. {
  48. maxmap.gameObject.SetActive( true);
  49. minimap.gameObject.SetActive( false);
  50. minicamera.orthographicSize = Maxmapsize;
  51. isMaxmap = true;
  52. }
  53. //打开小地图
  54. public void OpenMinimap()
  55. {
  56. maxmap.gameObject.SetActive( false);
  57. minimap.gameObject.SetActive( true);
  58. minicamera.orthographicSize = mapSize;
  59. isMaxmap = false;
  60. }
  61. //缩放地图方法
  62. public void ChangeMapSize(float value)
  63. {
  64. mapSize += value;
  65. mapSize = Mathf.Clamp(mapSize, minSize, maxSize);
  66. minicamera.orthographicSize = mapSize;
  67. }
  68. }

这样就实现了角色图标在大地图中的移动显示。如图:

 


转载:https://blog.csdn.net/alayeshi/article/details/116063841
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场