我们接着学习。如果没有学习第一篇,请前往学习。

由于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 插件入门教程(二)的更多相关文章

  1. Unreal Engine 4(虚幻UE4) GameplayAbilities插件入门教程(一)

    本文系笔者的实习生分享会内容预备兼GameplayAbilities的初学者教程. 本文适合已有四十天UE4开发经验的初学者. 参考资料:https://wiki.unrealengine.com/G ...

  2. Unreal Engine 4(虚幻UE4)GameplayAbilities 插件入门教程(三)技能标签(Ability Tags)

    本教程参考了https://wiki.unrealengine.com/GameplayAbilities_and_You,如果没有学习前两篇教程,请前往学习. GameplayAbilities插件 ...

  3. Unreal Engine 4(虚幻UE4)GameplayAbilities 插件入门教程(四)技能屏蔽和简单的Buff等

    本节内容继续上一节教程的内容(如果没有看过前面的教程,请前往学习),不会讲太难的新东西,而是继续探究技能标签(Abiilty Tags)的内容.先来一道开胃菜. 第1.1步: 将上一次的召唤冰龙中的C ...

  4. Unreal Engine 4(虚幻UE4)GameplayAbilities 插件入门教程(七)Ability的信息传递等

    本节及后面的内容将会探索更加有意思的内容,更加逼近实际的使用的内容.我们本节内容不难,讲的是释放Ability时的信息传递: 第一步:创建一个GA称为GA_AOE_BlindVengeance,复仇忌 ...

  5. Unreal Engine 4(虚幻UE4)GameplayAbilities 插件入门教程(六)GameplayEffect的级别设置

    本节的内容不难,权当是复习.如果没有完成前面的教程,请前往学习. 第一步:用一个csv文件表示级别数据,下图中的Hurt随级别1~7表示其损伤值在1~7级别时分别是-7,-14,-20等.写好之后关闭 ...

  6. Unreal Engine 4(虚幻UE4)GameplayAbilities 插件入门教程(五)技能属性集(AttributeSet)

    如果没有完成前面的教程,请前往学习.先上一段理论介绍(源于https://wiki.unrealengine.com/GameplayAbilities_and_You#GameplayTasks): ...

  7. SpringBoot入门教程(二)CentOS部署SpringBoot项目从0到1

    在之前的博文<详解intellij idea搭建SpringBoot>介绍了idea搭建SpringBoot的详细过程, 并在<CentOS安装Tomcat>中介绍了Tomca ...

  8. JasperReports入门教程(二):中文打印

    JasperReports入门教程(二):中文打印 背景 在上一篇中我们介绍了JasperReport的基本入门,也展示了一个报表.但是我们的示例都是使用的英文,如果我们把需要打印的数据改为中文会怎么 ...

  9. 无废话ExtJs 入门教程二十一[继承:Extend]

    无废话ExtJs 入门教程二十一[继承:Extend] extjs技术交流,欢迎加群(201926085) 在开发中,我们在使用视图组件时,经常要设置宽度,高度,标题等属性.而这些属性可以通过“继承” ...

随机推荐

  1. koa 框架 介绍 -- 待续

    对比 express  更小  更健壮 解决繁琐的回调函数嵌套, 并极大地提升错误处理的效率 Koa 的核心设计思路是为中间件层 提供高级语法糖封装, (其实就是用了 ES6的生成器, 能中断函数的执 ...

  2. mysql_query — 发送一条 MySQL 查询

    仅对 SELECT,SHOW,EXPLAIN 或 DESCRIBE 语句返回 一个资源标识符,如果查询执行不正确则返回 FALSE.对于 其它类型的 SQL 语句,在执行成功时返回 TRUE,出错时返 ...

  3. define 常量的定义和读取

    define(‘常量’,‘常量值’)----------------------define来定义常量, echo 也能输出常量, get_defined_constants(true)------- ...

  4. JDK中Integer类的进制转换实现

    JDK中关于Integer类的进制转换方法很精巧,具体实现如下: final static char[] digits = { '0' , '1' , '2' , '3' , '4' , '5' , ...

  5. Android RIL结构分析与移植

    介绍 本文档对Android RIL部分的内容进行了介绍,其重点放在了Android RIL的原生代码部分. 包括四个主题: 1.Android RIL框架介绍 2.Android RIL与 Wind ...

  6. 如何从ie11降到ie9

    如果你是win7,中间没有安装过IE10的话,在系统已安装的更新中找到IE11右键卸载后就会回滚到IE9. ie11浏览器现在win7和win8版本的都已经发布了;但是因为一些12306火车票订票网站 ...

  7. pygame经典sprite精灵类

    import cStringIO, base64 import pygame from pygame.locals import * class Ball(pygame.sprite.Sprite): ...

  8. [LeetCode&Python] Problem 700. Search in a Binary Search Tree

    Given the root node of a binary search tree (BST) and a value. You need to find the node in the BST ...

  9. 今天遇到的一个奇葩的NoClassFound的问题

    nohup的日志中报错 java.lang.NoClassDefFoundError: org/apache/catalina/core/ApplicationContext$DispatchData ...

  10. CTF-练习平台-Misc之 宽带信息泄露

    七.宽带信息泄露 下载文件发现是bin文件,题目又说是宽带,所以用工具RouterPassView,打开工具 打开bin文件 快捷键:Ctrl+F搜索username 找到宽带用户名了.