先来总结一下之前学Unity学到的一个非常重要的例子,如题,关于这部分的研究,网络上已经有太多的大神贡献出他们的才能了,我非常非常有幸,在暑假的时候结识了一位,看过他的博文,真叫一个字,爽!接下来要贴的代码,完全出自他,我只是在他们的代码上添加了几行注释,在这边写下来只为了自己总结,如果诸君对代码有兴趣,可以直接联系原博主(秦元培:http://blog.csdn.net/qinyuanpei/article/details/39125353)
实现第三人称无锁定需要人物和摄像机的配合,人物脚本只需要完成移动,摄像机脚本负责摄像机的旋转、移动、距离的缩放、以及对人物旋转。
下面是我的人物的脚本:只实现移动,用的是新版本的动画组件Animator
using UnityEngine;
using System.Collections;
public class TEST : MonoBehaviour
{
public float mSpeed=1.5f;
private Animator animator=null;
private CharacterController chaCon;
void Start ()
{
animator = GetComponent();
chaCon = GetComponent();
}
void Update ()
{
Vector3 mDir = Vector3.zero;
float v = Input.GetAxis("Vertical");
float h = Input.GetAxis("Horizontal");
animator.SetFloat ("valY", v, 0.25f, Time.deltaTime);
animator.SetFloat ("valX", h, 0.25f, Time.deltaTime);
if (v < -0.2)
{
//transform.Translate (-Vector3.forward * Time.deltaTime * mSpeed);
mDir=-Vector3.forward * Time.deltaTime * mSpeed;
}
else if (v > 0.2)
{
mDir=Vector3.forward*Time.deltaTime*mSpeed;
}
if (h< -0.2)
{
mDir = Vector3.left*Time.deltaTime*mSpeed;
}
else if (h > 0.2)
{
mDir = Vector3.right*Time.deltaTime*mSpeed;
}
//考虑重力因素
mDir=transform.TransformDirection(mDir);
float y=mDir.y-Gravity *Time.deltaTime;
mDir=new Vector3(mDir.x,y,mDir.z);
chaCon.Move(mDir);
}
}
其中角色AnimatorContrller相关部分Blend Tree如下图
接下来就是摄像机的代码了,相对于人物仅仅只实现移动,摄像机做的工作要复杂一点,总结来看,共有三点:
1.右键控制摄像机旋转,包括水平、竖直两个方向。
2.鼠标滑轮控制摄像机距人物的距离
3.控制角色的旋转
需要注意的是,旋转范围,水平无限制,竖直方向上比较合适的范围是5-45度,5度是为了不让摄像机透过水平地面,45度是为了防止摄像机移过人头
具体代码如下:
using UnityEngine;
using System.Collections;
public class FreeView_Camera : MonoBehaviour {
//目标
public Transform target;
//距离
public float distance = 5f;
//右键旋转控制部分
//旋转速度
private float speedX = 240;
private float speedY = 120;
//Y轴旋转的角度限制
private float minLimitY = 5;
private float maxLimitY = 45;
//旋转角度
private float mX = 0.0f;
private float mY = 0.0f;
//鼠标缩放控制部分
//鼠标缩放距离最值
private float maxDistance = 10;
private float minDistance = 1.5f;
//鼠标缩放速度
private float zoomSpeed = 2f;
//差值控制部分
//是否启用差值计算
public bool isNeedDamping = false;
//差值速度
public float dampingSpeed = 10f;
private Quaternion mRotation;
private Vector3 mPosition;
void Start()
{
//初始化旋转角度
mX = transform.eulerAngles.x;
mY = transform.eulerAngles.y;
}
void LateUpdate()
{
//第一步(功能一):右键控制相机旋转部分
if (target != null && Input.GetMouseButton (1))
{
//1.获取鼠标输入
mX += Input.GetAxis("Mouse X")*speedX*0.02f;
mY -= Input.GetAxis("Mouse Y")*speedY*0.02f;
//1.1Y轴角度范围限制
//mY = ClampAngle(mY,minLimitY,maxLimitY);
mY = Mathf.Clamp(mY,minLimitY,maxLimitY);
//1.2计算旋转,转化成欧拉角
mRotation = Quaternion.Euler(mY,mX,0);
//2.旋转相机
//根据是否差值采取不同的角度计算方式,角度旋转的时候不用差值更自然
//if(isNeedDamping)
//transform.rotation = Quaternion.Lerp(transform.rotation,mRotation,Time.deltaTime*dampingSpeed);
//else
transform.rotation = mRotation;
//3.对目标物体的状态限定。不是所有的状态都可以旋转的,比如轻功时、战斗时就不可以旋转(去除物体本身旋转的可能)
target.rotation = Quaternion.Euler(new Vector3(0,mX,0)); //注意,这里mx中的X是针对鼠标的,实际上,在X平面上是绕着Y轴旋转
}
//第二步(功能二):鼠标滚轮缩放部分控制
distance -= Input.GetAxis ("Mouse ScrollWheel") * zoomSpeed;
distance = Mathf.Clamp (distance, minDistance, maxDistance);
//第三步(功能三):计算相机位置并进行设定
//这里出了个小问题,计算位置的时候,Y轴还是先别动了
mPosition = mRotation * new Vector3 (0.0f, 0.0f, -distance) + target.position;
if (isNeedDamping)
{
transform.position = Vector3.Lerp (transform.position, mPosition, Time.deltaTime * dampingSpeed);
}
else
{
transform.position = mPosition;
}
}
/*private float ClampAngle(float angle,float min,float max)
{
if (angle < 5)
angle += 5;
if (angle > 180)
angle -= 90;
return Mathf.Clamp (angle, min, max);//数值限制
}*/
}
/*Unity中Update和Lateupdate的区别。Lateupdate和Update每一祯都被执行,但是执行顺序不一样,先执行Updatee然后执行lateUpdate。
如果你有两个脚本JS1、JS2,两个脚本中都有Update()函数, 在JS1中有 lateUpdate ,JS2中没有。那么 lateUpdate 函数会等待JS1、JS2两个脚本的Update()函数 都执行完后才执行。也就是说, 如果现在有100个脚本,分别有100个 Update()函数,其中只有一个LateUpdate,那么在同一祯中,等待100个Update()执行完后,才执行这一个lateUpdate()。
这就是Unity这款引擎精妙之处,系统帮我们封装了多线程。 想一想曾经的Java单击游戏。 游戏主线程都是需要我们自己开。如果想实现Update LateUpdate 都需要自己去实现。官方这样做无疑是为开发好。就这个问题而言。Unity后台主线程将 Update LateUpdate 制作成两个多线程先去执行Update的线程,等Update 执行完毕后 在去执行LateUpdate线程。
*/
好吧,第一篇日志就这样结束吧,自己的内容不算太多,主要就是为了自己的总结,更多人物控制的思路、方法大家如果有兴趣推荐去看看秦元培大神的博客,那里记录着更多这方面值得我们探讨的地方,再贴一下大神的链接吧~
秦元培:http://blog.csdn.net/qinyuanpei/article/details/39125353