Unity第三人称的实现思路(二)

  • 锁定视角动画设置
  • 锁定视角摄像机
  • 角色朝向控制
  • 主要代码


这一次我们在上一篇自由视角的基础上加上锁定视角的功能,没有看过上一篇的点下方链接。
Unity第三人称的实现思路(一)

锁定视角动画设置

锁定视角的动画分为两种情况,一种是不带方向的一种是带方向的:

单一方向:

8方向:


比如黑魂里的锁定视角,只推左摇杆正常移动时模型永远面朝目标,但如果按住x奔跑时模型就会朝向移动的方向,但摄像机依旧是对准目标的。而在这个Demo中我用的是拔出剑时模型永远面朝目标,剑收起来时模型朝向移动方向。 锁定视角只需要理清 角色碰撞器,模型,目标 三者之间的相对位置就能知道融合树中的数值应该怎么给。

锁定视角摄像机

Cinemachine组件很多参数都是公开的,只需要引用Cinemachine命名空间然后获取组件就能修改其中的参数。锁定视角需要更改的参数其实只有两三处,可以在锁定视角时用代码修改,这里为了减少代码量没有采用这种方法,毕竟现在需要修改的只有两三处,但以后就不一定了。在上一篇中提到的Priority(优先级)参数就起到作用了,主摄像机会渲染处于激活状态的更高优先级的虚拟相机,我们只需要复制一份自由视角的相机然后修改其中的参数,再用代码动态激活和关闭这个相机即可。



Axis Control中两个轴的speed设置成0是为了让鼠标两个轴的输入变为0,相当于禁止移动视角。
Binding Mode原本是World Space,如果不移动视角的话位置就不会改变,锁定视角时会出现相机在目标与角色中间,看不到角色的问题。设置成Lock To Target后相机位置会锁定在角色身后,只要让角色时刻朝向目标,摄像机就永远能看见角色并对准目标。

角色朝向控制

     //如果按下锁定键if(Input.GetKeyDown(keys.Lock)){//锁定状态改变state.isLocking = !state.isLocking;//锁定为真打开锁定视角摄像机,锁定为假时关闭lockCamera.SetActive(state.isLocking);//设置动画状态机锁定状态的参数animController.SetBool("LockState", state.isLocking);}
 //锁定状态时每一帧调用void LockLook(){if (!state.isLocking)return;//不移动时不旋转角色if (moveDir.sqrMagnitude < 0.1f)return;//相机朝向目标,旋转值赋给角色后角色也朝向目标Vector3 cameraEuler = Camera.main.transform.eulerAngles;transform.rotation = Quaternion.Euler(0, cameraEuler.y, 0);//非战斗状态(空手)if(!state.isEquiped){//键盘输入的方向Vector3 dir = moveDir.normalized;float angle = Mathf.Atan2(dir.x, dir.z) * Mathf.Rad2Deg;Quaternion targetDir = Quaternion.Euler(0, angle, 0);//模型朝向键盘输入方向model.localRotation = Quaternion.Lerp(model.localRotation, targetDir, 12 * Time.deltaTime);}//战斗状态(拔剑)else{//模型本地旋转设置为0model.localRotation = Quaternion.Lerp(model.localRotation, Quaternion.Euler(0, 0, 0), 12 * Time.deltaTime);}}

上面修改模型朝向时用的是本地旋转值。空手状态时,因为模型的父级朝向目标,移动时应该是相对于父级的本地方向而不是真实的方向。拔剑状态时模型应该朝向目标,因为父级朝向目标,只需要让模型旋转归零就能与父级同样朝向。

主要代码

using UnityEngine;public class PlayerController : MonoBehaviour
{public Transform target;/// <summary>/// 角色控制器/// </summary>CharacterController characterController;/// <summary>/// 动画控制器/// </summary>PlayerAnimController animController;/// <summary>/// 角色状态/// </summary>CharacterState state;/// <summary>/// 按键/// </summary>[SerializeField] InputKeys keys;/// <summary>/// 模型/// </summary>Transform model;/// <summary>/// 锁定状态下的摄像机/// </summary>GameObject lockCamera;/// <summary>/// 移动欲望/// </summary>Vector3 moveDir;private void Awake(){Cursor.visible = false;Cursor.lockState = CursorLockMode.Locked;characterController = GetComponent<CharacterController>();animController = GetComponentInChildren<PlayerAnimController>();animController.PlayerController = this;state = new CharacterState();animController.State = state;model = transform.Find("Model");lockCamera = GameObject.Find("Virtual Camera Group").transform.Find("LockLook").gameObject;}private void Update(){InputCheck();}private void FixedUpdate(){FreeLook();LockLook();Vector2 movement = SquareToCircle(moveDir);if(state.isLocking && state.isEquiped){animController.SetFloat("SpeedZ", movement.y);animController.SetFloat("SpeedX", movement.x);}else{animController.SetFloat("SpeedZ", movement.sqrMagnitude);}}/// <summary>/// 自由视角/// </summary>void FreeLook(){if (state.isLocking)return;if (moveDir.sqrMagnitude < 0.1f)return;model.localRotation = Quaternion.Lerp(model.localRotation, Quaternion.Euler(0 ,0 ,0), 12 * Time.deltaTime);Vector3 dir = moveDir.normalized;float angle = Mathf.Atan2(dir.x, dir.z) * Mathf.Rad2Deg + Camera.main.transform.eulerAngles.y;Quaternion targetDir = Quaternion.Euler(0, angle, 0);transform.rotation = Quaternion.Lerp(transform.rotation, targetDir, 12 * Time.deltaTime);}/// <summary>/// 锁定视角/// </summary>void LockLook(){if (!state.isLocking)return;if (moveDir.sqrMagnitude < 0.1f)return;Vector3 cameraEuler = Camera.main.transform.eulerAngles;transform.rotation = Quaternion.Euler(0, cameraEuler.y, 0);//非战斗状态if(!state.isEquiped){Vector3 dir = moveDir.normalized;float angle = Mathf.Atan2(dir.x, dir.z) * Mathf.Rad2Deg;Quaternion targetDir = Quaternion.Euler(0, angle, 0);model.localRotation = Quaternion.Lerp(model.localRotation, targetDir, 12 * Time.deltaTime);}//战斗状态else{model.localRotation = Quaternion.Lerp(model.localRotation, Quaternion.Euler(0, 0, 0), 12 * Time.deltaTime);}}/// <summary>/// 输入检测/// </summary>void InputCheck(){float fwd = 0;float right = 0;fwd = Input.GetKey(keys.fwd) ? 1 : fwd;fwd = Input.GetKey(keys.bwd) ? -1 : fwd;right = Input.GetKey(keys.right) ? 1 : right;right = Input.GetKey(keys.left) ? -1 : right;moveDir.z = Mathf.Lerp(moveDir.z, fwd, 24 * Time.deltaTime);moveDir.x = Mathf.Lerp(moveDir.x, right, 24 * Time.deltaTime);//拔出武器if (Input.GetKeyDown(keys.equip)){state.isEquiped = !state.isEquiped;animController.SetTrigger("Equip");}//锁定视角if(Input.GetKeyDown(keys.Lock)){state.isLocking = !state.isLocking;lockCamera.SetActive(state.isLocking);animController.SetBool("LockState", state.isLocking);}}/// <summary>/// 椭圆映射/// </summary>/// <param name="oldVec"></param>/// <returns></returns>Vector2 SquareToCircle(Vector3 oldVec){Vector2 newVec;newVec.x = oldVec.x * Mathf.Sqrt(1 - (oldVec.z * oldVec.z) / 2);newVec.y = oldVec.z * Mathf.Sqrt(1 - (oldVec.x * oldVec.x) / 2);return newVec;}/// <summary>/// 动画根节点速度作为移动速度/// </summary>/// <param name="velocity"></param>public void SetCharacterVelocity(Vector3 velocity){characterController.SimpleMove(new Vector3(velocity.x, characterController.velocity.y, velocity.z));}}
using UnityEngine;public class PlayerAnimController : MonoBehaviour
{/// <summary>/// 角色逻辑控制器/// </summary>PlayerController playerController;public PlayerController PlayerController { set { playerController = value; } }/// <summary>/// 角色状态/// </summary>CharacterState state;public CharacterState State { set { state = value; } }/// <summary>/// 动画状态机/// </summary>Animator anim;private void Awake(){anim = GetComponent<Animator>();}/// <summary>/// 设置Float参数/// </summary>/// <param name="name"></param>/// <param name="value"></param>public void SetFloat(string name, float value){anim.SetFloat(name, value);}/// <summary>/// 触发器/// </summary>/// <param name="name"></param>public void SetTrigger(string name){anim.SetTrigger(name);}public void SetBool(string name, bool value){anim.SetBool(name, value);}/// <summary>/// 动画执行时每一帧调用/// </summary>private void OnAnimatorMove(){playerController.SetCharacterVelocity(anim.velocity);}#region 帧事件/// <summary>/// 拔出武器调用/// </summary>public void OnEquipStateEnter(){SetBool("IsEquiped", true);}/// <summary>/// 收起武器调用/// </summary>public void OnUnEquipStateEnter(){SetBool("IsEquiped", false);}#endregion}

工程文件下载

Unity第三人称的实现思路(二)相关推荐

  1. unity第三人称射击游戏_在游戏上第3部分完美的信息游戏

    unity第三人称射击游戏 Previous article 上一篇文章 The economics literature distinguishes the quality of a game's ...

  2. Unity第三人称控制实现方式

    第三人称移动,主要两个部分,一是人物,二是相机. 先说人物,unity其实提供了一个CharacteController组件可以方便地用于控制人物移动,但是这个组件会与刚体冲突.如果使用Charact ...

  3. Unity 第三人称角色控制器:动画混合树、Cinemachine等功能或插件的使用

    前言: 无论是RPG.ACT.AVG还是TPS游戏,都有大量的以第三人称为人物视角的游戏作品,尤其是TPS,直接以第三人称为特点来命名 游戏类型: RPG:角色扮演游戏 ACT:动作游戏 AVG:冒险 ...

  4. Unity 第三人称射击游戏视角控制与武器瞄准

    ===================更新一下源工程链接: 链接:https://pan.baidu.com/s/15bxH-MPregp2ZIN92fK7XA 提取码:e7bp ========== ...

  5. unity 第三人称射击游戏中如何防止跟随摄像机穿墙?

    在制作3d射击类游戏中,会遇到跟随角色的摄像机会穿透墙壁导致视野不佳情况,下面,介绍一下具体的解决方法. 我们需要用到的原理就是unity中射击线函数.具体的原理是,从相机的跟随点向相机的方向发射一条 ...

  6. Unity 第三人称 摄像机

    今天主要是简单的模拟下吃鸡游戏的第三人称摄像机的实现. 观察 我们玩过吃鸡手游的都知道,吃鸡的人物跟随的摄像机有两种状态 1. 滑动屏幕的时候,摄像机左右上下移动,人物也会跟随着左右移动,上下抬头低头 ...

  7. Unity第三人称射击游戏的相机控制

    (关于其他几种角色移动的控制在我之前的博客有写到) 首先我们需要先理解一下第三人称相机控制的原理: 我们要实现的效果就是:获取鼠标的移动输入,转化成角色以及相机的旋转,通过鼠标输入Input.GetA ...

  8. unity第三人称漫游,游戏场景精美,人物可移动

    unity3d第三人称漫游 (下载链接在文末) 游戏场景精美,包含山谷房屋桌椅等等模型,鼠标控制小狐狸移动,有血条,有菜单有按钮等等,需要什么额外功能可以自己再改造,如下图所示: 点我下载 https ...

  9. Unity 第三人称自由视角

    环绕相机控制脚本 该脚本需要挂载在环绕相机上,而环绕相机不绑定在角色身上,而是作为一个单独的存在 此外,由于一般来说,角色的原点都在脚底,所以需要特别在角色的中心位置放置一个空对象作为视野中心,并在面 ...

最新文章

  1. Redis混合存储产品与架构介绍
  2. 使用PowerDesigner 15对现有数据库进行反向工程(图解教程) by Yulh
  3. php 加权计算公式,PHP计算加权平均数的实例分享
  4. HTML5 新增结构元素分为主体结构元素和非主体结构元素
  5. DCMTK:OFUUID测试程序
  6. 我的20天项目经历--至今令我难忘的技术难题
  7. Anaconda安装更新库
  8. java mysql show status_Java 能不能执行mysql 中的show master status 命令
  9. Mycat监控_监控平台安装zookeeper_作为配置中心注册发现用---MyCat分布式数据库集群架构工作笔记0036
  10. redis常用命令getex_redis常用命令大全
  11. 移植制造时保持资源的「统一」。
  12. c语言实现shellcode转换工具
  13. 2018/7/31-zznuoj-问题 A: A + B 普拉斯【二维字符串+暴力模拟+考虑瑕疵的题意-0的特例】...
  14. How to Be Cool at College
  15. 【学习笔记】n皇后问题的解决方法+改进代码(回溯递归)
  16. HTML5七夕情人节表白网页源码 HTML+CSS+JavaScript
  17. [Java GC]Java垃圾回收
  18. vue构建项目对接口的调用封装
  19. HDU 1865 1string
  20. Netbeans 8.0配置Python开发环境

热门文章

  1. 抖音不露脸拍什么题材好,抖音拍可以不露脸吗
  2. 央视播网友调侃委员周星驰:国家有任务给你了
  3. [软件工具][windows]OCR指定区域图片自动识别内容重命名软件使用教程
  4. Ffmpeg 处理视频命令
  5. 目标检测: 数据集转换txt转为xml格式
  6. JPA复合主键的使用
  7. k8s-存储插件:cfs运行机制
  8. 戴尔服务器系列区别,拆解戴尔服务器,看看内部构造与普通计算机的区别
  9. a标签js阻止跳转_js阻止a标签href跳转的方法
  10. 错路狂奔已久,美国准备好成为科学强国了吗?