Unity3D第三人称无锁定视角实现

来源:互联网 发布:js删除一个div内容 编辑:程序博客网 时间:2024/04/28 12:29
     博客,对程序员来说应该是个特殊、特别的词汇,尤其是对于俺----这只只知道默默的呆在教室的一角,偶尔45度望望天空,装装文艺的小程序猿,不只是为了把程序运行成功后的那份激动分享出来,更希望能在这茫茫人海中寻得一二位情深潭水、志趣相投的好友,举杯畅饮,起舞邀月,所谓梦想用在,踏歌长行嘛!一直有动笔写博客的冲动,可总是在一个令人欲哭无泪的懒惰面前,只道一句洗洗睡吧,热情便所剩无几了,最终还是迟迟未能落笔,最近接了个小小的项目,为了能更好的与小组内的伙伴间交流,最终下定决心,开敲!

    先来总结一下之前学Unity学到的一个非常重要的例子,如题,关于这部分的研究,网络上已经有太多的大神贡献出他们的才能了,我非常非常有幸,在暑假的时候结识了一位,看过他的博文,真叫一个字,爽!接下来要贴的代码,完全出自他,我只是在他们的代码上添加了几行注释,在这边写下来只为了自己总结,如果诸君对代码有兴趣,可以直接联系原博主(秦元培:http://blog.csdn.net/qinyuanpei/article/details/39125353)

    实现第三人称无锁定需要人物和摄像机的配合,人物脚本只需要完成移动,摄像机脚本负责摄像机的旋转、移动、距离的缩放、以及对人物旋转。

    下面是我的人物的脚本:只实现移动,用的是新版本的动画组件Animator

<pre name="code" class="csharp">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<Animator>();chaCon = GetComponent<CharacterController>();}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如下图
<img src="http://img.blog.csdn.net/20141127200100909?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTcwNzA3Ng==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />
接下来就是摄像机的代码了,相对于人物仅仅只实现移动,摄像机做的工作要复杂一点,总结来看,共有三点:
1.右键控制摄像机旋转,包括水平、竖直两个方向。
2.鼠标滑轮控制摄像机距人物的距离
3.控制角色的旋转
需要注意的是,旋转范围,水平无限制,竖直方向上比较合适的范围是5-45度,5度是为了不让摄像机透过水平地面,45度是为了防止摄像机移过人头
具体代码如下:
<pre name="code" class="csharp">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





    

0 0
原创粉丝点击