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