第三人称控制
来源:互联网 发布:金融学大学知乎 编辑:程序博客网 时间:2024/04/27 16:01
第三人称控制
前言
经过一段时间的Unity 3D学习,练习制作了一个简单的游戏Demo。该Demo实现了一个简单的RPG副本,英雄杀死两种怪兽游戏即获胜。
该Demo使用Unity 3D的版本为 4.6.4f1。
游戏采用第三人称视角(3rd Person Controller),但是Standard Assert中的3rd Person Controller不能满足要求。因此,自己动手实现一个第三人称角色控制。下面将从角色(英雄)控制与Camera控制两方面介绍第三人称控制的实现。
英雄控制
旋转与移动
给英雄添加Character Controller组件。通过水平和垂直虚拟轴获取玩家输入,垂直虚拟轴控制前进后退,水平虚拟轴控制旋转(此过程也带动Camera绕英雄旋转)。只有当英雄在地上时方能操作,也就是controller.isGrounded==true
。
旋转的关键代码
//此段代码在英雄的脚本组件中//获取水平虚拟轴输入float horizontal = Input.GetAxis ("Horizontal");float rotateY = horizontal * heroRotateSpeed; //英雄自转float cameraRotateHero = horizontal * cameraRotateSpeed;//Camera绕英雄转controller.transform.Rotate(0, rotateY*Time.deltaTime, 0); //人物调整朝向mainCamera.transform.RotateAround(transform.position, Vector3.up, cameraRotateHero * Time.deltaTime); //摄像机也旋转
移动的关键代码。首先根据输入,获得移动的本地方向向量,然后将其转为世界坐标系中的方向。
float vertical = Input.GetAxis("Vertical");Vector3 targetDirection = new Vector3 (0.0f, 0.0f, vertical); //本地Z方向if (targetDirection != Vector3.zero) {targetDirection = targetDirection.normalized; }movingDirection = transform.TransformDirection (targetDirection) ; //向量变换self -> world//...根据不同的操作设置移动速度movingSpeed,例如走、慢跑、快跑的速度是不同的movingDirection *= movingSpeed;if (Input.GetButton("Jump")) {...}movingDirection.y -= gravity * Time.deltaTime; //重力if (movingDirection != Vector3.zero) { collisionFlags = controller.Move (movingDirection * Time.deltaTime ); //当没有移动时,collisionFlags为None,所以if}CameraFollow (); //摄像机跟随移动
跳跃
考虑重力的影响,每一帧都会给英雄一个向下的速度movingDirection.y -= gravity * Time.deltaTime; //重力影响
。当跳跃时,给英雄添加一个向上的速度初速度:
//计算跳跃时的初速度float CalculateJumpVerticalSpeed (float targetJumpHeight) { return Mathf.Sqrt(2 * targetJumpHeight * gravity); //位移公式Vo^2 / 2g = H -> Vo = Sqrt(2gH)}if (Input.GetButton("Jump")) { _characterState = CharacterState.Jumping; movingDirection.y = CalculateJumpVerticalSpeed(jumpHeight); movingDirection.z = Mathf.Min (movingDirection.z, 0.2f);}
动画
英雄移动过程中,播放相应状态的动画。当玩家没有操作时,需要自动切换到Idle动画,由于攻击动画是触发式的,必须等待期播放完毕才能切换到其他状态的动画,使用_animation.IsPlaying(clip.name)
可以判断某动画片段是否播放完毕。
死亡
英雄死亡时,需要播放死亡动画,之后并处理后续工作,例如通知游戏结束。这里采用协同程序实现。
IEnumerator Dying() { _animation [dying.name].speed = 1f; _animation [dying.name].wrapMode = WrapMode.Once; _animation.CrossFade (dying.name); yield return new WaitForSeconds (5.0f); //等待动画播放完毕 //transform.gameObject.SetActive (false); //Destroy (transform.gameObject, 1.0f); //Time.timeScale = 0f; //暂停 gameResult.SendMessage ("GameLoseEnable"); //输了 }
第三视角Camera控制
第三人称的主摄像机需要时刻跟随英雄移动,考虑到英雄的跳跃、动画时不确定的移动、死亡(可能销毁GameObject)等状态,游戏中没有将主摄像机作为英雄的子节点,降低耦合。同时,为了方便不同视角的观察角色,需要根据玩家的操作调整视角。因此,需要解决Camera的移动、相对英雄的位置和距离变化等问题。
旋转和移动
当英雄旋转时,Camera也同方向、同轴旋转,但是角速度要小于英雄旋转的角速度(避免旋转太快产生眩晕)。
Camera的移动向量由英雄的移动向量获取。但是考虑以下两种情况:1.英雄跳跃;2.英雄当前遇到障碍物。
游戏中,英雄跳跃时,Camera不会跳跃,英雄时刻受重力影响会有一个垂直向下的速度,但Camera不受重力的影响。因此,Camera在y方向的变换为0,只有根据玩家的操作变化。
当英雄遇到障碍物,但移动向量不为零时,Camera是不移动。具体代码如下所示:
//该函数在英雄脚本组件中void CameraFollow(){ //camera 移动 Vector3 cameraMove = movingDirection * Time.deltaTime;; if ((collisionFlags & CollisionFlags.CollidedSides) != 0) { //遇到障碍物,不移动,只是看着玩家 mainCamera.transform.LookAt (transform.position); } else { cameraMove.y = 0.0F; //高度由玩家自己调整 mainCamera.transform.Translate (cameraMove, Space.World); }}
视角调整
视角有三种变换:
1. 以英雄的up为轴,在xz平面旋转;
2. 调整高度,升降;
3. 推进或者远离角色;
方式1水平旋转比较简单,也没有限制。
//水平旋转 float h = Input.GetAxis ("Mouse X"); h *= rotationXSpeed; if (Mathf.Abs(h) > 0.01f){ mainCamera.transform.RotateAround(hero.transform.position, Vector3.up, h * Time.deltaTime); mainCamera.transform.LookAt(hero.transform.position); //如果是鼠标右键则人物也旋转 if (Input.GetMouseButton(1)){ hero.transform.Rotate(Vector3.up, h*Time.deltaTime); } }
其中,2和3需要做边界限定。2不能将camera降到地面以下或者升到英雄的正上方,3不能无限制的推进或者远离。
方式2高度通过向量(英雄,Camera)与水平面的夹角限制。该夹角的Tan值,也就是Camera相对英雄的高度H/水平距离D。
//垂直变化 float v = -Input.GetAxis ("Mouse Y"); v *= changeYSpeed; //在y方向变化量 if (Mathf.Abs (v) > 0.01f) { float nextY = mainCamera.transform.position.y + v; //下一个位置的y值 if (nextY > minHeight || v > 0f) { Vector3 xyHero = hero.transform.position; Vector3 xyCamera = mainCamera.transform.position; xyHero.y = xyCamera.y = 0.0f; xyCamera -= xyHero; float dist = Mathf.Max (minDistance, xyCamera.magnitude); float tanA = nextY / dist; if (tanA < Mathf.Tan(maxAngle/180*Mathf.PI) && tanA > Mathf.Tan(minAngle/180*Mathf.PI) ) { //上下移动 mainCamera.transform.Translate(0.0f, v, 0.0f); mainCamera.transform.LookAt(hero.transform.position); } } }
方式3通过限制Camera与英雄的相对距离实现,调整距离过程中采用平滑插值Lerp,避免跳跃性太大。
//滚动鼠标滚轮,推近摄像机 float deltaScroll = Input.GetAxis ("Mouse ScrollWheel"); if (Mathf.Abs(deltaScroll) >= 0.01f) { Vector3 from = mainCamera.transform.position; Vector3 to = hero.transform.position; if (deltaScroll > 0) { //远离 Vector3 closestPoint = (from - to).normalized * minDistance + to; //从摄像机到人物方向,最近处的点 mainCamera.transform.position = Vector3.Lerp(from, closestPoint, closingSpeed * Time.time); } else { //远离 Vector3 farPoint = (from - to).normalized * maxDistance + to; //从人物到摄像机方向,最远处的点 mainCamera.transform.position = Vector3.Lerp(from, farPoint, closingSpeed * Time.time); } mainCamera.transform.LookAt(hero.transform.position); }
- 第三人称控制
- 第三人称游戏人物控制
- 第三人称蓝图控制
- unity第三人称控制
- 可以控制的第三人称摄像机
- Unity3d--第三人称角色移动控制
- Unity实现第三人称角色控制
- Unity3D中的第三人称镜头的脚本控制
- Unity3D中的第三人称镜头的脚本控制
- Unity3d基于第三人称控制简单优化
- Unity3D第一人称第三人称角色控制组件修改C#版
- Unity3D研究之第一人称第三人称角色控制组件修改
- Unity3D游戏开发第三人称角色控制的模式
- unity中实现的第三人称摄像机控制脚本。
- Unity3D之第一人称第三人称角色控制组件修改C#版本
- Unity3D之第一人称第三人称角色控制组件修改C#版本
- unity3d学习笔记(三)--不用一句代码快速加载并控制第三人称主角
- 今天开始做人物--会跑会跳的韩菱纱(如何制作第三人称人物控制)
- 二进制漏洞之——邪恶的printf
- Lucene技术---Solr实现全文检索技术
- 2015年华为实习生机试样题(记票统计,计算麻将的番数,Word Maze(单词迷宫))
- Unity3d NGUI的使用(五)(UISprite&UISlider制作彩色血条)
- 杭电oj——迷瘴
- 第三人称控制
- Notepad++常用的快捷键
- 关于 Script# 一些理解
- Hibernate主键生成策略
- ehcache调用说明
- 零长度数组的妙用
- PHP multipart/form-data 远程DOS漏洞
- java UID 问题
- Linux sudo用户管理