查看: 3882|回复: 4
打印 上一主题 下一主题

[教程] 从一个摄像头脚本说起

[复制链接]

21

主题

7

听众

651

积分

初级设计师

Rank: 3Rank: 3

纳金币
0
精华
3

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

跳转到指定楼层
楼主
发表于 2012-11-12 23:44:20 |只看该作者 |倒序浏览
          有时我们需要编写一个摄像头全方位观察角色的脚本,却苦于难以入手。这时,我们可以根据有关脚本来做一番修改。
        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);
      
        }
}


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




分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

2317

主题

54

听众

2万

积分

资深设计师

Rank: 7Rank: 7Rank: 7

纳金币
20645
精华
62

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

沙发
发表于 2012-11-13 00:44:05 |只看该作者
很好的分析与介绍,这个脚本的效果很不错。感谢大神的教程!
回复

使用道具 举报

may    

8830

主题

81

听众

7万

积分

首席设计师

Rank: 8Rank: 8

纳金币
52352
精华
343

最佳新人 热心会员 灌水之王 活跃会员 突出贡献 荣誉管理 论坛元老

板凳
发表于 2012-11-30 03:55:10 |只看该作者
支持一下楼主
回复

使用道具 举报

0

主题

1

听众

329

积分

设计实习生

Rank: 2

纳金币
2
精华
0

最佳新人

地板
发表于 2013-12-28 23:33:45 |只看该作者
呵呵,学习了!
回复

使用道具 举报

1

主题

1

听众

77

积分

设计初学者

Rank: 1

纳金币
21
精华
0
5#
发表于 2015-11-14 19:01:14 |只看该作者
学习学习
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

手机版|纳金网 ( 闽ICP备2021016425号-2/3

GMT+8, 2025-7-22 15:35 , Processed in 0.068521 second(s), 31 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部