今日学习: 小地图区域显示
前几天学习了小地图,画符,今天又是小地图。不过这次的小地图跟上次不一样,是在小地图上显示摄像机照到地形的范围。
回顾一下,在上一个小地图中,用到了比例,在画符中,用到了GL,这次的这个小地图,结合了比例和GL,把摄像机照到的范围大小,映射到了摄像机上。
在场景中:
位置随意,将Image的轴心点改成(0,0)。
创建两个脚本:
CameraView(挂到MainCamera上)和MapView(挂到Image上)。
直接上代码:
以下是完整代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraView : MonoBehaviour
{
public Vector3[] rayPoints;
public Terrain terrain;
private void Start()
{
rayPoints = new Vector3[4];
for (int i = 0; i < 4; i++)
{
rayPoints[i] = Vector3.zero;
}
}
private void Update()
{
Ray tmpZeroRay = Camera.main.ViewportPointToRay(Vector3.zero);
//在Scene面板上画出射线轨迹
Debug.DrawRay(tmpZeroRay.origin, tmpZeroRay.direction, Color.red);
Ray oneToZeroRay = Camera.main.ViewportPointToRay(Vector3.right);
Debug.DrawRay(oneToZeroRay.origin, oneToZeroRay.direction, Color.blue);
Ray oneToOneRay = Camera.main.ViewportPointToRay(Vector3.one);
Debug.DrawRay(oneToOneRay.origin, oneToOneRay.direction, Color.green);
Ray zeroToOneRay = Camera.main.ViewportPointToRay(Vector3.up);
Debug.DrawRay(zeroToOneRay.origin, zeroToOneRay.direction, Color.yellow);
RaycastHit hitOut;
if(Physics.Raycast(tmpZeroRay ,out hitOut, 1000))
{
//射向的点的世界坐标
rayPoints[0] = hitOut.point;
}
if (Physics.Raycast(oneToZeroRay, out hitOut, 1000))
{
//射向的点的世界坐标
rayPoints[1] = hitOut.point;
}
if (Physics.Raycast(oneToOneRay, out hitOut, 1000))
{
//射向的点的世界坐标
rayPoints[2] = hitOut.point;
}
if (Physics.Raycast(zeroToOneRay, out hitOut, 1000))
{
//射向的点的世界坐标
rayPoints[3] = hitOut.point;
}
}
public Vector2 GetRate(int index)
{
Vector2 result = Vector2.zero;
//防止越界
index = index % rayPoints.Length;
Vector3 localToTerrain = rayPoints[index] - terrain.transform.position;
result.x = localToTerrain.x / terrain.terrainData.size.x;
result.y = localToTerrain.z / terrain.terrainData.size.z;
return result;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MapView : MonoBehaviour
{
CameraView cameraView;
RectTransform rectTransform;
private void Start()
{
cameraView = Camera.main.GetComponent<CameraView>();
rectTransform = transform.GetComponent<RectTransform>();
}
/// <summary>
/// 计算位置
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public Vector2 CaculatePos(int index)
{
Vector2 result = Vector2.zero;
Vector2 tmpRate = cameraView.GetRate(index);
result.x = rectTransform.sizeDelta.x * tmpRate.x;
result.y = rectTransform.sizeDelta.y * tmpRate.y;
return result;
}
static Material lineMaterial;
static void CreateLineMaterial()
{
if (!lineMaterial)
{
// Unity has a built-in shader that is useful for drawing
// simple colored things.
Shader shader = Shader.Find("Hidden/Internal-Colored");
lineMaterial = new Material(shader);
lineMaterial.hideFlags = HideFlags.HideAndDontSave;
// Turn on alpha blending
lineMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
lineMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
// Turn backface culling off
lineMaterial.SetInt("_Cull", (int)UnityEngine.Rendering.CullMode.Off);
// Turn off depth writes
lineMaterial.SetInt("_ZWrite", 0);
}
}
// Will be called after all regular rendering is done
public void OnRenderObject()
{
CreateLineMaterial();
lineMaterial.SetPass(0);
GL.PushMatrix();
GL.MultMatrix(transform.localToWorldMatrix);
//GL.LoadOrtho();
GL.Begin(GL.LINES);
GL.Color(Color.red);
for (int i = 1; i < 5; i++)
{
Vector2 tmpFront = CaculatePos(i - 1);
Vector2 tmpBack = CaculatePos(i);
GL.Vertex3(tmpFront .x,tmpFront .y ,0);
GL.Vertex3(tmpBack.x, tmpBack.y, 0);
}
GL.End();
GL.PopMatrix();
}
}
如果想在运行过程中操纵摄像机的移动,可以再写一个摄像机移动的脚本挂载到摄像机上。
今日,懒,不想动