[Unity3D]Unity3D游戏开发之自由视角下的角色控制

在开始今天的内容前,首先让我们来学习下Unity3D中较为重要的一部分知识,理解这些知识是我们开始学习今天内容的基础。

1、Input.GetAxis():该方法用于在Unity3D中根据坐标轴名称返回虚拟坐标系中的值,通常情况下,使用控制器和键盘输入时此值范围在-1到1之间。这段话怎么理解呢?我们来看下面这段脚本:

[csharp] view plaincopyprint?

  1. using UnityEngine;
  2. using System.Collections;
  3. public class example : MonoBehaviour {
  4. //水平速度
  5. public float HorizontalSpeed = 2.0F;
  6. //垂直速度
  7. public float VerticalSpeed = 2.0F;
  8. void Update()
  9. {
  10. //水平方向
  11. float h = HorizontalSpeed * Input.GetAxis("Mouse X");
  12. //垂直方向
  13. float v = VerticalSpeed * Input.GetAxis("Mouse Y");
  14. //旋转
  15. transform.Rotate(v, h, 0);
  16. }
  17. }

这 段脚本呢是根据鼠标的位置来旋转物体从而实现对物体的观察,从这段脚本中我们可以看出,通过获取输入轴的办法,我们可以获得鼠标移动的方向进而实现对于物 体的旋转控制。在Unity3D中我们可以通过Edit->Project Setting->Input来查看项目中的坐标轴名称:


在后面,我们还将使用这种方式,大家可以对这个方法有进一步的了解。

2、欧拉角eulerAngles:该值是Vector3类型的值,x、y、z分别代表绕x轴旋转x度,绕y轴旋转y度,绕z轴旋转z度。因此,该值最为直观的形式是可以允许我们直接以一个三维向量的形式来修改一个物体的角度,例如下面的脚本:

[html] view plaincopyprint?

  1. float mY = 5.0;
  2. void Update ()
  3. {
  4. mY += Input.GetAxis("Horizontal");
  5. transform.eulerAngles =new Vector3(0,mY, 0);
  6. }

如果你已经理解了上面的话,那么不出意外的,这段脚本会如你所愿的,按照鼠标在水平方向上移动的方向绕Y轴旋转。通常情况下,我们不会单独设置欧拉角其
中一个轴,例如eulerAngles.x =
10,因为这将导致偏移和不希望的旋转。当设置它们一个新的值时,要同时设置全部。好在我们可以通过Quaternion.Euler()方法将一个
Vector3类型的值转化为一个四元数,进而通过修改Transform.Rotation来实现相同的目的。

3、插值:所谓插值是指在离散数据的基础上补插连续函数,使得这条连续曲线通过全部给定的离散数据点。插值是离散函数逼近的重要方法,利用它可通过函数在有限个点处的取值状况,估算出函数在其他点处的近似值。在某些情况下,如果我们希望过程中处理得较为平滑,此时我们就可以使用插值的方法来实现对中间过程的模拟。在Unity3D中我们可以使用两种插值方法,即线性插值Lerp,球形插值SLerp。我们来看下面的脚本:

[csharp] view plaincopyprint?

  1. void Rotating (float horizontal, float vertical)
  2. {
  3. // Create a new vector of the horizontal and vertical inputs.
  4. Vector3 targetDirection = new Vector3(horizontal, 0f, vertical);
  5. // Create a rotation based on this new vector assuming that up is the global y axis.
  6. Quaternion targetRotation = Quaternion.LookRotation(targetDirection, Vector3.up);
  7. // Create a rotation that is an increment closer to the target rotation from the player‘s rotation.
  8. Quaternion newRotation = Quaternion.Lerp(rigidbody.rotation, targetRotation, turnSmoothing * Time.deltaTime);
  9. // Change the players rotation to this new rotation.
  10. rigidbody.MoveRotation(newRotation);
  11. }

插值的方法很简单,只要我们给出初始和结束的状态、时间就可以了,大家可以自己看API。

好了,有了这三部分的基础,我们就可以开始今天的内容了,今天的脚本分为两个部分,第一部分是角色控制的部分,主要负责的角色在场景中的移动、转身和动画
处理。第二部分是相机控制的部分,主要涉及相机旋转、相机缩放的相关内容。下面,我们分别来讲这两个部分,场景依然是博主自己在做的小游戏:

本次的主角呢,是博主非常喜欢的角色谢沧行,好了,我们回到今天的内容里吧!在第一部分,主要的是完成角色向各个方向的转身,这里博主定义四个方向(其实八个方向是一样的!),脚本如下:

[csharp] view plaincopyprint?

  1. using UnityEngine;
  2. using System.Collections;
  3. public class NoLockiVew_Player : MonoBehaviour {
  4. /*自由视角下的角色控制*/
  5. /*作者:秦元培*/
  6. //玩家的行走速度
  7. public float WalkSpeed=1.5F;
  8. //重力
  9. public float Gravity=20;
  10. //角色控制器
  11. private CharacterController mController;
  12. //动画组件
  13. private Animation mAnim;
  14. //玩家方向,默认向前
  15. private DirectionType mType=DirectionType.Direction_Forward;
  16. [HideInInspector]
  17. //玩家状态,默认为Idle
  18. public PlayerState State=PlayerState.Idle;
  19. //定义玩家的状态枚举
  20. public enum PlayerState
  21. {
  22. Idle,
  23. Walk
  24. }
  25. //定义四个方向的枚举值,按照逆时针方向计算
  26. protected enum DirectionType
  27. {
  28. Direction_Forward=90,
  29. Direction_Backward=270,
  30. Direction_Left=180,
  31. Direction_Right=0
  32. }
  33. void Start ()
  34. {
  35. //获取角色控制器
  36. mController=GetComponent<CharacterController>();
  37. //获取动画组件
  38. mAnim=GetComponentInChildren<Animation>();
  39. }
  40. void Update ()
  41. {
  42. MoveManager();
  43. //MouseEvent();
  44. }
  45. //玩家移动控制
  46. void MoveManager()
  47. {
  48. //移动方向
  49. Vector3 mDir=Vector3.zero;
  50. if(mController.isGrounded)
  51. {
  52. //将角色旋转到对应的方向
  53. if(Input.GetAxis("Vertical")==1)
  54. {
  55. SetDirection(DirectionType.Direction_Forward);
  56. mDir=Vector3.forward * Time.deltaTime * WalkSpeed;
  57. mAnim.CrossFade("Walk",0.25F);
  58. State=PlayerState.Walk;
  59. }
  60. if(Input.GetAxis("Vertical")==-1)
  61. {
  62. SetDirection(DirectionType.Direction_Backward);
  63. mDir=Vector3.forward * Time.deltaTime * WalkSpeed;
  64. mAnim.CrossFade("Walk",0.25F);
  65. State=PlayerState.Walk;
  66. }
  67. if(Input.GetAxis("Horizontal")==-1)
  68. {
  69. SetDirection(DirectionType.Direction_Left);
  70. mDir=Vector3.forward * Time.deltaTime * WalkSpeed;
  71. mAnim.CrossFade("Walk",0.25F);
  72. State=PlayerState.Walk;
  73. }
  74. if(Input.GetAxis("Horizontal")==1)
  75. {
  76. SetDirection(DirectionType.Direction_Right);
  77. mDir=Vector3.forward * Time.deltaTime * WalkSpeed;
  78. mAnim.CrossFade("Walk",0.25F);
  79. State=PlayerState.Walk;
  80. }
  81. //角色的Idle动画
  82. if(Input.GetAxis("Vertical")==0 && Input.GetAxis("Horizontal")==0)
  83. {
  84. mAnim.CrossFade("Idle",0.25F);
  85. State=PlayerState.Idle;
  86. }
  87. }
  88. //考虑重力因素
  89. mDir=transform.TransformDirection(mDir);
  90. float y=mDir.y-Gravity *Time.deltaTime;
  91. mDir=new Vector3(mDir.x,y,mDir.z);
  92. mController.Move(mDir);
  93. }
  94. //设置角色的方向,有问题
  95. void SetDirection(DirectionType mDir)
  96. {
  97. if(mType!=mDir)
  98. {
  99. transform.Rotate(Vector3.up*(mType-mDir));
  100. mType=mDir;
  101. }
  102. }
  103. }


里定义四个方向,是按照逆时针方向转的,相邻的两个方向间相差90度,所以我们只需要将当前的角度和目标角度相减就可以转到目标角度的方向(其实这是以前
写的代码,现在回头再看,直接用欧拉角似乎更为简单啊,呵呵)。这里主要的内容就是这样了。下面我们来看相机控制部分的代码吧,这里的代码参考了
MouseOrbit脚本,主要完成了鼠标右键旋转控制,博主在此基础上增加了相机缩放的代码。提到相机缩放,其实就是根据鼠标滚轮滚动的方向和大小重新
计算角色与相机的距离,与之类似地还有小地图的放缩,其实同样是通过修改距离来实现的。博主今天的一个体会是官方的代码能自己写一遍的最好自己写一遍,这
样好多东西就能在这个过程中给理解了。我们一起来看脚本

[csharp] view plaincopyprint?

  1. using UnityEngine;
  2. using System.Collections;
  3. public class NoLockView_Camera : MonoBehaviour
  4. {
  5. //观察目标
  6. public Transform Target;
  7. //观察距离
  8. public float Distance = 5F;
  9. //旋转速度
  10. private float SpeedX=240;
  11. private float SpeedY=120;
  12. //角度限制
  13. private float  MinLimitY = 5;
  14. private float  MaxLimitY = 180;
  15. //旋转角度
  16. private float mX = 0.0F;
  17. private float mY = 0.0F;
  18. //鼠标缩放距离最值
  19. private float MaxDistance=10;
  20. private float MinDistance=1.5F;
  21. //鼠标缩放速率
  22. private float ZoomSpeed=2F;
  23. //是否启用差值
  24. public bool isNeedDamping=true;
  25. //速度
  26. public float Damping=2.5F;
  27. void Start ()
  28. {
  29. //初始化旋转角度
  30. mX=transform.eulerAngles.x;
  31. mY=transform.eulerAngles.y;
  32. }
  33. void LateUpdate ()
  34. {
  35. //鼠标右键旋转
  36. if(Target!=null && Input.GetMouseButton(1))
  37. {
  38. //获取鼠标输入
  39. mX += Input.GetAxis("Mouse X") * SpeedX * 0.02F;
  40. mY -= Input.GetAxis("Mouse Y") * SpeedY * 0.02F;
  41. //范围限制
  42. mY = ClampAngle(mY,MinLimitY,MaxLimitY);
  43. }
  44. //鼠标滚轮缩放
  45. Distance-=Input.GetAxis("Mouse ScrollWheel") * ZoomSpeed;
  46. Distance=Mathf.Clamp(Distance,MinDistance,MaxDistance);
  47. //重新计算位置和角度
  48. Quaternion mRotation = Quaternion.Euler(mY, mX, 0);
  49. Vector3 mPosition = mRotation * new Vector3(0.0F, 0.0F, -Distance) + Target.position;
  50. //设置相机的角度和位置
  51. if(isNeedDamping){
  52. //球形插值
  53. transform.rotation = Quaternion.Lerp(transform.rotation,mRotation, Time.deltaTime*Damping);
  54. //线性插值
  55. transform.position = Vector3.Lerp(transform.position,mPosition, Time.deltaTime*Damping);
  56. }else{
  57. transform.rotation = mRotation;
  58. transform.position = mPosition;
  59. }
  60. //将玩家转到和相机对应的位置上
  61. if(Target.GetComponent<NoLockiVew_Player>().State==NoLockiVew_Player.PlayerState.Walk)
  62. {
  63. Target.eulerAngles=new Vector3(0,mX,0);
  64. }
  65. }
  66. private float  ClampAngle (float angle,float min,float max)
  67. {
  68. if (angle < -360) angle += 360;
  69. if (angle >  360) angle -= 360;
  70. return Mathf.Clamp (angle, min, max);
  71. }
  72. }

这里很多朋友可能对我设置一个状态很不理解吧,这其实是为了让玩家有一个自由查看角色的机会,否则当玩家按下鼠标右键的话,角色就会转向相机正对着的位置,这样玩家就看不到角色的正面了。当然,这里用到了插值,这样能使角色在转身的时候平滑一点,效果会更好。

唉,
不知不觉已经这个时候了,开学已经一周了,这学期我们只上九周课,然后就是实习、毕设、找工作一大堆事情在等着我们。可是不知道为什么博主宿舍的同学居然
还能每天什么事情都不做,从早上一直看电视剧到晚上十点,虽然这件事情和博主没有什么关系吧,可是整个宿舍的人都安安静静地做着自己的事情,就有这么一个
人整天声音开得很大在那里外放,这样真的好吗?以前和这个人闹过一次,因为他聚了一帮人在宿舍打麻将,我觉得吵就说了他一顿,结果就和我僵上了。说真的,
博主对目前的专业真的没有什么情感,大学四年里最让博主开心的事情就是博主学会了好多自己想要学的东西,认识了几个不错的老师和朋友,仅此而已。或许我们
注定要越走越远吧,因为我们根本就不是同一种人。


几天网上有人通过博客联系到博主,希望博主能到他哪里工作,可惜博主目前仍然有一大堆的琐事缠身,不然离开这喧嚣吵闹的宿舍,去做博主喜欢的事情,去寻找
博主自己的梦想,博主相信,博主一定可以做得更好吧。人生或许就是这样,你越是在乎的可能越让你得不到,你无心插柳可能会得到一片绿荫。对于未来,不管怎
么样,坦然面对就好了,博主改变不了周围的这群人,只能努力地去改变自己。好了,晚安吧!

时间: 2024-07-30 02:37:07

[Unity3D]Unity3D游戏开发之自由视角下的角色控制的相关文章

Unity3D游戏开发之自由视角状态下的角色控制

在上一篇文章Unity3D游戏开发之基于Trigger的触发式动画设计一文中,博主与大家分享自己在这方面方面的一些感悟.今天呢,我们来探讨Unity3D角色控制的内容,如图是博主非常喜欢的<古剑奇谭>游戏截图,在这款游戏中就使用了博主今天要讲解的自由视角,所谓自由视角是指玩家可以按照自身坐标系向着四个不同的方向移动,当玩家按下鼠标右键时,可以绕Y轴按照一定的角度旋转摄像机,在旋转的过程中,角色将旋转相应的角度.在移动的过程中,摄像机会保持与玩家间的一定距离,然后跟随角色进行移动.好了,下面我们

Unity3D游戏开发之自由视角状态下的角色控制(二)

在测试Unity3D游戏开发之自由视角状态下的角色控制这个项目的时候意外地发现了一个Bug.Bug出现在如下位置: [csharp] view plaincopyprint? //设置玩家跟随角度 if(Target.GetComponent<NoLockiVew_Player>().State==NoLockiVew_Player.PlayerState.Walk) { Target.rotation=Quaternion.Euler(new Vector3(0,mX,0)); } 该方法主

《Unity3D/2D游戏开发从0到1》正式出版发行啦

书籍信息:   书籍的名称: <Unity3D/2D 游戏开发从0到1>   书号(ISBN): 978-7-121-26239-5    出版社: 电子工业出版社   发行时间:2015年7月1日 写作背景:    2015年6月30日我收到电子工业出版社张迪老师寄来,正式发行的<Unity3D/2D游戏开发从0到1>书籍.这本凝结着大半年心血的作品让我感慨万千.   本人从事游戏.软件与教学十多年,一直梦想可以进一步服务于全国广大的游戏与软件从业开发人员.14年下半年电子工业出

Unity3D 入门 游戏开发 Unity3D portal game development

Unity3D 入门 游戏开发 Unity3D portal game development 作者:韩梦飞沙 Author:han_meng_fei_sha 邮箱:[email protected] E-mail: 313134555 @qq.com 视频学习链接:Video learning link: [教学视频]深入浅出Unity3D--第一篇-何韬-CSDN学院-在线学习教程 u3d 4.6 c#  性能上 比 java脚本 好一些 C # is better than a Java

《Unity3D/2D游戏开发从0到1》正式出版发行

去年个人编写的Unity书籍正式在2015年7月正式发行,现在补充介绍一下个人著作.书籍信息: 书籍的名称: <Unity3D/2D 游戏开发从0到1> 书号(ISBN): 978-7-121-26239-5 出版社: 电子工业出版社 发行时间:2015年7月1日 写作背景: 2015年6月30日我收到电子工业出版社张迪老师寄来,正式发行的<Unity3D/2D游戏开发从0到1>书籍.这本凝结着大半年心血的作品让我感慨万千. 本人从事游戏.软件与教学十多年,一直梦想可以进一步服务于

Unity3D ARPG游戏开发《最初的幻想》之第一张地图与跳跃的改善详解

前面我们终于实现了人物动画.相机控制及昼夜系统,现在继续吧,为了方便继续编写的敌人之类的脚本,所以打算今天先把第一张地图画个大概.结果,画了我好久的地图….. ≡(▔﹏▔)≡ 我对美术方面的天赋简直是惨不忍睹了…..加之地图中途画的差不多的时候Unity又崩溃了一次….忘了保存(ㄒoㄒ).于是又忙活半天….这个地图完全靠临时发挥了,第一张地图我画了好几次了,基本上每次画出来的地形之类的都完全不一样,所以就不多解释了,就上一张大概的场景图吧: 看起来好简单吧?唉……开启编辑器,这时侯如果在场景中转

Unity3D ARPG游戏开发《最初的幻想》之强化敌人AI,折腾的GUI

 昨天搞了死亡的完善与提示栏的工作.今天的话,首先再升级一下敌人的Ai吧.毕竟在玩家在敌人身后使劲攻击的话,这敌人也都不会有反应的,太不合理了. 打开Enemy脚本,在最前面"变量"标签中,先定义一个计数器,因为必须考虑到被同类"误伤"的情况: private int m_attackMeCount=0;//被一个同类对象攻击的次数 然后再在最下面的WaitForAttack函数中将自己的对象传入自己的攻击对象,以作判断: m_damageTarget.m_ch

Unity3D/2D游戏开发从0到1

这篇是计算机中Oracle类的优质预售推荐>>>><Unity3D/2D游戏开发从0到1> Unity3D/2D游戏开发从0到1(含DVD光盘1张) 采用 "案例化"教学思路, 以个人长期线下培训讲义为蓝本:讲解透彻.循序渐进.突出与优化游戏开发实战技巧:附有全国Unity游戏研发职位笔试面试真题集锦.Unity开发常见错误与分析.游戏开发职位简历模板 编辑推荐 按照"案例化"教学特点,全书贯穿两个重量级游戏的开发全过程讲解,让学

关于《Unity3D/2D游戏开发从0到1》书籍再版说明

关于<Unity3D/2D游戏开发从0到1>第一版本在2015年7月1日全国发行,累计得到不少国内高校教师.培训机构的好评.但是由于Unity官方对于技术不断的升级与版本的快速迭代,基于Unity4.6版本的教学知识体系,则略显滞后.    随着2017年7月份,Unity2017.1正式版本的推出,<Unity3D/2D游戏开发从0到1>书籍的再版,则正式提上日程. 目前2017年8月份再版工作已经进行过半,现在给各位小伙伴汇报一下工作,希望得到更好的建议.现在说说第二版本的总体