




已阅读5页,还剩18页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Unity3D游戏开发之自由视角下的角色控制 今天呢,继续来探讨Unity3D角色控制的内容,自由视角是指玩家可以按照自身坐标系向着四个不同的方向移动,当玩家按下鼠标右键时,可以绕Y轴按照一定的角度旋转摄像机,在旋转的过程中,角色将旋转相应的角度。在移动的过程中,摄像机会保持与玩家间的一定距离,然后跟随角色进行移动。好了,下面我们正式开始今天的内容吧! 在开始今天的内容前,首先让我们来学习下Unity3D中较为重要的一部分知识,理解这些知识是我们开始学习今天内容的基础。 1、Input.GetAxis():该方法用于在Unity3D中根据坐标轴名称返回虚拟坐标系中的值,通常情况下,使用控制器和键盘输入时此值范围在-1到1之间。这段话怎么理解呢?我们来看下面这段脚本: using UnityEngine; using System.Collections; public class example : MonoBehaviour /水平速度 public float HorizontalSpeed = 2.0F; /垂直速度 public float VerticalSpeed = 2.0F; void Update() /水平方向 float h = HorizontalSpeed * Input.GetAxis(Mouse X); /垂直方向 float v = VerticalSpeed * Input.GetAxis(Mouse Y); /旋转 transform.Rotate(v, h, 0); 这段脚本呢是根据鼠标的位置来旋转物体从而实现对物体的观察,从这段脚本中我们可以看出,通过获取输入轴的办法,我们可以获得鼠标移动的方向进而实现对于物体的旋转控制。在Unity3D中我们可以通过Edit-Project Setting-Input来查看项目中的坐标轴名称:在后面,我们还将使用这种方式,大家可以对这个方法有进一步的了解。 2、欧拉角eulerAngles:该值是Vector3类型的值,x、y、z分别代表绕x轴旋转x度,绕y轴旋转y度,绕z轴旋转z度。因此,该值最为直观的形式是可以允许我们直接以一个三维向量的形式来修改一个物体的角度,例如下面的脚本:htmlview plaincopy float mY = 5.0; void Update () mY += Input.GetAxis(Horizontal); transform.eulerAngles =new Vector3(0,mY, 0); 如果你已经理解了上面的话,那么不出意外的,这段脚本会如你所愿的,按照鼠标在水平方向上移动的方向绕Y轴旋转。通常情况下,我们不会单独设置欧拉角其中一个轴,例如eulerAngles.x = 10,因为这将导致偏移和不希望的旋转。当设置它们一个新的值时,要同时设置全部。好在我们可以通过Quaternion.Euler()方法将一个Vector3类型的值转化为一个四元数,进而通过修改Transform.Rotation来实现相同的目的。 3、插值:所谓插值是指在离散数据的基础上补插连续函数,使得这条连续曲线通过全部给定的离散数据点。插值是离散函数逼近的重要方法,利用它可通过函数在有限个点处的取值状况,估算出函数在其他点处的近似值。在某些情况下,如果我们希望过程中处理得较为平滑,此时我们就可以使用插值的方法来实现对中间过程的模拟。在Unity3D中我们可以使用两种插值方法,即线性插值Lerp,球形插值SLerp。我们来看下面的脚本: void Rotating (float horizontal, float vertical) / Create a new vector of the horizontal and vertical inputs. Vector3 targetDirection = new Vector3(horizontal, 0f, vertical); / Create a rotation based on this new vector assuming that up is the global y axis. Quaternion targetRotation = Quaternion.LookRotation(targetDirection, Vector3.up); / Create a rotation that is an increment closer to the target rotation from the players rotation. Quaternion newRotation = Quaternion.Lerp(rigidbody.rotation, targetRotation, turnSmoothing * Time.deltaTime); / Change the players rotation to this new rotation. rigidbody.MoveRotation(newRotation); 插值的方法很简单,只要我们给出初始和结束的状态、时间就可以了,大家可以自己看API。文章出处狗刨学习网 好了,有了这三部分的基础,我们就可以开始今天的内容了,今天的脚本分为两个部分,第一部分是角色控制的部分,主要负责的角色在场景中的移动、转身和动画处理。第二部分是相机控制的部分,主要涉及相机旋转、相机缩放的相关内容。下面,我们分别来讲这两个部分,场景依然是博主自己在做的小游戏: 第一部分,主要的是完成角色向各个方向的转身,这里博主定义四个方向(其实八个方向是一样的!),脚本如下: using UnityEngine; using System.Collections; public class NoLockiVew_Player : MonoBehaviour /玩家的行走速度 public float WalkSpeed=1.5F; /重力 public float Gravity=20; /角色控制器 private CharacterController mController; /动画组件 private Animation mAnim; /玩家方向,默认向前 private DirectionType mType=DirectionType.Direction_Forward; HideInInspector /玩家状态,默认为Idle public PlayerState State=PlayerState.Idle; /定义玩家的状态枚举 public enum PlayerState Idle, Walk /定义四个方向的枚举值,按照逆时针方向计算 protected enum DirectionType Direction_Forward=90, Direction_Backward=270, Direction_Left=180, Direction_Right=0 void Start () /获取角色控制器 mController=GetComponent(); /获取动画组件 mAnim=GetComponentInChildren(); void Update () MoveManager(); /MouseEvent(); /玩家移动控制 void MoveManager() /移动方向 Vector3 mDir=Vector3.zero; if(mController.isGrounded) /将角色旋转到对应的方向 if(Input.GetAxis(Vertical)=1) SetDirection(DirectionType.Direction_Forward); mDir=Vector3.forward * Time.deltaTime * WalkSpeed; mAnim.CrossFade(Walk,0.25F); State=PlayerState.Walk; if(Input.GetAxis(Vertical)=-1) SetDirection(DirectionType.Direction_Backward); mDir=Vector3.forward * Time.deltaTime * WalkSpeed; mAnim.CrossFade(Walk,0.25F); State=PlayerState.Walk; if(Input.GetAxis(Horizontal)=-1) SetDirection(DirectionType.Direction_Left); mDir=Vector3.forward * Time.deltaTime * WalkSpeed; mAnim.CrossFade(Walk,0.25F); State=PlayerState.Walk; if(Input.GetAxis(Horizontal)=1) SetDirection(DirectionType.Direction_Right); mDir=Vector3.forward * Time.deltaTime * WalkSpeed; mAnim.CrossFade(Walk,0.25F); State=PlayerState.Walk; /角色的Idle动画 if(Input.GetAxis(Vertical)=0 & Input.GetAxis(Horizontal)=0) mAnim.CrossFade(Idle,0.25F); State=PlayerState.Idle; /考虑重力因素 mDir=transform.TransformDirection(mDir); float y=mDir.y-Gravity *Time.deltaTime; mDir=new Vector3(mDir.x,y,mDir.z); mController.Move(mDir); /设置角色的方向,有问题 void SetDirection(DirectionType mDir) if(mType!=mDir) transform.Rotate(Vector3.up*(mType-mDir); mType=mDir; 这里定义四个方向,是按照逆时针方向转的,相邻的两个方向间相差90度,所以我们只需要将当前的角度和目标角度相减就可以转到目标角度的方向(其实这是以前写的代码,现在回头再看,直接用欧拉角似乎更为简单啊,呵呵)。这里主要的内容就是这样了。下面我们来看相机控制部分的代码吧,这里的代码参考了MouseOrbit脚本,主要完成了鼠标右键旋转控制,博主在此基础上增加了相机缩放的代码。提到相机缩放,其实就是根据鼠标滚轮滚动的方向和大小重新计算角色与相机的距离,与之类似地还有小地图的放缩,其实同样是通过修改距离来实现的。我们一起来看脚本文章出处狗刨学习网 using UnityEngine; using System.Collections; public class NoLockView_Camera : MonoBehaviour /观察目标 public Transform Target; /观察距离 public float Distance = 5F; /旋转速度 private float SpeedX=240; private float SpeedY=120; /角度限制 private floatMinLimitY = 5; private floatMaxLimitY = 180; /旋转角度 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=true; /速度 public float Damping=2.5F; void Start () /初始化旋转角度 mX=transform.eulerAngles.x; mY=transform.eulerAngles.y; void LateUpdate () /鼠标右键旋转 if(Target!=null & Input.GetMouseButton(1) /获取鼠标输入 mX += Input.GetAxis(Mouse X) * SpeedX * 0.02F; mY -= Input.GetAxis(Mouse Y) * SpeedY * 0.02F; /范围限制 mY = ClampAngle(mY,MinLimitY,MaxLimitY); /鼠标滚轮缩放 Distance-=Input.GetAxis(Mouse ScrollWheel) * ZoomSpeed; Distance=Mathf.Clamp(Distance,MinDistance,MaxDistance); /重新计算位置和角度 Quaternion mRotation = Quaternion.Euler(mY, mX, 0); Vector3 mPosition = mRotation * new Vector3(0.0F, 0.0F, -Distance) + Target.position; /设置相机的角度和位置 if(isNeedDamping) /球形插值 transform.rotation = Quaternion.Lerp(transform.rotation,mRotation, Time.deltaTime*Damping); /线性插值 transform.position = Vector3.Lerp(transform.position,mPosition, Time.deltaTime*Damping); else transform.rotation = mRotation; transform.position = mPosition; /将玩家转到和相机对应的位置上 if(Target.GetComponent().State=NoLockiVew_Player.PlayerState.Walk) Target.eulerAngles=new Vector3(0,mX,0); private floatClampAngle (float angle,float min,float max) if (angle 360) angle -= 360; return Mathf.Clamp (angle, min, max); 这里很多朋友可能对我设置一个状态很不理解吧,这其实是为了让玩家有一个自由查看角色的机会,否则当玩家按下鼠标右键的话,角色就会转向相机正对着的位置,这样玩家就看不到角色的正面了。当然,这里用到了插值,这样能使角色在转身的时候平滑一点,效果会更好。效果演示(2M的限制让很多展示都无可奈何) 如果在测试的时候出现Bug。Bug出现在如下位置:csharpview plaincopy /设置玩家跟随角度 if(Target.GetComponent().State=NoLockiVew_Player.PlayerState.Walk) Target.rotation=Quaternion.Euler(new Vector3(0,mX,0); 该方法主要的作用是当玩家同时按下方向控制键和鼠标右键,玩家可以随着鼠标旋转到对应的角度,这主要是为了满足玩家双手操作的需求,不过由于这行代码,导致玩家在向左、向右、向后三个方向上的转身失效,如果除去这行代码,则原来的方向控制没有任何问题,可是没有这行代码,玩家的操作感就会下降。后来博主想到我们对角色的旋转实际上应该是放在鼠标右键事件里的,所以博主将代码修改如下,这样就解决了这个Bug:csharpview plaincopy using UnityEngine; using System.Collections; public class NoLockView_Camera : MonoBehaviour /观察目标 public Transform Target; /观察距离 public float Distance = 5F; /旋转速度 private float SpeedX=240; private float SpeedY=120; /角度限制 private floatMinLimitY = 5; private floatMaxLimitY = 180; /旋转角度 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=true; /速度 public float Damping=10F; private Quaternion mRotation; void Start () /初始化旋转角度 mX=transform.eulerAngles.x; mY=transform.eulerAngles.y; void LateUpdate () /鼠标右键旋转 if(Target!=null & Input.GetMouseButton(1) /获取鼠标输入 mX += Input.GetAxis(Mouse X) * SpeedX * 0.02F; mY -= Input.GetAxis(Mouse Y) * SpeedY * 0.02F; /范围限制 mY = ClampAngle(mY,MinLimitY,MaxLimitY); /计算旋转 mRotation = Quaternion.Euler(mY, mX, 0); /根据是
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- Unit6-A-Lets-talk教学设计(第1课时)【河南郑州】
- 股骨骨折皮牵引的护理措施
- 河北省石家庄市第四十中学2025届初三第三次(4月)联考英语试题理试题含答案
- Unit2-B-Read-and-write江西公开课教案
- 郑州信息工程职业学院《医学细胞生物学与遗传学实验》2023-2024学年第二学期期末试卷
- 赣南师范大学《社会工作机构人力资源管理》2023-2024学年第二学期期末试卷
- 云南师范大学《工作分析与工作设计》2023-2024学年第二学期期末试卷
- 三年级语文下册第六组22月球之谜说课稿新人教版
- 小学英语课堂游戏句子或对话类游戏语言和动作
- 2025届枣庄市重点中学高三第二次模拟物理试题试卷含解析
- 315食品安全宣传PPT模板
- GB/T 20145-2006灯和灯系统的光生物安全性
- GB 21519-2008储水式电热水器能效限定值及能效等级
- 2023年陕西省学业水平考试物理试真题答案无
- 运输供应商年度评价表
- 旅游项目融投资概述
- 全旅馆业前台从业人员资格证考试答案解析
- 十二经络及腧穴课件
- 立式圆筒形储罐罐底真空试验记录
- 公司新员工入职登记表(模板)
- 新疆大地构造单元划分论文(董连慧)2017最新整理
评论
0/150
提交评论