在手机上实现第三人称视角与在电脑上并无太大区别,只不过需要检测屏幕触碰以及滑动等问题。大体思路就是,在每一帧的开头,将Camera放到target的位置上等待进行旋转,获取到每一帧手指滑动的位移值,再按照位移值进行相应的旋转,最后Camera向自身z轴负方向平移以设置距离。
在一开始获取手指滑动的位移值时,我采取了两位置相减的方式,即在获取到每一帧开始和结束时手指的位置,然后用结束时的位置减去开始时的位置得到一个向量,此向量即为手指的位移,然而Touch里面已经使用deltaPosition为我们提供了手指触摸位置距离上一次检测时的该变量,当我们在Update里面使用它时,就会得到每一帧手指位置的改变量,最后我发现使用Input.GetAxis("Mouse Y") 和Input.GetAxis("Mouse X") 也可以达到手指的位移值,然而使用deltaPosition是最简便的。Ok,镜头旋转思路有了,镜头距离控制该怎么实现?我们可以在屏幕获得两个触控点的时候进行距离控制,思路是这样的,先获得两个触点开始时的距离,再获得两个触点移动后的距离,用移动后的距离减去移动前的距离来得出两个触点的相对移动,通过这个数值,我们可以判断两个触点的移动是相互靠近了还是相互远离了,然后把这个数值乘以灵敏度并累加到现有的距离上来从新设置距离。这个思路不错,但是实际运行时,我们发现只要两触点间的距离大于初始距离,不管两触点怎么移动,视角距离都会不断变大的现象,因此,我们在每一帧视角距离设置完毕后再次获取一下当前两触点间的距离就可以了。
下面来看一看实现代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ThirdPersonView_Android : MonoBehaviour {
public GameObject target;//目标物体
float Xsensitivity=0.5f;//视角X轴旋转灵敏度
float Ysensitivity=0.5f;//视角Y轴旋转灵敏度
//将X轴旋转角度限制在-45度和80度之间,因计算机程序可以识别的角度为0~360,故将-45度设置为315度
float Xrot_limit1 = 80;//旋转限制角度1
float Xrot_limit2 = 315;//限制旋转角度2
Vector3 rot;//手指位移向量
float Xrot, Yrot;//视角两个轴的旋转值
float distance = 2f;//Camera与target的距离
float dis1;//两个触点移动前的距离
float dis2;//两个触点移动后的距离
float dis3;//两个触点间距离的改变量
float distance_sensitivity = 0.003f;//设置Camera距离的灵敏度
float max_distance = 10f;//Camera最大距离
float min_distance = 2f;//Camera最小距离
// Use this for initialization
void Start ()
{
//如果Camera自身X轴的初始旋转角度大于80度并小于等于270度,则将其X轴旋转到80度位置
if (transform.localEulerAngles.x > Xrot_limit1 && transform.localEulerAngles.x<=270)
{
transform.Rotate(Xrot_limit1 - transform.localEulerAngles.x, 0, 0);
}
//如果Camera自身X轴的初始旋转角度大于270度并小于315度,则将其X轴旋转到315度位置,即-45度位置
else if (transform.localEulerAngles.x < Xrot_limit2 && transform.localEulerAngles.x > 270)
{
transform.Rotate(Xrot_limit2 - transform.localEulerAngles.x, 0, 0);
}
}
// Update is called once per frame
void Update () {
//将Camera放在target的位置上等待旋转
transform.position = target.transform.position;
//如果屏幕仅收到一个触控点信息
if (Input.touchCount == 1)
{
//如果检测到此触控点的状态时正在滑动
if (Input.GetTouch(0).phase == TouchPhase.Moved)
{
//将触控点上一帧的位移赋给位移向量rot
rot = Input.GetTouch(0).deltaPosition;
//视角X轴将要旋转的值等于其现在X轴的旋转值加上负的触控点Y轴的位移量乘以灵敏度,因为我们需要手指上划时视角抬头,故此处是负的
Xrot = transform.localEulerAngles.x - rot.y * Xsensitivity;
//视角Y轴将要旋转的值等于其现在Y轴的旋转值加上触控点X轴的位移量乘以灵敏度
Yrot = transform.localEulerAngles.y + rot.x * Ysensitivity;
//当视角X轴将要旋转的值小于等于80度或者大于等于315度时(即为其处于-45度到80度的范围时)
if (Xrot <= Xrot_limit1 || Xrot >= Xrot_limit2)
{
//把视角将要旋转的值化为四元数
Quaternion aaaaa = Quaternion.Euler(Xrot, Yrot, 0);
//将四元式赋值给Camera的rotation,完成旋转
transform.rotation = aaaaa;
}
//当视角X轴将要旋转的值处于80度和315度之间时,保持视角现有的X轴旋转角度不变,只旋转其Y轴(此举是为了防止视角在X轴限制的极限位置时,斜向滑动手指视角Y轴不随着旋转)
else if (Xrot > Xrot_limit1 && Xrot < Xrot_limit2)
{
//在视角处于X轴极限旋转位置时,视角X轴旋转值不变,仅Y轴旋转值改变,将其转化为四元数
Quaternion aaaaa = Quaternion.Euler(transform.localEulerAngles.x , Yrot, 0);
//将四元式赋值给Camera的rotation,完成旋转
transform.rotation = aaaaa;
}
}
}
setDistance();//调用设置Camera与target距离的函数以设置其距离
}
void setDistance()
{
//如果检测到两个触点
if (Input.touchCount == 2)
{
//如果第二个触点的状态是刚开始
if (Input.GetTouch(1).phase == TouchPhase.Began)
{
//获取两个触点的距离并赋值给dis1,此为触点移动前的距离
dis1 = Vector2.Distance(Input.GetTouch(0).position,Input.GetTouch(1).position);
}
//获取两个触点的距离并赋值给dis2,此为两个触点移动后的距离
dis2 = Vector2.Distance(Input.GetTouch(0).position, Input.GetTouch(1).position);
//两个触点间距离改变量
dis3 = dis2 - dis1;
//新的视角距离等于原有距离减去两个触点间距离的改变量与灵敏度乘积的差,此处为减去是因为我们希望两触点对向移动镜头拉远,两手指背向移动镜头拉近,若为加则效果相反
distance -= dis3 * distance_sensitivity;
//将视角距离限制在min_distance和max_distance的范围之内
distance = Mathf.Clamp(distance, min_distance, max_distance);
}
//camera平移,完成距离设置
transform.Translate(Vector3.back*distance);
//获取这一帧Camera设置完距离后的两触点间的距离,以实现下一帧只要两触点发生相对移动就会实时设置Camera距离
dis1 = Vector2.Distance(Input.GetTouch(0).position, Input.GetTouch(1).position);
}
}