Unity第三人称的实现思路(二)
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第三人称的实现思路(二)相关推荐
- unity第三人称射击游戏_在游戏上第3部分完美的信息游戏
unity第三人称射击游戏 Previous article 上一篇文章 The economics literature distinguishes the quality of a game's ...
- Unity第三人称控制实现方式
第三人称移动,主要两个部分,一是人物,二是相机. 先说人物,unity其实提供了一个CharacteController组件可以方便地用于控制人物移动,但是这个组件会与刚体冲突.如果使用Charact ...
- Unity 第三人称角色控制器:动画混合树、Cinemachine等功能或插件的使用
前言: 无论是RPG.ACT.AVG还是TPS游戏,都有大量的以第三人称为人物视角的游戏作品,尤其是TPS,直接以第三人称为特点来命名 游戏类型: RPG:角色扮演游戏 ACT:动作游戏 AVG:冒险 ...
- Unity 第三人称射击游戏视角控制与武器瞄准
===================更新一下源工程链接: 链接:https://pan.baidu.com/s/15bxH-MPregp2ZIN92fK7XA 提取码:e7bp ========== ...
- unity 第三人称射击游戏中如何防止跟随摄像机穿墙?
在制作3d射击类游戏中,会遇到跟随角色的摄像机会穿透墙壁导致视野不佳情况,下面,介绍一下具体的解决方法. 我们需要用到的原理就是unity中射击线函数.具体的原理是,从相机的跟随点向相机的方向发射一条 ...
- Unity 第三人称 摄像机
今天主要是简单的模拟下吃鸡游戏的第三人称摄像机的实现. 观察 我们玩过吃鸡手游的都知道,吃鸡的人物跟随的摄像机有两种状态 1. 滑动屏幕的时候,摄像机左右上下移动,人物也会跟随着左右移动,上下抬头低头 ...
- Unity第三人称射击游戏的相机控制
(关于其他几种角色移动的控制在我之前的博客有写到) 首先我们需要先理解一下第三人称相机控制的原理: 我们要实现的效果就是:获取鼠标的移动输入,转化成角色以及相机的旋转,通过鼠标输入Input.GetA ...
- unity第三人称漫游,游戏场景精美,人物可移动
unity3d第三人称漫游 (下载链接在文末) 游戏场景精美,包含山谷房屋桌椅等等模型,鼠标控制小狐狸移动,有血条,有菜单有按钮等等,需要什么额外功能可以自己再改造,如下图所示: 点我下载 https ...
- Unity 第三人称自由视角
环绕相机控制脚本 该脚本需要挂载在环绕相机上,而环绕相机不绑定在角色身上,而是作为一个单独的存在 此外,由于一般来说,角色的原点都在脚底,所以需要特别在角色的中心位置放置一个空对象作为视野中心,并在面 ...
最新文章
- Redis混合存储产品与架构介绍
- 使用PowerDesigner 15对现有数据库进行反向工程(图解教程) by Yulh
- php 加权计算公式,PHP计算加权平均数的实例分享
- HTML5 新增结构元素分为主体结构元素和非主体结构元素
- DCMTK:OFUUID测试程序
- 我的20天项目经历--至今令我难忘的技术难题
- Anaconda安装更新库
- java mysql show status_Java 能不能执行mysql 中的show master status 命令
- Mycat监控_监控平台安装zookeeper_作为配置中心注册发现用---MyCat分布式数据库集群架构工作笔记0036
- redis常用命令getex_redis常用命令大全
- 移植制造时保持资源的「统一」。
- c语言实现shellcode转换工具
- 2018/7/31-zznuoj-问题 A: A + B 普拉斯【二维字符串+暴力模拟+考虑瑕疵的题意-0的特例】...
- How to Be Cool at College
- 【学习笔记】n皇后问题的解决方法+改进代码(回溯递归)
- HTML5七夕情人节表白网页源码 HTML+CSS+JavaScript
- [Java GC]Java垃圾回收
- vue构建项目对接口的调用封装
- HDU 1865 1string
- Netbeans 8.0配置Python开发环境