纳金网

标题: 从一个摄像头脚本说起 [打印本页]

作者: wyb314    时间: 2012-11-12 23:44
标题: 从一个摄像头脚本说起
          有时我们需要编写一个摄像头全方位观察角色的脚本,却苦于难以入手。这时,我们可以根据有关脚本来做一番修改。
        Unity3D中的标准资源包Scripts中有一个脚本MouseOrbit.js,我们就可以从这个脚本下手。由于这个脚本是用js写的,我个人习惯用C#写脚本,所以我将其“翻译了一下”,代码奉上:

using UnityEngine;
using System.Collections;

public class MouseOrbit : MonoBehaviour {
    public Transform target ;
    public float distance = 10.0f;
    //摄像头距离target的距离,也可以动态的进行调节
    public float xSpeed = 250.0f;
    public float ySpeed = 120.0f;
    //这两个值时再程序运行时慢慢调节出来的,你可以根据你想要的效果来进行适当的调节

    public float yMinLimit = -20f;
    public float yMaxLimit = 80f;
    //限制摄像头的仰角在-20°到80°之间

    private float x = 0.0f;
    private float y = 0.0f;
       
        void Start () {



        Vector3 angles = transform.eulerAngles;//获取


        x = angles.y;


        y = angles.x;





        if (rigidbody){


              rigidbody.freezeRotation = ***e;


        }




        }
        void LateUpdate () {



        if (target)


        {


            x += Input.GetAxis("Mouse X") * xSpeed * 0.02f;//获取鼠标左键的偏移量,并对其大小进行规范化


            y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;





            y = ClampAngle(y, yMinLimit, yMaxLimit);//由于我们需要鼠标竖直方向移动时的角度可能大于360°,所以调用了这个工具函数。





            var rotation = Quaternion.Euler(y, x, 0);//求得旋转角,


            var position = rotation * (new Vector3(0.0f, 0.0f, -distance)) + target.position;





            transform.rotation = rotation;


            transform.position = position;


        }



        }
    static float ClampAngle ( float angle,float min ,float max ) {//工具函数,专门用来限制angle的值在min与max之间
            if (angle < -360f)
                    angle += 360f;
            if (angle > 360f)
                    angle -= 360f;
            return Mathf.Clamp (angle, min, max);
    }
}


这个脚本实现了摄像头在一定的范围内观察物体。由于通常我们使用鼠标右键拖拽时才实现这种功能,如果我们现在需要在鼠标右键单击拖拽时,实现此种观察,那么我们应该怎么做呢?鼠标右键拖拽导致摄像头的旋转,由于官方代码没有加入“鼠标右键拖拽”功能,所以我们首先得解决鼠标右键拖拽这个令人棘手的问题。鼠标右键,还要拖拽时才能改变x,y这两个值。所以我们可以这样做:

            if(Input.GetMouseButton(1))
            {
                x += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
                y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
            }

也就是在鼠标右键点击时改变x,y的值。我们随便建立一个场景,并以一个Cube来作为target ,然后调节一下摄像机的视角 。我们运行一下,发现还真的实现了此种功能。那假如我们还需要动态调节摄像头与target的距离时,我们又该怎么做呢?一般来说,我们通常使用鼠标滚轮来缩放距离,那我们就有这样一句代码:

distance *= (1 - 1 * Input.GetAxis("Mouse ScrollWheel"))或
distance +=Input.GetAxis("Mouse ScrollWheel") * 5.0f  注意:这个5.0f是我随便写的,你可以用一个公有成员变量表示,然后再Inspector面板中动态的调节以达到你想要的效果。一运行,果然达到了这个效果。那我们现在要是不想拉得很远,而且摄像机距离角色的距离还不能近到一定的程度,该怎么写代码?其实,官方脚本已经告诉了我们思路了,那个Y是怎么限制的,我们就怎么限制distance。所以我们只需仿照着工具函数ClampAngle 写一个工具函数ClampDistance,事情就能够轻易解决了,当然我们需要定义两个变量minDistance与maxDistance。那么代码实现我就留给读者自己去想吧。另外,我自己改编了另外的一个脚本也同样实现了摄像头全方位或者半全方位观察物体的脚本,代码奉上:


using UnityEngine;
using System.Collections;

public class CustomCamera : MonoBehaviour {

    public Transform target;
    private Transform cam;
   
    private float cameraRotSide;
    private float cameraRotUp;
    private float cameraRotSideCur;
    private float cameraRotUpCur;
    private float distance = 5.0f;

        void Start () {
        cam = transform;
        cameraRotSide = transform.eulerAngles.y;
        cameraRotSideCur = transform.eulerAngles.y;
        cameraRotUp = transform.eulerAngles.x;
        cameraRotUpCur = transform.eulerAngles.x;
    }
       
        void Update () {
        if (Input.GetMouseButton(1))
        {
            cameraRotSide += Input.GetAxis("Mouse X") * 5;
            cameraRotUp -= Input.GetAxis("Mouse Y") * 5;
        }
        cameraRotSideCur = Mathf.LerpAngle(cameraRotSideCur, cameraRotSide, Time.deltaTime * 5);
        cameraRotUpCur = Mathf.Lerp(cameraRotUpCur, cameraRotUp, Time.deltaTime * 5);

        distance *= (1 - 1 * Input.GetAxis("Mouse ScrollWheel"));

        Quaternion rotation_Y = Quaternion.Euler(cameraRotUpCur, cameraRotSideCur, 0);
        cam.position = target.position + rotation_Y*(-Vector3.forward)*distance ;
        cam.LookAt(target);
      
        }
}


有兴趣的读者可以研究一下。假如我们想在一定范围内利用鼠标移动控制摄像头的位置,而且鼠标右键拖拽时摄像头不移动,但是摄像头却可以全方位或者半方位旋转,这个代码该怎么写?有兴趣的读者可以试一下,应该不难。我想我们现在应该可以写出一些很不错的摄像头控制脚本吧!





作者: 王者再临    时间: 2012-11-13 00:44
很好的分析与介绍,这个脚本的效果很不错。感谢大神的教程!

作者: may    时间: 2012-11-30 03:55
支持一下楼主
作者: nianhua2008    时间: 2013-12-28 23:33
呵呵,学习了!
作者: HFKuang    时间: 2015-11-14 19:01
学习学习




欢迎光临 纳金网 (http://go.narkii.com/club/) Powered by Discuz! X2.5