Unreal Engine 4(虚幻UE4)GameplayAbilities 插件入门教程(二)
我们接着学习。如果没有学习第一篇,请前往学习。
由于GameplayAbilities插件基本上没有资料(除了前面提供的那篇Dave的博文以外,再无资料,有迹象表明Dave是这个插件的开发者)。
这个插件究竟能做什么,简单来说是可以制作复杂的技能系统,具体怎么奇妙现在还没有办法说明,不妨亲自动手做一做吧!
第零步【此步骤的目的是建立AbilitySystem】:补充昨天的一个步骤,在人物的cpp文件的构造函数中加入
//头文件加入:#include "AbilitySystemComponent.h" //请注意:如果在h文件中加入头文件,不要添加在generate.h的后面,而应该添加在它的前面。 AGATutCharacter::AGATutCharacter() { //省略一大段代码 …… // Create a follow camera FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera")); FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName); // Attach the camera to the end of the boom and let the boom adjust to match the controller orientation FollowCamera->bUsePawnControlRotation = false; // Camera does not rotate relative to arm //在底部新增! AbilitySystem = CreateDefaultSubobject<UAbilitySystemComponent>(TEXT("AbilitySystem")); // Note: The skeletal mesh and anim blueprint references on the Mesh component (inherited from Character) // are set in the derived blueprint asset named MyCharacter (to avoid direct content references in C++) }
编译完成之后看到蓝图里出现了AbilitySystem组件:
在蓝图中其实还用不上这个东西,我们继续回到cpp文件。
第0.5步【本步骤的目的是为了绑定ability到输入,但是具体如何绑定的不清楚,但是此步骤不可以缺少,有点下文中的AbilityInput枚举类好像没有使用到,此步骤存疑(建议大家稍微粗略看看即可,并将下面提及的代码添上)】:
这里贴一段理论介绍及其机器翻译(引用了这篇文章:)
https://wiki.unrealengine.com/GameplayAbilities_and_You
Binding to Character Input
绑定到人物的输入
First of all, we will bind our ability system to our character's input, because it's the slightly more complicated issue and it's actually pretty interesting on how you do it. So first of all, go back to your character's cpp file, and go to the SetupPlayerInputComponent function. It's the one responsible for binding your character's inputs to the player controlling it, and takes a UInputComponent as parameter. This is important, we need it to bind our ability system to it. We want to call AbilitySystem->BindAbilityActivationToInputComponent within the SetupPlayerInputComponent. It takes two parameters: The UInputComponent pointer at hand and a struct called FGameplayAbiliyInputBinds. This is not a typo! It is not called FGameplayAbilityInputBinds, but FGameplayAbiliyInputBinds!
首先,我们会将我们的能力系统绑定到我们的角色的输入,因为这是一个稍微复杂的问题,它实际上很有趣你是怎么做的。首先,回到你的角色的cpp文件,去SetupPlayerInputComponent函数。它负责将角色的输入绑定到控制它的玩家,并将UInputComponent作为参数。这很重要,我们需要它来约束我们的能力系统。我们想叫AbilitySystem - > BindAbilityActivationToInputComponent SetupPlayerInputComponent内。它接受两个参数:UInputComponent指针和结构称为FGameplayAbiliyInputBinds。这不是一个打字错误!这不是叫FGameplayAbilityInputBinds,但FGameplayAbiliyInputBinds !
(笔者:将AbilitySystem绑定到人物上需要这个关键的一步,但是实践上有出入
)
The constructor for FGameplayAbiliyInputBinds takes at least 3 parameters: The first two are strings, and represent the input names that will be used to define "Confirm" and "Cancel"-input commands. You do not necessarily need these depending on your game, but abilities can be set up to listen to these while they're active, and targeting actors (basically, actors that return an ability viable targets/locations to aim at for an ability, if an ability requests one) will use these too, so generally it can't hurt to have these even if you will never use them. The third parameter is the name of an arbitrary UEnum of all things. This is one of the witchcraft-ier aspects of the system: The ability system component will look into the enum whose name you've given and will map its ability slots to the names of the elements contained within the enum. This probably sounds way complicated from the way I'm describing this, but it's actually quite simple. This is an input enum lifted from my own project:
FGameplayAbiliyInputBinds至少需要三个参数的构造函数:前两个是字符串,并代表输入名称将用于定义固化“确认”和“取消”命令。你不一定需要这些取决于你的游戏,但是能力可以设置听这些活动时,和目标参与者(基本上,演员还能切实可行的目标/位置的瞄准能力,如果能力请求一个)将使用这些,所以一般不会伤害这些即使你永远不会使用它们。第三个参数是所有东西的任意枚举的名称。这是系统的一个主要方面:能力系统组件将查看枚举的名称,并将它的能力位置映射到enum中包含的元素的名称。这听起来很复杂,但实际上很简单。这是一个从我自己的项目中提出来的输入enum:
//Example for an enum the FGameplayAbiliyInputBinds may use to map input to ability slots. //It's very important that this enum is UENUM, because the code will look for UENUM by the given name and crash if the UENUM can't be found. BlueprintType is there so we can use these in blueprints, too. Just in case. Can be neat to define ability packages.
UENUM(BlueprintType)
enum class AbilityInput : uint8
{
UseAbility1 UMETA(DisplayName = "Use Spell 1"), //This maps the first ability(input ID should be 0 in int) to the action mapping(which you define in the project settings) by the name of "UseAbility1". "Use Spell 1" is the blueprint name of the element. UseAbility2 UMETA(DisplayName = "Use Spell 2"), //Maps ability 2(input ID 1) to action mapping UseAbility2. "Use Spell 2" is mostly used for when the enum is a blueprint variable.
UseAbility3 UMETA(DisplayName = "Use Spell 3"),
UseAbility4 UMETA(DisplayName = "Use Spell 4"),
WeaponAbility UMETA(DisplayName = "Use Weapon"), //This finally maps the fifth ability(here designated to be your weaponability, or auto-attack, or whatever) to action mapping "WeaponAbility". //You may also do something like define an enum element name that is not actually mapped to an input, for example if you have a passive ability that isn't supposed to have an input. This isn't usually necessary though as you usually grant abilities via input ID,
//which can be negative while enums cannot. In fact, a constant called "INDEX_NONE" exists for the exact purpose of rendering an input as unavailable, and it's simply defined as -1.
//Because abilities are granted by input ID, which is an int, you may use enum elements to describe the ID anyway however, because enums are fancily dressed up ints.
};
第一步【此步骤的目的是给人物添加Ability】:
在GATUTCharacter.h文件中加入Ability,下面我加入的是数组,暴露给蓝图。
同时您也看到了,添上一个Beginplay方便使用。
第二步【此步骤是为了登记这些Ability,虽然有点复杂,但是是必要的,从第三步开始就能看到一些有意思的内容了】:
void AGATutCharacter::BeginPlay()
{
Super::BeginPlay();
if (AbilitySystem == nullptr)return; UE_LOG(LogTemp, Warning, TEXT("%s"), *FString("Char Beginplay 97"));
if (HasAuthority() && MyAbilities.Num()) {
UE_LOG(LogTemp, Warning, TEXT("%s"), *FString("Char Bplay 99"));
for (auto i = ; i<MyAbilities.Num(); i++)
{
if (MyAbilities[i] == nullptr)continue;
AbilitySystem->GiveAbility(FGameplayAbilitySpec(MyAbilities[i].GetDefaultObject(), , ));
UE_LOG(LogTemp, Warning, TEXT("%s"), *FString("103bp we register an ability!"));
}
UE_LOG(LogTemp, Warning, TEXT("%s"), *FString("All Ablities registered"));
}
AbilitySystem->InitAbilityActorInfo(this, this);
//这两个参数以为着Owner和Avatar
UE_LOG(LogTemp, Warning, TEXT("%s"), *FString("Char Bplay 105"));
}
第三步:
编译,如果没有成功的话,请看原文
https://wiki.unrealengine.com/GameplayAbilities_and_You
第四步【关键!此步骤是为了建立一个Ability蓝图】:
建立一个名为A2的Ability如下:
第五步【配置input,请注意不用完全和我的截图一样】:
第5.5步【在蓝图中为MyAbilities数组赋值】:如果没有这一个步骤的话,第六步是没有效果的,也就是说我们的人物要有A2的声明,AbilitySystem组件才能够认识到这个人物有这个Ability(还记得前文在beginplay中有一句:
AbilitySystem->GiveAbility(FGameplayAbilitySpec(MyAbilities[i].GetDefaultObject(), 1, 0));
吗?这一句话将这些Ability赋予给了AbilitySystem。)
第六步【HelloWorld】:在人物的蓝图中写这个输入事件,然后执行,查看结果是否和我的截图效果一致:
恭喜,你已经HelloWorld完毕了!到这一步我花了四五个小时了。接下来我们研究一些稍微有意思一点的理论知识(大家要勤动脑筋啊)。
第七步【这一步是探究步骤】:
什么是Ability的实例化?
An ability is also able to control its own instancing state, and each ability may independently choose whether they do not want to be instanced (no ability tasks, no personal state and variables and some other limited functionality, but ridiculously cheap so preferable if you can get away with it).
一种能力也能够控制自己的实例状态,并且每种能力都可以独立地选择是否不想被实例化(没有能力任务,没有个人状态和变量,以及其他一些有限的功能,但是如果你能侥幸逃脱的话,它将会变得非常便宜)。
instanced on activation (personal state limited to a per-activation basis, variables and such can be replicated but it is not recommended).
实例化激活(个人状态限制为每个激活的基础,变量,可以复制,但是不推荐)。
or instanced per ability owner (most expensive, but variables can easily be replicated, state can be carried across activations [for example, a fireball that gets stronger with each use would be possible without permanently considering the ability active] and most functions are intact).
或者是每个能力所有者(最昂贵的,但是变量可以很容易被复制,状态可以跨激活)(例如,一个在每次使用时变得更强的火球,如果没有永久地考虑激活的能力)和大多数功能都是完整的。
用笔者自己的话来说是分为三种:
1.每一个Actor(比如每一个英雄)实例化一个此Ability。
2.每一次执行实例化一个此Ability。
3.永不实例化Ability。
实验:
Step1:向上面一样,建立一个Ability称为A3.
Step2:这个A3里面有一个整数,然后打印一下执行次数:
Step3:在A3中看Class Default,设置为每个Actor实例化一次。
Step4:在人物中绑定一下动作和Ability的Activate:
Step5:运行查看结果:
对照实验2:
将上面步骤中的实例化模式设置为Instanced per execution,将会得到:
为什么?心造不宣。
对照实验3:
设置为no instanced,运行,结果宕机。具体是怎么使用的,存疑。
本节的内容还算简单,下一节讲技能标签(AbilityTags)。
——小江村儿的文杰 zouwj5@qq.com 2017年7月14日14:40:39
Unreal Engine 4(虚幻UE4)GameplayAbilities 插件入门教程(二)的更多相关文章
- Unreal Engine 4(虚幻UE4) GameplayAbilities插件入门教程(一)
本文系笔者的实习生分享会内容预备兼GameplayAbilities的初学者教程. 本文适合已有四十天UE4开发经验的初学者. 参考资料:https://wiki.unrealengine.com/G ...
- Unreal Engine 4(虚幻UE4)GameplayAbilities 插件入门教程(三)技能标签(Ability Tags)
本教程参考了https://wiki.unrealengine.com/GameplayAbilities_and_You,如果没有学习前两篇教程,请前往学习. GameplayAbilities插件 ...
- Unreal Engine 4(虚幻UE4)GameplayAbilities 插件入门教程(四)技能屏蔽和简单的Buff等
本节内容继续上一节教程的内容(如果没有看过前面的教程,请前往学习),不会讲太难的新东西,而是继续探究技能标签(Abiilty Tags)的内容.先来一道开胃菜. 第1.1步: 将上一次的召唤冰龙中的C ...
- Unreal Engine 4(虚幻UE4)GameplayAbilities 插件入门教程(七)Ability的信息传递等
本节及后面的内容将会探索更加有意思的内容,更加逼近实际的使用的内容.我们本节内容不难,讲的是释放Ability时的信息传递: 第一步:创建一个GA称为GA_AOE_BlindVengeance,复仇忌 ...
- Unreal Engine 4(虚幻UE4)GameplayAbilities 插件入门教程(六)GameplayEffect的级别设置
本节的内容不难,权当是复习.如果没有完成前面的教程,请前往学习. 第一步:用一个csv文件表示级别数据,下图中的Hurt随级别1~7表示其损伤值在1~7级别时分别是-7,-14,-20等.写好之后关闭 ...
- Unreal Engine 4(虚幻UE4)GameplayAbilities 插件入门教程(五)技能属性集(AttributeSet)
如果没有完成前面的教程,请前往学习.先上一段理论介绍(源于https://wiki.unrealengine.com/GameplayAbilities_and_You#GameplayTasks): ...
- SpringBoot入门教程(二)CentOS部署SpringBoot项目从0到1
在之前的博文<详解intellij idea搭建SpringBoot>介绍了idea搭建SpringBoot的详细过程, 并在<CentOS安装Tomcat>中介绍了Tomca ...
- JasperReports入门教程(二):中文打印
JasperReports入门教程(二):中文打印 背景 在上一篇中我们介绍了JasperReport的基本入门,也展示了一个报表.但是我们的示例都是使用的英文,如果我们把需要打印的数据改为中文会怎么 ...
- 无废话ExtJs 入门教程二十一[继承:Extend]
无废话ExtJs 入门教程二十一[继承:Extend] extjs技术交流,欢迎加群(201926085) 在开发中,我们在使用视图组件时,经常要设置宽度,高度,标题等属性.而这些属性可以通过“继承” ...
随机推荐
- Goolge全球各国域名大全
搜索过技术文章的朋友都知道,Google的搜索功力绝对是世界第一,仅仅搜索中文还体现不出Google的功力,如果大家是做外贸或者搜索其它语言的文章,就会知道Google的内涵有多少了.全世界的国家Go ...
- java.lang.NoClassDefFoundError: Could not initialize class org.jfree.chart.JFreeChart
最近在进行利用jfreechart生成图表时发现,项目在本地运行的好好的,一部署到服务器(linux系统)上就不行,报这样的错误: java.lang.NoClassDefFoundError: Co ...
- centos7下Redis-Sentinel安装和配置
一.Redis的安装 1.从官网https://redis.io/download下载最新的stable版本(也可以下载unstable版本)redis-4.0.9.tar.gz. 2.上传到Cent ...
- html5、canval 对 图片的压缩
let src = this.cropper.getCroppedCanvas().toDataURL('image/jpeg');let can = document.createElement(' ...
- 算法训练 P1103
算法训练 P1103 时间限制:1.0s 内存限制:256.0MB 编程实现两个复数的运算.设有两个复数 和 ,则他们的运算公式为: 要求:(1)定义一个结构体类型来描述复数. ...
- css里涉及到定位相关的example实例
一,情景导入:正常文档流:指的是HTML文档在进行内容布局时所遵循的从左到右,从上到下的表现方式.HTML中的大多数元素都处在正常的文档流中,而一个元素要脱离正常流的唯一途径就是浮动或定位.二,定位的 ...
- 【知识笔记】ASP.NET报错问题
一.前端asp.net在远程部署到IIS时报错:Web 部署任务失败,在远程计算机上处理请求时出错 服务器在处理请求时遇到问题.请与服务器管理员联系以了解详细信息((2017/6/16 16:22:4 ...
- 使用Visual Studio Code开发Asp.Net Core WebApi学习笔记(三)-- Logger
本篇是在上一篇的基础上添加日志功能,并记录NLog在Asp.Net Core里的使用方法. 第一部分:默认Logger支持 一.project.json添加日志包引用,并在cmd窗口使用 dotnet ...
- django中的FBV和CBV
django中请求处理方式有2种:FBV 和 CBV 一.FBV FBV(function base views) 就是在视图里使用函数处理请求. 看代码: urls.py from django.c ...
- js 命名空间
yui的命名空间和继承机制 var YAHOO = window.YAHOO || {};YAHOO.namespace = function(ns) { if (!ns || !ns. ...