用Unity实现游戏弹反效果
大渣好。
老贼的黑魂系列,想必大家都乐(tong)在其中。
那么要说到魂系列、乃至很多其他ACT要素浓郁的作品,最核心的机制之一,那就是弹反(视游戏不同叫法也不同,一闪、完美防御、弹开等等)。
实现了这个效果,(理论上)你也可以做一个类似的游戏出来(强调:只是理论上,只是理论上)。
今天我们就用简单粗暴的方法来实现一个弹反。
先看效果图。
图中可知:
- 持续格挡,受击时有晃动、硬直动作。
- 完美格挡成功时(会根据攻击方向进行格挡),敌人攻击会被弹开。
- 当敌人被弹开攻击3次时,会进入后仰慢动作。
这次用的资源是在https://www.mixamo.com里免费下的Great Sword Pack和Pro Sword And Shield Pack,需要的可以在工程里边拉或者自行下载。导入资源后,用Plane和Cube随便搭建一个场地。
由于这是一个简单版的弹反功能实现,因此我们只需要制作两个功能残缺的工具人:一个只会左砍右砍的双刀火鸡哥,一个只能跑和防反的大剑姐。
一、双剑角色
1.功能及动画状态机
双剑角色作为被弹反的工具人,免费包里没有演出效果比较好的动画,最终只好用同一个挥砍动画(Slash)通过调节应用在三个状态中(完美符合乞丐版气息):左砍、右砍(镜像)、被弹反(调节播放速度为负),自己有动画的小伙伴请毫不犹豫地自行替换。
2.实现思路:
(1)在每个动画快结束的时候执行动画帧事件,随机下一个Slash(挥刀)状态,激活对应攻击源,用于判定攻击方向。
(2)Slash时用动画帧事件激活武器上的触发器。
(3)被弹反的时候,调节播放速度AnimaSpeed为负,使其回放。
(4)当被弹反3次时触发BehitBack后仰动画。
3.相关设置
(1)角色设置
以下添加的Collider都勾选IsTrigger。
①给角色添加CapsuleCollider,然后调节至跟角色差不多大小。
②添加RigidBody,并勾选IsKinematic。
③展开角色的骨骼,分别给双剑所在节点加上BoxCollier组件,并且调节至跟剑差不多大小,设置Tag为”EWeapon”,用于格挡时碰撞检测。
④在剑的节点下边新建一个空的物体SwordOri并添加Collider组件,设置Tag”为EWeaponOri”,作为攻击源用于给玩家判定攻击方向。
(2)设置动画
因为需要一个后仰的慢动作,把BehitBack动画的Speed调为0.5。
4.部分功能实现
(1)激活武器的Collider
- 双击Animator窗口里的LSlash,展开Events,拖动动画进度条。
- 在手刚挥到角色前方的位置,点击Events下“+”,添加动画帧事件(当动画播放到这个位置时会执行对应名称的方法),设置完成后Apply。
由于LSlash和RSlash使用的是同一个动画,这里通过获取当前动画状态的名字的方式来判断应该激活哪边的武器Collider,代码(含注释)如下:
- //激活武器Collider
- public void OnAnimation_OpenSwordCollider()
- {
- if (beBlock)
- {
- return;
- }
- //获取当前动画信息
- aniInfo = animator.GetCurrentAnimatorStateInfo(0);
- if (aniInfo.IsName("LSlash")) //激活左剑Collider
- {
- lSwordCollider.enabled = true;
- }
- else if (aniInfo.IsName("RSlash")) //激活右剑Collider
- {
- rSwordCollider.enabled = true;
- }
- }
复制代码
同理,在砍动作结束时添加动画帧事件关闭武器的Collider。
(2)被弹反
这次乞丐版的弹反实际上是Slash动画的回放,所以只要播放速度为负即可,为了提升视觉效果,我们通过动画曲线模拟先快后慢的弹开速度。
①设置动画曲线
在脚本中声明一个变量public AnimationCurve animaSpeed,保存后我们可以在Unity中找到这个变量,点击右侧图框便能编辑曲线。
横轴将作为时间,竖轴将作为播放速度(具体参数按自己喜好调节):
②根据动画曲线调节播放速度
- 打开Animator窗口,添加float类型参数AnimaSpeed。
- 找到LSlash和RSlash两个动画状态,分别勾选Speed下Multiplier的Parameter并选择AnimSpeed,把动画播放的速度与参数AnimaSpeed建立联系。
- 通过AnimationCurve.Evaluate(float time)设置AnimaSpeed来调节播放速度。
代码(含注释)如下:
- //被格挡时触发动作回弹
- public IEnumerator BeBlocked()
- {
- OnAnimation_CloseWeaponCollier(); //关闭武器碰撞盒
- beBlock = true;
- beBlockCounter += 1; //被弹反次数+1
- timer = 0;
- while (timer < 0.8f) //弹反动画播放0.8s
- {
- SetAnimaSpeed();
- yield return new WaitForFixedUpdate();
- }
- beBlock = false;
- OnAnimation_RandomAState(); //随机下一个状态
- animator.SetFloat("AnimaSpeed", 1); //播放速度恢复正常
- }
- //设置格挡回弹时的速度
- public void SetAnimaSpeed()
- {
- timer += Time.fixedDeltaTime; //计时
- animaSpeed = animaSpeedCur.Evaluate(timer); //读取曲线数据
- animator.SetFloat("AnimaSpeed", animaSpeed); //设置播放速度
- }
复制代码
二、大剑角色
1.功能及动画状态机
大剑角色具有只有格挡(完美格挡、持续格挡、受击)和移动功能。
2.实现思路:
(1)点击右键,进入PerfectBlock状态,根据敌人攻击来方触发对应的格挡动画。
(2)当在PerfectBlock状态下,手机游戏购买敌人的武器碰到格挡Collider时会被弹反。
(3)按住右键进入KeepBlocking状态,持续防御。
(4)当在KeepBlocking状态下,敌人的武器碰到格挡Collider时,玩家被击晃动。
3.相关设置
(1)角色设置
以下添加的Collider都勾选IsTrigger。
①给角色添加Character Controller组件,用于实现移动。
②添加BoxCollider,调节大小与位置,使其位于角色前方,用于探测敌人和判定攻击方向。
③展开角色骨骼,在武器节点下新建空的子物体BlockCollider并添加BoxCollider,用于格挡检测,可以适量调大来增加格挡容错率。
(2)动画设置
当只有左方向的格挡动画时,可以通过设置动画状态的Mirror(镜像)属性获得右方向的格挡动画。
拿PerfectBlock作为例子,在Animator添加一个Bool类型参数isRightB,在Inspector窗口如下图设置:勾选Mirror右侧Parameter,并选择参数isRightB,表示当isRightB为true时播放镜像。接下来只需在脚本中控制isRightB的切换就可以控制左右格挡。
剩下的KeepBlock、BlockImpact、BlockEnd状态也这样操作,就可以获得一套右格挡动画。
4.部分功能实现
Block
(1)角色上的代码(含注释)如下:
①敌人攻击时,大剑角色前方的大Collider会检测到敌人的SwordOri。
- private void OnTriggerEnter(Collider other)
- {
- if (other.CompareTag("Enemy")) //获取敌人Transform
- {
- targetTrans = other.transform;
- }
- if (other.CompareTag("EWeaponOri")) //检测敌人攻击时激活的攻击源Collider
- {
- eWeaponOriTrans = other.transform;
- }
- }
复制代码
②敌人攻击时会激活SwordOri,通过计算SwordOri与角色右方的夹角,决定格挡方向。
- //检测攻击方向
- void CheckAttackDir(Vector3 eWeaponOriPos)
- {
- Vector3 aDir = eWeaponOriPos - transform.position; //从玩家指向敌人攻击源
- float angle = Vector3.Angle(transform.right, aDir); //计算aDir与角色右方的夹角
- if (angle < 90) //夹角<90度往右格挡
- {
- isRightB = true;
- }
- else
- {
- isRightB = false; //否则往左格挡
- }
- }
复制代码
③激活blockCollider进行碰撞监测,并且根据攻击来向播放相应的格挡动画。
- //格挡
- public void Block()
- {
- if (isFighting) //如果战斗相关动画在播放,则返回
- {
- return;
- }
- if (eWeaponOriTrans) //如果检测到敌人攻击源
- {
- CheckAttackDir(eWeaponOriTrans.position); //检测敌人攻击方向
- }
- LookAtTarget(); //转向目标
- isBlocking = true;
- isPerfectBlock = true;
- blockCollider.SetActive(true); //激活格挡Collider
- animator.SetTrigger("Block");
- }
复制代码
(2)BlockCollider上的代码(含注释)如下:
在BlockCollider上添加脚本,当碰到敌人的武器时,如果玩家是PerfectBlock状态,使敌人变为BeBlock状态,触发弹反,否则玩家进入格挡受击状态(isBImpact)。
- private void OnTriggerEnter(Collider other)
- {
- if (other.CompareTag("EWeapon"))
- {
- Enemy enemy = other.GetComponentInParent<Enemy>();
- if (!player.isPerfectBlock)
- {
- player.isBImpact = true; //格挡受击
- }
- else
- {
- enemy.eState = Estate.BeBlock; //弹反
- }
- }
- }
复制代码
结语:实现简单版弹反的主要功能基本都介绍完了,实质上是Collider与Animator的应用,有兴趣的小伙伴可以下载工程看看设置参数或者其他小功能的实现,希望对大家有所启发。
用Unity实现游戏弹反效果相关推荐
- unity 2D游戏实现传送门效果
第一步:首先制作一个传送门的2D的图片(这个是我做的有点简陋大家可以拿去使用) 第二步:给传送门添加一个胶囊碰撞体 第三步:添加代码 public class Portal : MonoBehavio ...
- unity脚本控制逐渐消失_Unity实现只狼弹反后处理效果
简介 今天是只狼发售一周年,作为去年的goty,只狼最核心的系统莫过于弹反,笔者去年也是和弦一郎大战几百回合,通关之后很想实现以下弹反瞬间的效果. 最终实现效果如下: Unity实现只狼弹反后处理效果 ...
- Unity 2D游戏开发教程之2D游戏的运行效果
Unity 2D游戏开发教程之2D游戏的运行效果 2D游戏的运行效果 本章前前后后使用了很多节的篇幅,到底实现了怎样的一个游戏运行效果呢?或者说,游戏中的精灵会不会如我们所想的那样运行呢?关于这些疑 ...
- Unity 2D游戏开发教程之2D游戏的运行效果
Unity 2D游戏开发教程之2D游戏的运行效果 2D游戏的运行效果 本章前前后后使用了很多节的篇幅,到底实现了怎样的一个游戏运行效果呢?或者说,游戏中的精灵会不会如我们所想的那样运行呢?关于这些疑问 ...
- 【游戏开发实战】使用Unity制作水果消消乐游戏教程(八):游戏得分加分效果
文章目录 一.前言 二.使用TextMeshPro显示得分 1.导入TTF字体到工程中 2.创建字源txt文件 3.生成字体asset 4.制作得分预设 三.得分数字动画 四.得分代码 五.运行测试 ...
- 《Unity 3D 游戏开发技术详解与典型案例》——1.3节第一个Unity 3D程序
本节书摘来自异步社区<Unity 3D 游戏开发技术详解与典型案例>一书中的第1章,第1.3节第一个Unity 3D程序,作者 吴亚峰 , 于复兴,更多章节内容可以访问云栖社区" ...
- NVIDIA显卡3D设置 让你的游戏得到最佳效果
NVIDIA显卡3D设置 让你的游戏得到最佳效果 来源:电脑软硬件应用网 编辑: 黄燕飞 发布时间: 12-02-24 很多朋友的n卡(NVIDIA英伟达,简称N卡) ,都是在wi ...
- unity 2D游戏开发 制作帧动画的两种方法
本小主在这里给大家分享一下unity 2D游戏开发中制作帧动画的两种方法. 比较简单,一学即会. 方法一: 是用代码控制: 先创建一个2D工程.导入图片资源,并设置texture的texture ty ...
- 自制Unity小游戏TankHero-2D(1)制作主角坦克
自制Unity小游戏TankHero-2D(1)制作主角坦克 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm)这个游戏制作的. ...
最新文章
- winform调用webservice增删查改_教你分别用数据库与云函数实现“增删查改”
- 把关与服务的关系_泉州代做投标书-电子标书值得信赖 - 泉州广告服务
- NoSuchMethodError 常见原因及解决方法
- python-31:然而我发现结果并不是我想要的
- jogamp:MAC机,有的能正常运行,有的直接崩溃
- iis php 映射,iis添加php的模块映射
- 大华海康宇视等监控安防摄像头如何通过GB/T28181平台接入到GB28181国标流媒体平台
- 绩效管理-目标拆解技巧
- matlab三角形外接圆
- 74LVC1G3157GW
- 陈老师排课12A排早晚自习课、假期补课表的方法
- HTML基础-笔记1标签
- (华为社招岗位,部门---公共开发部,数字能源,计算,Carbu, 上海海思,GTS,海思,2012):上海!上海上海!
- cmake中如何添加fPIC编译选项
- React.createElement()的使用
- linux下ss工具简介
- 路由器攻击java,局域网中ARP攻击和浏览器挟持的解决方法
- jdbc 胖连接_JDBC完美连接方法
- 存储过程实现银行转账的简易操作
- Windows/Windows下堪称神器的软件集合
热门文章
- bootstrap mysql分页_bootstrap分页
- web python php golang_python go 语言完成最简单的web应用
- 深度学习-Tensorflow2.2-RNN循环神经网络{11}-评论分类-25
- mysql jdbc allow_mysql的jdbc.url携带allowMultiQueries=true参数的作用及其原理
- 机器学习:神经网络矩阵形式,向量形式,矩阵求导
- BZOJ 1602: [Usaco2008 Oct]牧场行走 倍增裸题
- 一个关于组织学员学习技术的笔试题--求讨论
- Java:清空文件内容
- NEFU 560 半数集
- Fragment Summary 2/2