Unity3D 小地图(3) 实时同步相机可视区域

本文介绍了如何在Unity3D中实现小地图上实时同步相机可视区域。通过从相机四个角发出射线并计算与地形的交点,获取可视区域的比例,然后根据比例确定小地图上对应的位置,最终在小地图上绘制可视区域。
在小地图上同步摄像机的可视区域
基本可以分为这两个步骤
1,相机的可视区,找到相机四个角相应的世界位置
        从相机的四个角,发出四条射线,射向地面。
        建立一个数组存储射线与地面相交的四个点.
2,将相机可视区域同步到小地图中
        可视区域相对地形的位置 = 世界坐标 - 地形位置
        可视区域相对地形的比例 =  相对地形的位置/地形的宽高
        同步到小地图的可视区域 = 小地图的宽高*可视区域相对地形的比例

3,将比例得到的可视区域显示在小地图上面

从相机的四个角,发出四条射线,射向地面。


 Camera.main.ViewportPointToRay(Vector3.zero);

从摄像机的视图坐标发射一条射线,分别以 zero,up,one,right 来表示屏幕坐标系的(0,0),(1,0),(1,1),(0,1).

    RaycastHit hitOut;
    public Vector3[] rayPoint;
    public Terrain myTerrain;
	// Use this for initialization
	void Start () {
        //数组初始化赋值
        rayPoint = new Vector3[4];
        for (int i = 0; i < 4; i++)
        {
            rayPoint[i] = Vector3.zero;
        }
    }

    // Update is called once per frame
    void Update()
    {
        //从屏幕视图坐标向地面发射射线
        Ray zeroRay = Camera.main.ViewportPointToRay(Vector3.zero);
       
        Ray zeroToOneRay = Camera.main.ViewportPointToRay(Vector3.right);
        Ray oneToZeroRay = Camera.main.ViewportPointToRay(Vector3.up);
        Ray oneRay = Camera.main.ViewportPointToRay(Vector3.one);

        if (Physics.Raycast(zeroRay, out hitOut, 1000))
        {
            rayPoint[0] = hitOut.point;
        }

        if (Physics.Raycast(oneToZeroRay, out hitOut, 1000))
        {
            rayPoint[1] = hitOut.point;
        }

        if (Physics.Raycast(oneRay, out hitOut, 1000))
        {
            rayPoint[2] = hitOut.point;
        }

        if (Physics.Raycast(zeroToOneRay, out hitOut, 1000))
        {
            rayPoint[3] = hitOut.point;
        }
    }

发射射线的效果如图所示 


获取数组Point点再地图上的位置比例
        可视区域相对地形的位置 = 世界坐标 - 地形位置

        可视区域相对地形的比例 =  相对地形的位置/地形的宽高

    /// 获取第几个Point在地图上的比例
    /// </summary>
    /// <param name="index"></param>
    /// <returns></returns>
    public Vector2 GetRate(int index)
    {
        //没有意义,给Result一个初始化值
        Vector2 result = Vector2.zero;
        //防止越界
        index = index % rayPoint.Length;
       // Debug.Log(index);
        //Point相对于地形的位置
        Vector3 localToTerrain = rayPoint[index] - myTerrain.transform.position;
        //获取点在地形上的位置的比例
        result.x = localToTerrain.x / myTerrain.terrainData.size.x;
        result.y = localToTerrain.z / myTerrain.terrainData.size.z;

        return result;
    }

按Point点在地形上的比例激素那Point点在小地图上的位置

  同步到小地图的可视区域 = 小地图的宽高*可视区域相对地形的比例

 /// <summary>
/// <summary>
    /// 计算同步到小地图的位置
    /// </summary>
    /// <param name="index"></param>
    /// <returns></returns>
    public Vector2 CaculatePos(int index)
    {
        Vector2 result = Vector2.zero;
        Vector2 tmpRate = cameraView.GetRate(index);

        result.x = rectTrans.sizeDelta.x * tmpRate.x;
        result.y = rectTrans.sizeDelta.y * tmpRate.y;
        return result;
    }

在屏幕中画线,显示在小地图上方

 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();
        // Apply the line material
        lineMaterial.SetPass(0);
        GL.PushMatrix();
        GL.MultMatrix(transform.localToWorldMatrix);
        // Draw lines
        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();
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值