制作小地图,先添加一个Camera专门用来显示地图,设为正交相机,然后有两种制作方法。
直接使用地图相机
调整小地图Camera的Viewport Rect,比如设x为0.75,y为-0.75,让小地图位于右下角。采用这种方式,通过修改Camera的Depth,小地图相机显示区域会覆盖在最上层,小地图相机可以通过代码直接修改transform.position来跟随人物运动。如果希望点击小地图时,获得对应在场景中点击的位置,可以用小地图Camera来发射屏幕射线。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
void DragCheck()
{
if (MapCamera.pixelRect.Contains (Input.mousePosition)) {
Ray ray = MapCamera.ScreenPointToRay (Input.mousePosition);
RaycastHit hitInfo;
if (Physics.Raycast (ray, out hitInfo, 100, BattleMain.Instance.PlaneLayerMask)) {
Vector3 mapPosition = hitInfo.point;
Ray cameraCenterRay = battleCamera.ViewportPointToRay(new Vector3(0.5f, 0.5f));
RaycastHit cameraView;
Physics.Raycast(cameraCenterRay, out cameraView, Mathf.Infinity, BattleMain.Instance.PlaneLayerMask);
Vector3 camViewCenter = cameraView.point;
Vector3 camDestPos = mapPosition - camViewCenter;
camDestPos.y = 0;
battleCamera.transform.position += camDestPos;
}
}
}
|
通过上面的代码,点击小地图,可以移动主相机到点击的位置。使用这种方式的缺点很明显,即小地图的形状是方形的,而且不好加其它元素在小地图上。
还有,如果需要一个动态UI跟随场景中物体,比如血条,那么会发现血条始终位于小地图上面。解决的办法是,把显示血条的Canvas的Render Mode改为Screen Space Camera,然后计算UI的位置。
1
2
3
4
5
6
7
8
9
10
11
|
void AddHPBarForTowers()
{
Transform parentTransform;
Transform child;
GameObject HPBarObject = Instantiate (TowerHPBarPrefab) as GameObject;
HPBarObject.transform.SetParent (HPBarParent, false);
HPBar hp = HPBarObject.GetComponent<HPBar> ();
hp.Target = child;
hp.offset = new Vector3 (0, 3.4f, 0);
}
|
上面的代码用于动态添加血条Prefab到Canvas中,使用SetParent时需要添加额外第二个参数为false,可以保持原局部坐标和缩放。
1
2
3
4
5
6
|
void Update () {
Vector2 pos = battleCamera.WorldToScreenPoint (Target.position + offset);
pos.x -= battleCamera.pixelWidth* 0.5f;
pos.y -= battleCamera.pixelHeight * 0.5f;
GetComponent<RectTransform> ().anchoredPosition = pos;
}
|
上面的代码可以使Canvas中的血条位于人物顶部。如果主相机是正交相机,那么上面的代码需要改成下面的样子:
1
|
GetComponent<RectTransform>().anchoredPosition = pos/GetComponentInParent<Canvas>().scaleFactor;
|
使用 Render Texture
使用Render Texture,可以方便的制作圆形地图,但在小地图上点击后计算实际点击位置比较麻烦。即新建一个Render Texture,然后把小地图的Target Texture指向这张图片,小地图渲染的内容会显示在图片中,此时不需要修改Camera的Viewport Rect。然后,使用那张Render Texture,可以在Canvas中新建一个Raw Image来显示。
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
|
public Camera battleCamera; // 主透视相机
public Camera MapCamera; // 小地图正交相机
public GameObject MiniMap; // Canvas下的小地图组件,默认在右下角显示
void Update () {
if (Input.GetMouseButtonDown(0))
{
Rect miniMapRect = MiniMap.GetComponent<RectTransform>().rect;
Rect screenRect = new Rect(
MiniMap.transform.position.x - miniMapRect.width,
MiniMap.transform.position.y,
miniMapRect.width, miniMapRect.height);
if (screenRect.Contains(Input.mousePosition))
{
Vector3 mousePos = Input.mousePosition;
mousePos.x -= screenRect.x;
Vector3 mapClickPos = new Vector3(mousePos.x / screenRect.width, mousePos.y / screenRect.height);
Ray portaledRay = MapCamera.ViewportPointToRay(mapClickPos);
RaycastHit raycastHit;
if (Physics.Raycast(portaledRay, out raycastHit, Mathf.Infinity, BattleMain.Instance.PlaneLayerMask))
{
Vector3 mapPos = raycastHit.point;
Ray cameraCenterRay = battleCamera.ViewportPointToRay(new Vector3(0.5f, 0.5f));
RaycastHit hitInfo;
Physics.Raycast(cameraCenterRay, out hitInfo, Mathf.Infinity, BattleMain.Instance.PlaneLayerMask);
Vector3 camCenterPos = hitInfo.point;
Vector3 camDestPos = mapPos - camCenterPos;
camDestPos.y = 0;
battleCamera.transform.position += camDestPos;
}
}
}
}
|
上面的代码用于点击小地图后,让主相机移动到点击的位置处。