《土豆荣耀》重构笔记(七)控制角色移动并添加音效
章节目录
- 前言
- 为角色添加Collider和Rigidbody
- 控制角色移动
- 添加Physics Material
- 添加音效
- PlayerController.cs完整代码
- 后言
- 参考链接
前言
为了便于测试,我们会先使用PC端的键盘和鼠标输入
来控制人物的移动,等到功能测试完成之后,再将PC端的键盘和鼠标输入
换成移动端的虚拟摇杆和按钮输入
。这里,我们首先使用PC端的键盘和鼠标输入
来实现控制角色进行移动的功能。
为角色添加Collider和Rigidbody
为了让角色具有物理属性,我们需要为角色添加Collider和Rigidbody。此外,为了避免角色出现翻滚的问题,让角色一直保持直立,因此我们需要在Rigidbody2D
的Constraints
属性里设置勾选Freeze Rotation Z
,不让角色在进行物理模拟时,绕Z轴进行旋转。
控制角色移动
接下来,我们开始编写脚本来实现让怪物在场景中移动的功能。我们在Assets\Scripts
文件夹下创建一个名为Player
的文件夹用于保存和角色相关的脚本。创建完毕后,我们在Player
文件夹下创建一个名为PlayerController
的C#脚本,然后添加以下代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;[RequireComponent(typeof(Rigidbody2D))]
public class PlayerController : MonoBehaviour {[Tooltip("角色初始朝向是否朝向右边")]public bool FacingRight = true;[Tooltip("移动时角色加速的力大小")]public float MoveForce = 365f;[Tooltip("角色移动的最大速度")]public float MaxSpeed = 5f;[Tooltip("跳跃时向上加速的力大小")]public float JumpForce = 1000f;[Tooltip("检测角色是否落地")]public Transform GroundCheck;// 记录角色当前是否处于准备跳跃状态private bool m_IsReadyToJump;// 记录角色当前是否正处于跳跃状态private bool m_IsJumping;// 记录角色当前是否处于着地状态private bool m_GroundedStatus;// 组件引用变量private Rigidbody2D m_Rigidbody2D;private void Awake() {// 获取组件引用m_Rigidbody2D = GetComponent<Rigidbody2D>();}private void Start() {// 监测变量是否正确赋值if(GroundCheck == null) {Debug.LogError("请先设置GroundCheck");}// 初始化变量m_IsReadyToJump = false;m_IsJumping = false;m_GroundedStatus = false;}private void Update() {// 通过检测角色和groundCheck之间是否存在Ground层的物体来判断当前是否落地m_GroundedStatus = Physics2D.Linecast(transform.position,GroundCheck.position,LayerMask.GetMask("Obstacle"));// 着地时,如果当前不处于跳跃状态且按下了跳跃键,进入准备跳跃状态if(m_GroundedStatus && !m_IsJumping && Input.GetButtonDown("Jump")) {m_IsReadyToJump = true;}// 刚刚落地,退出跳跃状态if(m_GroundedStatus && m_IsJumping) {m_IsJumping = false;}}private void FixedUpdate() {//获取水平输入float h = Input.GetAxis("Horizontal");// 若h * m_Rigidbody2D.velocity.x为正数且小于MaxSpeed,表示需要继续加速// 若h * m_Rigidbody2D.velocity.x为负数,则表示需要反向加速if(h * m_Rigidbody2D.velocity.x < MaxSpeed) {m_Rigidbody2D.AddForce(Vector2.right * h * MoveForce);}//设置物体速度的阈值if(Mathf.Abs(m_Rigidbody2D.velocity.x) > MaxSpeed) {m_Rigidbody2D.velocity = new Vector2(Mathf.Sign(m_Rigidbody2D.velocity.x) * MaxSpeed,m_Rigidbody2D.velocity.y);}//判断当前是否需要转向if(h > 0 && !FacingRight) {Flip();}else if(h < 0 && FacingRight) {Flip();}// 跳跃if(m_IsReadyToJump) {Jump();}}private void Jump() {// 进入跳跃状态m_IsJumping = true;// 设置一个竖直向上的力m_Rigidbody2D.AddForce(new Vector2(0f, JumpForce));// 退出准备跳跃状态,避免重复跳跃m_IsReadyToJump = false;}private void Flip() {// 修改当前朝向FacingRight = !FacingRight;// 修改scale的x分量实现转向this.transform.localScale = Vector3.Scale(new Vector3(-1, 1, 1),this.transform.localScale);}
}
代码说明:
- Input.GetAxis(“Horizontal”):Unity提供的默认输入项,能获取键盘上
A\D
键和<-\->
方向键的输入- Input.GetButtonDown(“Jump”):Unity提供的默认输入项,能获取键盘上空格键的输入
- Physics2D.Linecast:来获取场景里两个点之间属于某个Layer的所有Collider
- 因为
和角色物理模拟有关的操作都应该在FixedUpdate里执行
,所以Jump函数需要在FixedUpdate里调用- 我们为了避免出现多次按跳跃键导致Jump函数被多次调用的问题,我们使用变量
m_IsJumping
来判断当前是否处于跳跃状态
添加Physics Material
添加完成后,将PlayerController.cs
添加到Hierarchy
窗口的Player
上,运行游戏,我们发现角色在运动时,会出现很明显的滑动现象。这是因为我们没有为角色和平台上的Collider设置Physics Material
,导致角色和平台之间的摩擦力为0。
添加Physics Material的步骤
- 在
Assets
目录下新建一个名为Physics Material
的文件夹- 在
Physics Material
的文件夹创建两个Physics Material 2D
,并将它们分别命名为Platform
和Player
- 将
Platform
和Player
这两个Physics Material 2D
的Friction
属性都设置为1
- 将
Platform
和Player
这两个Physics Material 2D
分别设置到所有角色可移动的平台
和角色的Rigidbody2D
上
因为平台数量较多,我们可以批量操作。按住shift
键选择多个GameObject,右侧Inspector
就会显示它们同时都具备的组件,我们可以同时对它们同时都具备的组件进行编辑。
此外,角色在跳跃时,我们发现角色跳跃的高度很高,且下落的速度很慢,游戏体验较差。为了提高游戏体验,我们需要增大游戏角色的重力加速度。将Player
下Rigidbody2D
组件的Gravity Scale
设置为3.1
,表示将角色的重力加大至原有的3.1
倍。
从上面的图片可以看到,我将Player
这一Physics Material 2D
设置到角色的Rigidbody2D
上,这表示角色的所有没设置Physics Material 2D
的Collider都会使用Player
这一Physics Material 2D
。
设置完成之后,运行游戏,可以看到之前的滑动和下落缓慢的问题都消失了,但是出现了一个新的问题,那就是当我们按住方向键不动的时候,角色会贴在平台边缘。之所以会出现这个问题,是因为角色和平台之间有摩擦力,为了避免这一情况,我们需要创建一个名为Wall
的Physics Material 2D
,将其Friction
属性都设置为0
,然后在各个平台的末端处创建一个使用Wall
这一Physics Material 2D
的Collider。
Foreground添加Collider的情况如下:
- env_TowerFull和env_TowerFull (1):
- 不添加新的Collider
- 设置原有Collider的
Physics Material 2D
为Wall
- env_PlatformBridge和env_PlatformBridge (1):
- 新添加一个BoxCollider2D
Material
:WallOffset
:(0.8, 0.8)Size
: (15.5, 0.6)- env_PlatformTop和env_PlatformTop (1):
- 新添加一个BoxCollider2D
Material
:WallOffset
:(4.7, 0.12)Size
: (0.5, 2.6)- env_PlatformUfo:
- 新添加两个CircleCollider2D
Material
:都为WallOffset
:(-15.3, -0.65)和(15.3, -0.65)Radius
: 都为0.5
添加完毕之后,再次运行游戏,可以看到不再出现角色贴在平台边缘的问题。
添加音效
接着,我们需要为角色添加音效。首先,在PlayerController.cs
内加入以下代码,其中...
表示原有的代码:
...
[RequireComponent(typeof(AudioSource))]
public class PlayerController : MonoBehaviour {...[Tooltip("跳跃音效")]public AudioClip[] JumpClips;...private AudioSource m_AudioSource;...private void Awake() {...m_AudioSource = GetComponent<AudioSource>();}private void Jump() {...//随机在角色当前所处的位置播放一个跳跃的音频if(JumpClips.Length > 0) {int i = Random.Range(0, JumpClips.Length);AudioSource.PlayClipAtPoint(JumpClips[i], transform.position);}}
}
添加完毕之后,我们给Player添加AudioSource
组件,并将Assets\Audio\Player\Jumps
添加到JumpClips
属性上。接着运行游戏,可以听到角色在跳跃的时候已经有了音效。最后,将我们在Player
上做的修改Apply
到Prefab上,并保存场景产生的修改即可。
PlayerController.cs完整代码
此时,PlayerController.cs
完整代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;[RequireComponent(typeof(Rigidbody2D))]
[RequireComponent(typeof(AudioSource))]
public class PlayerController : MonoBehaviour {[Tooltip("角色初始朝向是否朝向右边")]public bool FacingRight = true;[Tooltip("移动时角色加速的力大小")]public float MoveForce = 365f;[Tooltip("角色移动的最大速度")]public float MaxSpeed = 5f;[Tooltip("跳跃时向上加速的力大小")]public float JumpForce = 1000f;[Tooltip("检测角色是否落地")]public Transform GroundCheck;[Tooltip("跳跃音效")]public AudioClip[] JumpClips;// 记录角色当前是否处于准备跳跃状态private bool m_IsReadyToJump;// 记录角色当前是否正处于跳跃状态private bool m_IsJumping;// 记录角色当前是否处于着地状态private bool m_GroundedStatus;// 组件引用变量private Rigidbody2D m_Rigidbody2D;private AudioSource m_AudioSource;private void Awake() {// 获取组件引用m_Rigidbody2D = GetComponent<Rigidbody2D>();m_AudioSource = GetComponent<AudioSource>();}private void Start() {// 监测变量是否正确赋值if(GroundCheck == null) {Debug.LogError("请先设置GroundCheck");}// 初始化变量m_IsReadyToJump = false;m_IsJumping = false;m_GroundedStatus = false;}private void Update() {// 通过检测角色和groundCheck之间是否存在Ground层的物体来判断当前是否落地m_GroundedStatus = Physics2D.Linecast(transform.position,GroundCheck.position,LayerMask.GetMask("Obstacle"));// 着地时,如果当前不处于跳跃状态且按下了跳跃键,进入准备跳跃状态if(m_GroundedStatus && !m_IsJumping && Input.GetButtonDown("Jump")) {m_IsReadyToJump = true;}// 刚刚落地,退出跳跃状态if(m_GroundedStatus && m_IsJumping) {m_IsJumping = false;}}private void FixedUpdate() {//获取水平输入float h = Input.GetAxis("Horizontal");// 若h * m_Rigidbody2D.velocity.x为正数且小于MaxSpeed,表示需要继续加速// 若h * m_Rigidbody2D.velocity.x为负数,则表示需要反向加速if(h * m_Rigidbody2D.velocity.x < MaxSpeed) {m_Rigidbody2D.AddForce(Vector2.right * h * MoveForce);}//设置物体速度的阈值if(Mathf.Abs(m_Rigidbody2D.velocity.x) > MaxSpeed) {m_Rigidbody2D.velocity = new Vector2(Mathf.Sign(m_Rigidbody2D.velocity.x) * MaxSpeed,m_Rigidbody2D.velocity.y);}//判断当前是否需要转向if(h > 0 && !FacingRight) {Flip();}else if(h < 0 && FacingRight) {Flip();}// 跳跃if(m_IsReadyToJump) {Jump();}}private void Jump() {// 进入跳跃状态m_IsJumping = true;// 设置一个竖直向上的力m_Rigidbody2D.AddForce(new Vector2(0f, JumpForce));// 退出准备跳跃状态,避免重复跳跃m_IsReadyToJump = false;//随机在角色当前所处的位置播放一个跳跃的音频if(JumpClips.Length > 0) {int i = Random.Range(0, JumpClips.Length);AudioSource.PlayClipAtPoint(JumpClips[i], transform.position);}}private void Flip() {// 修改当前朝向FacingRight = !FacingRight;// 修改scale的x分量实现转向this.transform.localScale = Vector3.Scale(new Vector3(-1, 1, 1),this.transform.localScale);}
}
后言
可以看到,目前角色在运动的时候还没有动画。因为给角色加上动画设计到动画状态机的制作,较为复杂,在下一篇文章将会介绍如何给角色添加动画。最后,本篇文章所做的修改,可以在PotatoGloryTutorial这个仓库的essay5
分支下看到,读者可以clone这个仓库到本地进行查看。
参考链接
- Gravity Scale
- Conventional Game Input
- Physics Material 2D
《土豆荣耀》重构笔记(七)控制角色移动并添加音效相关推荐
- Vue.js 学习笔记 七 控制样式
Vue.js可以灵活的控制样式 我们首先随便写2个样式 <style>.divCss {background-color: green;width:400px;height:400px;} ...
- 《土豆荣耀》重构笔记(五)创建角色以及怪物的动画
章节目录 前言 创建角色和怪物 创建怪物的动画 创建角色动画 制作Prefab 后言 参考链接 前言 在游戏中,角色和AI的移动都需要配上相应的动画,以免让玩家产生游戏中的角色或者AI在平移的不真 ...
- 《土豆荣耀》重构笔记(三)创建游戏场景
章节目录 前言 导入资源 调整Unity布局 创建游戏场景 设置Aspect 放置Sprite Sorting Layer 组织场景中的物体 后言 参考链接 前言 为了记录重构笔记的进度,我在Gi ...
- (完结)Unity游戏开发——新发教你做游戏(七):Animator控制角色动画播放
文章目录 一.前言 二.Animator状态机组织 三.过渡条件 四.用代码设置过渡条件,触发动画播放 五.CharacterAniLogic.cs完整代码 一.前言 文章列表 Unity游戏开发-- ...
- 吴恩达《机器学习》学习笔记七——逻辑回归(二分类)代码
吴恩达<机器学习>学习笔记七--逻辑回归(二分类)代码 一.无正则项的逻辑回归 1.问题描述 2.导入模块 3.准备数据 4.假设函数 5.代价函数 6.梯度下降 7.拟合参数 8.用训练 ...
- 《MFC游戏开发》笔记七 游戏特效的实现(一):背景滚动
本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9344721 作者:七十一雾央 新浪微博:http:// ...
- 【K210】K210学习笔记七——使用K210拍摄照片并在MaixHub上进行训练
[K210]K210学习笔记七--使用K210拍摄照片并在MaixHub上进行训练 前言 K210准备工作 K210如何拍摄照片 准备工作 拍摄相关代码定义 用K210拍摄到的照片在MaixHub平台 ...
- window的dos命令学习笔记 七
文章目录 一.dos历史学习笔记(后期整合到这里,我想能学到这里的应该不多了,嘿嘿,加油) 二.执行状态返回值(`%errorlevel%`,和shell中`$?`相似): 三.视窗 1.color ...
- jQuery整理笔记七----几个经典表单应用
1.文本框获得(失去)焦点 当文本框获得输入焦点时,将该文本框高亮显示,算不得一个应用,仅仅是一个小技巧,能够提高用户体验. <!DOCTYPE html PUBLIC "-//W3C ...
- jQuery整理笔记七----几个经典表单应用 .
登录 | 注册 收藏成功 确定 收藏失败,请重新收藏 确定 标题 标题不能为空 网址 标签 摘要 公开 取消收藏 全部设为已读查看所有通知 暂没有新通知 返回通知列表 下一条 上一条 分享资讯传PPT ...
最新文章
- 1. C语言中只能使用单行注释,贵州大学C语言判断题
- C++Eratosthenes埃氏筛法获取素数列表的实现算法(附完整源码)
- 授人以鱼不如授人以渔——CPU漏洞的Symantec解决之道
- 《PHP精粹:编写高效PHP代码》——1.1节为什么要使用面向对象编程
- 接口500什么原因_80%小餐饮店几乎都“活“不过500天,为什么?都在这5个原因里...
- Oracle11完全卸载方法
- Redis系列 --第一篇
- e盾服务端源码_原罪西游源码发布!!!
- Java Servlet(八):EL自定义函数
- tidyr | 批量处理数据的前奏——数据嵌套化
- vector, list, deque的使用区别
- windows桌面待办事项_想拒绝拖延症?你还缺一款云同步提醒的的桌面便签软件!...
- 容器(Context)使用之支付系统
- (转)log4j(二)——如何控制日志信息的输出?
- ios 启动图一键生成工具_一键生成App图标所有尺寸的三个酷站分享
- 超好看的QQ群管机器人html官网源码
- 惠普扫描应用程序当前正由此计算机上的其,惠普打印机 打印扫描的时候显示“由于另一个程序或另一台计算机正在使用联网的HP成像设备因此无法执行”...
- 李宏毅2020机器学习深度学习(完整版)国语课程PPT
- 工业大数据的关键技术是什么
- 什么叫云计算?云计算通俗解释
热门文章
- python爬虫英文翻译_python爬虫学习---爬取微软必应翻译(中英互译)
- ThinkPHP5旅游管理系统
- dell 服务器ghost系统,Dell 5000笔记本装win7 64位Ghost系统真正成功教程
- 无法创建堆栈的防护页面 解决方法
- 网络安全-SQL注入原理、攻击及防御
- A_A03_001 stc-isp 单片机烧录软件安装与使用
- 《廖雪峰python3教程》| 书评 + 学习笔记干货
- 2022-2028全球记账软件行业调研及趋势分析报告
- 活学活用pic单片机c语言编程pdf,活学活用PIC单片机C语言编程
- 在java中调用python程序