多点触摸+摄像机旋转拉伸学习笔记

using UnityEngine;
using System.Collections;

public class Move : MonoBehaviour {

	// Use this for initialization
    [SerializeField]
    Transform Target;//目标物体
    [SerializeField]
    float distance = 10f;//摄像机与目标物体的距离,Z轴负方向是远离目标,正方向是靠近目标(当然是对于本例子)
    [SerializeField]
    float xScale = 2.40f;//对应旋转角度的系数,鼠标位移*系数 = 旋转角度
    [SerializeField]
    float yScale = 5.0f;//对应旋转角度的系数
    [SerializeField]
    float yMinLimit = 0f;//垂直移动,也就是绕x轴移动,最小范围,在Unity中一边移动,一边尝试
    [SerializeField]
    float yMaxLimit = 180f;//最大范围

    [SerializeField]
    float x = 0;//水平方向的旋转角度
    [SerializeField]
    float y = 0;//垂直方向的旋转角度

    Vector2 oldPosition1;
    Vector2 oldPosition2;

	void Start () {
        Vector3 angles = transform.eulerAngles;
        x = angles.x;
        y = angles.y;
        if (rigidbody)
        {
            rigidbody.freezeRotation = true;
        }
	}
	
	// Update is called once per frame
	void Update () {

        if (Input.touchCount == 1)//单点触摸时,可以让摄像机围绕物体旋转
        {
            if (Input.GetTouch(0).phase == TouchPhase.Moved)
            {
                x += Input.GetAxis("Mouse X") * xScale;//屏幕x方向拖动,是沿y轴旋转,另外注意,角度是累加的
                y -= Input.GetAxis("Mouse Y") * yScale;//屏幕y方向拖动,是沿x轴旋转
            }
        }
        else if(Input.GetMouseButton(0))//鼠标左键可以控制
        {
            x += Input.GetAxis("Mouse X") * xScale;
            y -= Input.GetAxis("Mouse Y") * yScale;
        }
        if (Input.touchCount > 1)
        {
            //这里很巧妙,只要一个手指一动,就算形成手势,这个很巧妙
            if (Input.GetTouch(0).phase == TouchPhase.Moved || Input.GetTouch(1).phase == TouchPhase.Moved)
            {
                Vector2 tempPos1 = Input.GetTouch(0).position;
                Vector2 tempPos2 = Input.GetTouch(1).position;
                if(isEnlarge(oldPosition1,oldPosition2,tempPos1,tempPos2))
                {
                    if(distance>3f)
                    {
                        distance -=0.5f;
                    }
                }
                else
                {
                    if(distance<18.5f)
                    {
                        distance += 0.5f;
                    }
                }
                oldPosition1 = tempPos1;
                oldPosition2 = tempPos2;
            }
        }
	}
    /// <summary>
    /// 比较之前的两个手指距离, 和新的两个手指的距离,看看变化
    /// </summary>
    /// <param name="op1"></param>
    /// <param name="op2"></param>
    /// <param name="np1"></param>
    /// <param name="np2"></param>
    /// <returns></returns>
    bool isEnlarge(Vector2 op1, Vector2 op2, Vector2 np1, Vector2 np2)
    {
        float leng1 = (op1 - op2).magnitude;//取模运算
        float leng2 = (np1 - np2).magnitude;
        if (leng1 < leng2)
        {
            return true;
        }
        else 
        {
            return false;
        }

    }
    void LateUpdate()//在update之后每一帧都会调用该函数
    {
        if (Target)
        {
            //确定垂直方向的范围
            y = ClampAngle(y, yMinLimit, yMaxLimit);
            //摄像机始终要面朝物体,所以需要旋转
            //将欧拉角转换为旋转使用的四元数,表示沿x轴方(竖直)向旋转y度,沿y轴(水平)方向旋转x度
            Quaternion rotation = Quaternion.Euler(y, x, 0);
            //将向量 (其实就是有物体指向摄像机的向量)按照这个四元数旋转 + 物体坐标(世界坐标系) = 摄像机的位置 
            //另外,这个乘法,和四元数的数学乘法有点区别啊,不是完全一样的
            Vector3 position = rotation * (new Vector3(0f, 0f, -distance)) + Target.position;

            //物体rotation的定义是:The rotation of the transform in world space stored as a Quaternion.物体在世界坐标系的,以四元数方式存储的旋转
            //所以,我们改变这个值,就是改变了摄像机的朝向
            transform.rotation = rotation;
            //光有朝向没有用,还要有正确的位置
            transform.position = position;
        }
    }
    static float ClampAngle(float angle, float min, float max)
    {
        //放置旋转太猛,直接翻几个跟头
        if (angle < -360)
            angle += 30;
        if (angle > 360)
            angle -= 360;
        return Mathf.Clamp(angle,min,max);
    }
}

摄像机沿Z轴正方向正对物体


摄像机和物体的位置关系



参考: 代码参考:http://www.xuanyusong.com/archives/512

      四元数参考:http://www.cnblogs.com/Mrt-02/archive/2011/10/15/2213656.html

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值