unity摄像机投影

摄像机分为两种,一种是正交摄像机还有一种是透视摄像机。正交摄像机无论远近它的视口范围永远是固定的,但是透视摄像机是由原点向外扩散性发射,也就是距离越远它的视口区域也就越大。那么我们如何获取距离摄像机任意距离的视口区域呢?如下图所示,分别用红色和黄色两种颜色将计算出来的视口区域标记了出来。

Unity3D研究院之获取摄像机的视口区域 - 雨松MOMO程序研究院 - 1

 

下面上代码,把如下脚本挂在摄像机出直接运行游戏即可看到。

using UnityEngine;
using System.Collections;

public class Demo : MonoBehaviour
{


    private Camera theCamera;

    //距离摄像机8.5米 用黄色表示
    public float upperDistance = 1.0f;
    //距离摄像机30米 用红色表示
    public float lowerDistance = 20.0f;

    private Transform tx;

    private bool isFirst = true;
    void Start()
    {
        if (!theCamera)
        {
            theCamera = Camera.main;
        }
        tx = theCamera.transform;
    }


    void Update()
    {
        FindUpperCorners();
        FindLowerCorners();
    }


    void FindUpperCorners()
    {
        Vector3[] corners = GetCorners(upperDistance);

        // for debugging
        Debug.DrawLine(corners[0], corners[1], Color.yellow); // UpperLeft -> UpperRight
        Debug.DrawLine(corners[1], corners[3], Color.yellow); // UpperRight -> LowerRight
        Debug.DrawLine(corners[3], corners[2], Color.yellow); // LowerRight -> LowerLeft
        Debug.DrawLine(corners[2], corners[0], Color.yellow); // LowerLeft -> UpperLeft
    }


    void FindLowerCorners()
    {
        Vector3[] corners = GetCorners(lowerDistance);

        // for debugging
        Debug.DrawLine(corners[0], corners[1], Color.red);
        Debug.DrawLine(corners[1], corners[3], Color.red);
        Debug.DrawLine(corners[3], corners[2], Color.red);
        Debug.DrawLine(corners[2], corners[0], Color.red);

        //if (isFirst == false)
        //    return;
        Vector3 cornersFirst = (corners[0] + corners[1])/2;
        Vector3 cornersSecord = (corners[2] + corners[3])/2;
        Vector3 finalCorners = (cornersFirst + cornersSecord) / 2;
        Debug.LogWarning("finalCorners.x = " + finalCorners.x + ",finalCorners.y =" + finalCorners.y + ",finalCorners.z = " + finalCorners.z);

        GameObject obj = GameObject.FindWithTag("BattleBg");
        obj.transform.position = finalCorners;

        GameObject cameraParent = GameObject.Find("SmartCamera");
        if (null == cameraParent)
            return;


        Debug.LogWarning("world , UpperLeft, corners[0].x = " + corners[0].x + ",[0].y = " + corners[0].y + ",[0].z = " + corners[0].z);
        Debug.LogWarning("world , UpperRight, corners[1].x = " + corners[1].x + ",[1].y = " + corners[1].y + ",[1].z = " + corners[1].z);
        Debug.LogWarning("world,  LowerLeft,  corners[2].x = " + corners[2].x + ",[2].y = " + corners[2].y + ",[2].z = " + corners[2].z);
        Debug.LogWarning("world , LowerRight,corners[3].x = " + corners[3].x + ",[3].y = " + corners[3].y + ",[3].z = " + corners[3].z);

        Vector3 screenPoint1 = Camera.main.WorldToScreenPoint(corners[0]);
        Vector3 screenPoint2 = Camera.main.WorldToScreenPoint(corners[1]);
        Vector3 screenPoint3 = Camera.main.WorldToScreenPoint(corners[2]);
        Vector3 screenPoint4 = Camera.main.WorldToScreenPoint(corners[3]);

        Debug.LogWarning("screen , UpperLeft,  screenPoint1.x = " + screenPoint1.x + ",y = " + screenPoint1.y + ",z = " + screenPoint1.z);
        Debug.LogWarning("screen , UpperRight, screenPoint2.x = " + screenPoint2.x + ",y = " + screenPoint2.y + ",z = " + screenPoint2.z);
        Debug.LogWarning("screen,  LowerLeft,  screenPoint3.x = " + screenPoint3.x + ",y = " + screenPoint3.y + ",z = " + screenPoint3.z);
        Debug.LogWarning("screen , LowerRight, screenPoint4.x = " + screenPoint4.x + ",y = " + screenPoint4.y + ",z = " + screenPoint4.z);

        Vector3 meshVec = obj.GetComponent<MeshFilter>().mesh.bounds.size;
        Vector3 meshRender = obj.GetComponent<MeshRenderer>().bounds.size;

        //Old
        Quaternion quaternion = cameraParent.transform.rotation;
        Vector3 euler = quaternion.eulerAngles;
        Vector3 finalVec = new Vector3(90 - euler.x, euler.y - 180, euler.z);
        quaternion = Quaternion.Euler(finalVec);
        obj.transform.rotation = quaternion;

        //New error
        //obj.transform.LookAt(cameraParent.transform);
        //Quaternion quaternion = obj.transform.rotation;
        //Vector3 euler = quaternion.eulerAngles;
        //Vector3 finalVec = new Vector3(euler.x , euler.y , euler.z);
        //quaternion = Quaternion.Euler(finalVec);
        //obj.transform.rotation = quaternion;

        //TODO
        //obj.transform.localScale = new Vector3(2.81f, 1f, 1.27f);
        float finalHeight = 1.27f;
        float finalWidth = theCamera.aspect * finalHeight;
        
        obj.transform.localScale = new Vector3(finalWidth, 1f, finalHeight);
        //isFirst =false;
    }


    Vector3[] GetCorners(float distance)
    {
        Vector3[] corners = new Vector3[4];

        float halfFOV = (theCamera.fieldOfView * 0.5f) * Mathf.Deg2Rad;
        float aspect = theCamera.aspect;

        float height = distance * Mathf.Tan(halfFOV);
        float width = height * aspect;

        // UpperLeft
        corners[0] = tx.position - (tx.right * width);
        corners[0] += tx.up * height;
        corners[0] += tx.forward * distance;

        // UpperRight
        corners[1] = tx.position + (tx.right * width);
        corners[1] += tx.up * height;
        corners[1] += tx.forward * distance;

        // LowerLeft
        corners[2] = tx.position - (tx.right * width);
        corners[2] -= tx.up * height;
        corners[2] += tx.forward * distance;

        // LowerRight
        corners[3] = tx.position + (tx.right * width);
        corners[3] -= tx.up * height;
        corners[3] += tx.forward * distance;

        return corners;
    }
}


这个脚本是我在逛国外网站无意间发现的,我这里翻译成了C#语言。http://answers.unity3d.com/questions/509466/scale-box-collider-to-camera-view-1.html?sort=oldest

我们可以根据文章里的算法计算出视口3D的坐标点,有了坐标信息那么想干什么都好干了,呵呵。

 

### Unity摄像机的使用与设置 在 Unity 中,Camera 是一个非常重要的组件,它负责捕捉并呈现游戏世界中的觉内容。以下是关于 Unity 摄像机的一些常见用法和设置: #### 基本配置 在项目中调整摄像机的基础属性可以通过 `Project Settings->Other Settings->Configuration` 进行全局设定[^1]。然而更具体的摄像机参数通常是在 Inspector 板中完成。 - **Projection (投影模式)** 可以选择 Perspective 或 Orthographic 投影方式。Perspective 提供透效果,适合大多数 3D 场景;Orthographic 则提供平行投影,适用于 UI 显示或某些特殊角需求。 - **Field of View (场角)** 当 Projection 设置为 Perspective 时生效,定义了摄像机野的角度范围,默认值为 60 度。较大的数值会产生更强的广角变形效果。 - **Clipping Planes (裁剪平)** 包括 Near 和 Far 裁剪距离,决定了哪些物体能够进入摄像机线范围内。合理设置这些值有助于提高渲染效率以及防止不必要的 Z-fighting 效果。 - **Clear Flags & Background Color** Clear Flags 控制每帧绘制之前如何清理屏幕缓冲区。可以选择 Solid Color, Skybox 等选项来定制背景样式。 #### 性能优化建议 对于希望改善性能的游戏开发者来说,减少 Update 方法内的逻辑处理次数至关重要[^2]。如果存在多个相机实例,则需注意它们各自的 culling mask 属性分配情况以免造成额外开销。另外利用 Light Probes 结合静态烘焙技术也能有效降低动态光源计算负担。 #### 多分辨率适配方案 考虑到不同设备间显示比例可能存在较大差异,在设计阶段统一按照某一标准尺寸比如768×1024来进行布局规划很有必要[^3]。针对高像素密度显示屏如Retina屏或者最新款iPhone机型所支持的@2x,@3x资源版本管理机制也应充分考虑进去以便获得更好的画质表现同时兼顾兼容性问题。 ```csharp // 示例代码展示如何切换正交/透模式 public class CameraSwitcher : MonoBehaviour { public bool isOrtho; void Start() { Camera cam = GetComponent<Camera>(); if(cam != null){ cam.orthographic = isOrtho; } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值