【Unity】动作游戏开发实战详细分析-26-组合攻击


基本思想

在游戏中,有些攻击方法必须要等待条件触发后才可以执行,并且根据情况的不同会发挥不同的效果,这是一种有前置条件要求的组合攻击方式。

脚本逻辑结构

我们先看一下这个模块的脚本结构

ComposeAttackController脚本中存放着不同的攻击组合类型,通过Update事件函数每帧更新当前可触发的组合攻击,并信息存储在索引字段中。上下文结构信息存放了组合攻击所需要的角色自身组件,例如Animator、Transform等。

模块代码实现

首先这是组合攻击的抽象类,定义了基本的方法

  • CanTrigger,用于判断组合技是否达到了触发条件,他的输入参数要求信息上下文
  • Trigger,用于处理触发逻辑
public abstract class ComposeAttackBase : ScriptableObject
{public abstract bool CanTrigger(ComposeAttackContext context, bool prepareTrigger);public abstract IEnumerator Trigger(ComposeAttackContext context);
}
public struct ComposeAttackContext
{public Transform CasterTransform { get; set; }public Animator Animator { get; set; }
}

然后就是组合攻击控制器

该控制器用于控制当前控制器下所有的攻击组件,并且通过Update进行每帧判断,并将可使用的攻击索引存储在字段中。并提供了外部的触发接口对对应的攻击组件进行触发

public class ComposeAttackController : MonoBehaviour
{[SerializeField] Animator animator = null;//上下文所需接口,面板暴露参数[SerializeField] ComposeAttackBase[] composeAttackArray = null;//组件列表面板暴露参数public int TriggerableComposeAttackIndex { get; private set; }//当前已触发的组合技能索引public ComposeAttackBase[] GetComposeAttackArray()//对外提供组合技能数组列表{return composeAttackArray;}public void Update()//每一帧更新组合技能是否触发逻辑,但可修改.enabled关闭脚本更新{var context = new ComposeAttackContext() { Animator = animator, CasterTransform = transform };for (int i = 0; i < composeAttackArray.Length; i++){var item = composeAttackArray[i];if (item.CanTrigger(context, true))//触发条件检测{TriggerableComposeAttackIndex = i;break;}}}public IEnumerator TriggeredComposeSkill(int index)//组合技能的触发接口{if (index > composeAttackArray.Length - 1)throw new ArgumentOutOfRangeException();var context = new ComposeAttackContext() { Animator = animator, CasterTransform = transform };yield return composeAttackArray[index].Trigger(context);}
}

测试代码

public class ComposeAttackController_Test : MonoBehaviour
{public ComposeAttackController composeAttackController;public Animator[] animators;void Update(){if (InputCache.AttackButton){StartCoroutine(composeAttackController.TriggeredComposeSkill(composeAttackController.TriggerableComposeAttackIndex));for (int i = 0; i < animators.Length; i++){animators[i].enabled = false;animators[i].enabled = true;animators[i].Play("LightHit", 0, 0);}}}
}
public class InputCache : MonoBehaviour
{public static bool AttackButton { get; set; }void Update(){AttackButton = Input.GetKeyDown(KeyCode.J);}
}
[CreateAssetMenu(fileName = "ComposeAttack1", menuName = "ComposeAttacks/Attack1")]
public class ComposeAttack1 : ComposeAttackBase
{public float yOffset = 1f;//检测碰撞的y轴偏移public Vector3 size = new Vector3(1f, 2f, 1f);//检测碰撞的大小public Vector4 aroundOffset = new Vector4(0.5f, 0.5f, 0.5f, 0.5f);//前后左右检测距离偏移public LayerMask layerMask;bool mIsForwardAndBackword;public override bool CanTrigger(ComposeAttackContext context, bool prepareTrigger){var upAxis = -Physics.gravity.normalized;//垂直轴var right = Vector3.ProjectOnPlane(context.CasterTransform.right, upAxis);//投影的右侧方向var forward = Vector3.ProjectOnPlane(context.CasterTransform.forward, upAxis);//投影的前方var upAxisOffset = upAxis * yOffset;//垂直轴偏移var forwardFlag = Physics.CheckBox(context.CasterTransform.position+ upAxisOffset + forward * aroundOffset.x, size, Quaternion.identity, layerMask);var backwardFlag = Physics.CheckBox(context.CasterTransform.position+ upAxisOffset + (-forward) * aroundOffset.y, size, Quaternion.identity, layerMask);if (forwardFlag && backwardFlag)//前后都有敌人{if (prepareTrigger) mIsForwardAndBackword = true;return true;}var leftFlag = Physics.CheckBox(context.CasterTransform.position+ upAxisOffset + (-right) * aroundOffset.z, size, Quaternion.identity, layerMask);var rightFlag = Physics.CheckBox(context.CasterTransform.position+ upAxisOffset + right * aroundOffset.w, size, Quaternion.identity, layerMask);if (rightFlag && leftFlag)//左右都有敌人{if (prepareTrigger) mIsForwardAndBackword = false;return true;}return false;}public override IEnumerator Trigger(ComposeAttackContext context){Debug.Log("Trigger!");yield return null;if (mIsForwardAndBackword)//前后都有敌人的情况{context.Animator.Play("Range_Attack", 0, 0);}else//左右都有敌人的情况{context.CasterTransform.forward = context.CasterTransform.right;//先将角色朝向切至右边context.Animator.Play("Range_Attack", 0, 0);}}
}

【Unity】动作游戏开发实战详细分析-26-组合攻击相关推荐

  1. 【Unity】动作游戏开发实战详细分析-07-连续技与组合技功能设计

    [Unity]动作游戏开发实战详细分析-07-连续技与组合技功能设计 基本思路 在一些动作游戏中,存在着连续技这一功能,具体来说就是连续按下规定的按键会触发能力的功能,或者是长按触发等等. 实现解析 ...

  2. 【Unity】动作游戏开发实战详细分析-16-敌人AI设计

    [Unity]动作游戏开发实战详细分析-16-敌人AI设计 基本思想 本文来实现简单的敌人AI,使用协程来开发AI.如果想要使用行为树插件可自行学习使用. 代码实现 敌人的目标信息结构 用于存储所有的 ...

  3. 【Unity】动作游戏开发实战详细分析-06-技能系统设计

    [Unity]动作游戏开发实战详细分析-06-技能系统设计 基本思想 不同的技能可以设计为技能模版,当角色释放技能时,会通过模版ID将它进行实例化,这个实例技能类可以是一个挂载的MonoBehavio ...

  4. 【Unity】动作游戏开发实战详细分析-25-角色残影效果的实现

    [Unity]动作游戏开发实战详细分析-25-角色残影效果的实现 基本思路 Unity中的蒙皮网格组件提供了一个接口BakeMesh,允许我们拿到当前动画帧的网格数据,借此可对烘焙网格使用半透明的边缘 ...

  5. 【Unity】动作游戏开发实战详细分析-15-可扩展的战斗系统

    [Unity]动作游戏开发实战详细分析-15-可扩展的战斗系统 系统设计 攻击信息传递 通常情况下,伤害.属性.判定都会被封装到类中,在触发动画事件后将战斗信息发送给受击者. 我们可以结合Unity碰 ...

  6. 【Unity】动作游戏开发实战详细分析-24-流血喷溅程序

    [Unity]动作游戏开发实战详细分析-24-流血喷溅程序 溅落血迹效果 实现思路 利用对象池的代码设计思路,通过随机性来实现随机的溅落血迹效果. 代码 public class DripBloodF ...

  7. 五分钟详述:一文理解动作游戏开发中的攻击逻辑和受击逻辑

    前言: 本文节选自机械工业出版社出版的<Unity3D动作游戏开发实战>一书,略有改动. 攻击逻辑 一个好的操作手感对于战斗非常重要,玩家会根据当前动画状态来确定下一步输入,若手感混乱则会 ...

  8. 【游戏开发实战】Unity从零开发多人视频聊天功能,无聊了就和自己视频聊天(附源码 | Mirror | 多人视频 | 详细教程)

    文章目录 一.前言 二.思考问题与解决方案 1.思考问题 2.解决方案 2.1.Unity中如何开启摄像头并对图像进行采样 2.2.图像如何中转给其他客户端 2.3.如何实现清晰度切换 2.4.客户端 ...

  9. 《Unity 2D与3D手机游戏开发实战》简介

    #好书推荐##好书奇遇季#<Unity 2D与3D手机游戏开发实战>,京东当当天猫都有发售.彩色印制,定价89元,网店打折销售更便宜.本书配套源码.PPT课件,适合Unity游戏开发初学者 ...

  10. 《Unity 5.x游戏开发实战》一1.9 添加一个水平面

    本节书摘来异步社区<Unity 5.x游戏开发实战>一书中的第1章,第1.9节,作者: Alan Thorn 译者: 李华峰 责编: 胡俊英,更多章节内容可以访问云栖社区"异步社 ...

最新文章

  1. 获取人口_Human Terrain——世界人口三维可视化
  2. FSLib.Extension库
  3. python获取已打开网页的html,【已解决】Python的BeautifulSoup去实现提取带tag的HTML网页主体内容...
  4. boost::phoenix::bind相关的测试程序
  5. 终端架构深研,CodeDay 成都站等你
  6. (总结)HTTP常见错误返回代码
  7. Ant Design Pro 修改title
  8. 苏州大学计算机科学研究生,报录比最高专业TOP10!就离谱!
  9. [转载]JS语法字典
  10. ChaiNext:主流代币回调
  11. NeurIPS 2021 | Garment4D: 从点云序列中重建衣物
  12. php 时间转换时间戳_php时间戳转换日期方法总结
  13. crashdumpandroid_Android Stability - crash 和 ramdump
  14. java excel 导出加密
  15. 大家都在学Python,你和别人的差距在哪?
  16. 搭配Online:腾讯吃鸡手游《PUBG Mobile》及《和平精英》(前《刺激战场》)全球收入超15亿美元!
  17. Kinetics-400数据集简介及下载
  18. equest.getRequestDispatcher方法的作用是什么
  19. coursera python_如何最高效且自由地收看Coursera
  20. 我给鸿星尔克写了一个720°全景看鞋展厅

热门文章

  1. 通过JSP页面访问Servlet
  2. windows远程连接不能复制粘贴
  3. 深入解析protobuf 2-自定义protoc 插件
  4. 使用css3制作正六面体
  5. windows桌面待办事项_提醒待办事项app哪个好用?苹果手机上有什么好用的提醒便签软件吗...
  6. 一个故事看懂计算机操作系统的进化史
  7. Spring AOP报错Set ‘exposeProxy‘ property on Advised to ‘true‘ to make it available问题
  8. nginx 的proxy 时间讲解
  9. Linux man中文手册的安装与使用
  10. Mysql之三少一多原则