{"id":3144,"date":"2021-01-02T14:10:59","date_gmt":"2021-01-02T06:10:59","guid":{"rendered":"http:\/\/blog.coolcoding.cn\/?p=3144"},"modified":"2021-01-02T19:42:11","modified_gmt":"2021-01-02T11:42:11","slug":"gameplaytasks-api-making-things-happen-with-gameplaytasks","status":"publish","type":"post","link":"https:\/\/blog.coolcoding.cn\/?p=3144","title":{"rendered":"GameplayTasks API \u2013 making things happen with GameplayTasks"},"content":{"rendered":"\n<p> GameplayTasks\u00a0are used to wrap up some gameplay functionality in a reusable object. All you have to do to use them is derive from the\u00a0UGameplayTask\u00a0base class and override some of the member functions that you prefer to implement. <\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Getting ready<\/h1>\n\n\n\n<p>If you have not done so already, complete Steps 1-4 of the&nbsp;<em>GameplayAbilities API \u2013 triggering an actor&#8217;s gameplay abilities with game controls<\/em>&nbsp;recipe to link to the&nbsp;GameplayTasks&nbsp;API in your&nbsp;ProjectName.Build.cs&nbsp;file and enable its functionality.<\/p>\n\n\n\n<p>Afterwards, go in the UE4 Editor and navigate to&nbsp;Class Viewer&nbsp;by going to&nbsp;Window | Developer Tools | Class Viewer. Under&nbsp;Filters, uncheck the&nbsp;Actors Only&nbsp;and&nbsp;Placeable Only&nbsp;options.<\/p>\n\n\n\n<p>Ensure that the&nbsp;GameplayTask&nbsp;object type exists:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/blog.coolcoding.cn\/wp-content\/uploads\/2021\/01\/3294cedd-2012-4aee-b372-41fee61f3347.png\" alt=\"\"\/><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">How to do it&#8230;<\/h1>\n\n\n\n<ol><li>Click on&nbsp;File&nbsp;|&nbsp;Add C++ Class&#8230;. Choose to derive from&nbsp;GameplayTask. To do so, you must first tick&nbsp;Show All Classes, and then type&nbsp;gameplaytask&nbsp;into the filter box. Click on&nbsp;Next:<\/li><\/ol>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/blog.coolcoding.cn\/wp-content\/uploads\/2021\/01\/bcf5cdab-33de-40f8-82db-fc30adcbe46e.png\" alt=\"\"\/><\/figure>\n\n\n\n<ol><li>Name your C++ class (something like&nbsp;GameplayTask_TaskName&nbsp;is the convention), then add the class to your project. The example spawns a particle emitter and is called&nbsp;GameplayTask_CreateParticles:<\/li><\/ol>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/blog.coolcoding.cn\/wp-content\/uploads\/2021\/01\/bbd3d5ad-3e83-46d0-abcb-5096ca481530.png\" alt=\"\"\/><\/figure>\n\n\n\n<ol><li>Once your&nbsp;GameplayTask_CreateParticles.h&nbsp;and&nbsp;.cpp&nbsp;pair are created, navigate to the&nbsp;.h&nbsp;file and update the class to the following:<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-preformatted\">#pragma once<br><br>#include \"CoreMinimal.h\"<br>#include \"GameplayTask.h\"<br><strong>#include \"Particles\/ParticleSystem.h\"<\/strong><br>#include \"GameplayTask_CreateParticles.generated.h\"<br><br>\/**<br> * <br> *\/<br>UCLASS()<br>class CHAPTER_11_API UGameplayTask_CreateParticles : public UGameplayTask<br>{<br>    GENERATED_BODY()<br>    <br><strong>public:<\/strong><br><strong>    virtual void Activate();<\/strong><br><br><strong>    \/\/ A static constructor for an instance of a <br>    \/\/ UGameplayTask_CreateEmitter instance,<\/strong><br><strong>    \/\/ including args of (what class of emitter, where to <br>    \/\/ create it).<\/strong><br><strong>    UFUNCTION(BlueprintCallable, Category = \"GameplayTasks\", meta = (AdvancedDisplay = \"TaskOwner\", DefaultToSelf = \"TaskOwner\", BlueprintInternalUseOnly = \"TRUE\"))<\/strong><br><strong>        static UGameplayTask_CreateParticles* ConstructTask(<\/strong><br><strong>            TScriptInterface&lt;IGameplayTaskOwnerInterface&gt; TaskOwner,<\/strong><br><strong>            UParticleSystem* particleSystem,<\/strong><br><strong>            FVector location);<\/strong><br><br><strong>    UParticleSystem* ParticleSystem;<\/strong><br><strong>    FVector Location;<\/strong><br><br>};<\/pre>\n\n\n\n<ol><li>Then, implement the&nbsp;GameplayTask_CreateParticles.cpp&nbsp;file, as follows:<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-preformatted\">#include \"GameplayTask_CreateParticles.h\"<br><strong>#include \"Kismet\/GameplayStatics.h\"<\/strong><br><br><strong>\/\/ Like a constructor.<\/strong><br><strong>UGameplayTask_CreateParticles* UGameplayTask_CreateParticles::ConstructTask(<\/strong><br><strong>    TScriptInterface&lt;IGameplayTaskOwnerInterface&gt; TaskOwner,<\/strong><br><strong>    UParticleSystem* particleSystem,<\/strong><br><strong>    FVector location)<\/strong><br><strong>{<\/strong><br><strong>    UGameplayTask_CreateParticles* task = <br>    NewTask&lt;UGameplayTask_CreateParticles&gt;(TaskOwner);<\/strong><br><strong>    \/\/ Fill fields<\/strong><br><strong>    if (task)<\/strong><br><strong>    {<\/strong><br><strong>        task-&gt;ParticleSystem = particleSystem;<\/strong><br><strong>        task-&gt;Location = location;<\/strong><br><strong>    }<\/strong><br><strong>    return task;<\/strong><br><strong>}<\/strong><br><br><strong>void UGameplayTask_CreateParticles::Activate()<\/strong><br><strong>{<\/strong><br><strong>    Super::Activate();<\/strong><br><br><strong>    UGameplayStatics::SpawnEmitterAtLocation(GetWorld(),<br>    ParticleSystem, Location);<\/strong><br><strong>}<\/strong><\/pre>\n\n\n\n<ol><li>Open up your&nbsp;Warrior.h&nbsp;file and add the following interface to the class definition:<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-preformatted\">UCLASS()<br>class CHAPTER_11_API AWarrior : public ACharacter, public IAbilitySystemInterface<strong>, public IGameplayTaskOwnerInterface<\/strong><br>{<br>    GENERATED_BODY()<\/pre>\n\n\n\n<ol><li>Afterwards, add the following new properties to it:<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-preformatted\">    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Stats)<br>    UGameplayTasksComponent* GameplayTasksComponent;<br><br>    \/\/ This is the particleSystem that we create with the<br>    \/\/ GameplayTask_CreateParticles object.<br>    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Stats)<br>    UParticleSystem* particleSystem;<\/pre>\n\n\n\n<ol><li>Below that, add the following function definitions for the&nbsp;GameplayTaskOwnerInterface:<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-preformatted\">    \/\/ &lt;GameplayTaskOwnerInterface&gt;<br><br>    virtual UGameplayTasksComponent* GetGameplayTasksComponent(const <br>    UGameplayTask&amp; Task) const { return GameplayTasksComponent; }<br><br>    \/\/ This gets called both when task starts and when task gets <br>    \/\/ resumed.<br>    \/\/ Check Task.GetStatus() if you want to differentiate.<br>    virtual void OnTaskActivated(UGameplayTask&amp; Task) { }<br>    virtual void OnTaskDeactivated(UGameplayTask&amp; Task) { }<br><br>    virtual AActor* GetOwnerActor(const UGameplayTask* Task) const {<br>        return Task-&gt;GetOwnerActor(); \/\/ This will give us the <br>    \/\/ accurate answer for the Task..<br>    }<br>    \/\/ &lt;\/End GameplayTaskOwnerInterface&gt;<\/pre>\n\n\n\n<ol><li>Afterwards, go to the&nbsp;Warrior.cpp&nbsp;file and update the class constructor to the following:<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-preformatted\">AWarrior::AWarrior()<br>{<br>    \/\/ Set this character to call Tick() every frame. You can <br>    \/\/ turn this off to improve performance if you don't need <br>    \/\/ it.<br>    PrimaryActorTick.bCanEverTick = true;<br>    AbilitySystemComponent = CreateDefaultSubobject&lt;UAbilitySystemComponent&gt;<br>    (\"UAbilitySystemComponent\");<br>    GameplayTasksComponent = CreateDefaultSubobject&lt;UGameplayTasksComponent&gt;<br>    (\"UGameplayTasksComponent\");<br>}<\/pre>\n\n\n\n<ol><li>Save your scripts, return to the Unreal Editor, and compile your code. Once compiled, open&nbsp;your&nbsp;Actor&nbsp;class derivative (MyWarrior) and then scroll down to the&nbsp;Stats&nbsp;section and set the&nbsp;Particle System&nbsp;property to something you&#8217;d like to see, for instance, the&nbsp;P_Fire&nbsp;option if you included the sample content when you created your project:<\/li><\/ol>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/blog.coolcoding.cn\/wp-content\/uploads\/2021\/01\/e2540cdb-18c9-4567-9772-0bff4c83ab28.png\" alt=\"\"\/><\/figure>\n\n\n\n<ol><li>Which is available in the&nbsp;Full Blueprint Editor&nbsp;in the&nbsp;Components&nbsp;drop-down of the&nbsp;Components&nbsp;tab in the Blueprint editor.&nbsp;Add&nbsp;GameplayTasksComponent&nbsp;to<\/li><li>Create and add an instance of your&nbsp;GameplayTask&nbsp;inside your&nbsp;Actor&nbsp;derivative (MyWarrior) instance using the following code:<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-preformatted\">    UGameplayTask_CreateParticles* task =<br>        UGameplayTask_CreateParticles::ConstructTask(this,<br>        particleSystem, FVector(200.f, 0.f, 200.f));<br>            <br><br>    if (GameplayTasksComponent &amp;&amp; task)<br>    {<br>        GameplayTasksComponent-&gt;AddTaskReadyForActivation(*task);<br>    }<\/pre>\n\n\n\n<p>This code runs anywhere in your&nbsp;Actor&nbsp;class derivative, any time after&nbsp;GameplayTasksComponent&nbsp;is initialized (any time after&nbsp;PostInitializeComponents()).<\/p>\n\n\n\n<ol><li>Compile your code. Set your level to use&nbsp;MyWarrior&nbsp;as the&nbsp;Default Pawn Type&nbsp;and when the game starts, you should notice that the particle plays:<\/li><\/ol>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/blog.coolcoding.cn\/wp-content\/uploads\/2021\/01\/d976d754-77a1-43dd-9906-1e21151058ec.png\" alt=\"\"\/><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">How it works&#8230;<\/h1>\n\n\n\n<p>GameplayTasks&nbsp;simply register with the&nbsp;GameplayTasksComponent&nbsp;situated inside an&nbsp;Actor&nbsp;class derivative of your choice. You can activate any number of&nbsp;GameplayTasks&nbsp;at any time during gameplay to trigger their effects.<\/p>\n\n\n\n<p>GameplayTasks&nbsp;can also kick off&nbsp;GameplayEffects&nbsp;to change attributes of&nbsp;AbilitySystemsComponents&nbsp;if you wish.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">There&#8217;s more&#8230;<\/h1>\n\n\n\n<p>You can derive&nbsp;GameplayTasks&nbsp;for any number of events in your game. What&#8217;s more is that you can override a few more virtual functions to hook into additional functionality.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>GameplayTasks\u00a0are used to wrap up some gameplay functio [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[27,1],"tags":[],"_links":{"self":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts\/3144"}],"collection":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3144"}],"version-history":[{"count":3,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts\/3144\/revisions"}],"predecessor-version":[{"id":3332,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts\/3144\/revisions\/3332"}],"wp:attachment":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3144"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3144"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3144"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}