Bevor du anfängst
Stellen Sie sicher, dass Sie die folgenden Ziele in den vorherigen Abschnitten von Ein erstes First-Person-Abenteuerspiel programmieren abgeschlossen haben:
C++-First-Person-Spieler-Charakter inEinen Spieler-Charakter mit Input-Actions erstellen erstellt.
Datenbasierte Gameplay-Elemente in Gegenstände und Daten verwalten eingerichtet, um Gegenstandsdaten zu verwalten.
Abholpunkt-Gegenstand in Erstellen Sie einen respawnenden Abholpunkt Gegenstand erstellt und Ihrem Level hinzugefügt.
Referenzelemente mit einer neuen CreateItemCopy-Funktion erstellen
Bevor Sie damit beginnen, einen neuen ausrüstbaren Abholpunkt-Gegenstand zu erstellen, müssen Sie zuerst Ihre ItemDefinition- und PickupBase-Klassen anpassen, damit die Aufnahme eines Referenzgegenstands aus einer größeren Auswahl an Gegenstandstypen unterstützt wird.
In der InitializePickup()-Funktion Ihrer PickupBase-Klasse legen Sie ein ReferenceItem des Typs UItemDefinition fest. Das ist zu einschränkend; Wenn Sie einen Referenzgegenstand auf diese Weise festlegen, werden die zusätzlichen Eigenschaften nicht eingeschlossen, die Sie zu jeder neuen, spezialisierten Gegenstandsklasse hinzufügen, die von UItemDefinition abgeleitet wird.
Um dieses Problem zu lösen, werden Sie eine neue virtuelle Funktion in ItemDefinition erstellen, die eine Kopie dieses Gegenstandes erstellt und zurückgibt. Da es eine virtuelle Funktion ist, können Sie sie in allen Klassen überschreiben, die von UItemDefinition erben. Wenn PickupBase die Funktion aufruft, bestimmt der Compiler die korrekte aufzurufende Funktion basierend auf der Klasse, aus der sie aufgerufen wurde.
Durch Hinzufügen dieser Funktion zur Parent-Klasse ItemDefinition wird sichergestellt, dass sie verfügbar ist, wenn Sie sich entscheiden, Ihr Projekt weiterhin zu erweitern, um mehr Gegenstandstypen einzuschließen, die von UItemDefinition erben.
Befolgen Sie diese Schritte, um eine neue CreateItemCopy()-Funktion zur Erstellung von Referenzgegenständen zu definieren:
Öffnen Sie
ItemDefinition.h. Deklarieren Sie impublic-Abschnitt eine neue virtuelle const-Funktion namensCreateItemCopy(), die einenUItemDefinition-Zeiger zurückgibt.C++// Creates and returns a copy of the item. virtual UItemDefinition* CreateItemCopy() const;Implementieren Sie in
ItemDefinition.cpp, die FunktionCreateItemCopy(). Erstellen Sie darin einen neuenUItemDefinition-Objektzeiger namensItemCopymit derStaticClass().C++UItemDefinition* UItemDefinition::CreateItemCopy() const { UItemDefinition* ItemCopy = NewObject<UItemDefinition>(StaticClass()); }Visual Studio stellt die Eindeutigkeit von
UItemDefinition::StaticClass()zuStaticClass()her.Weisen Sie jedes Feld von
ItemCopyden Feldern dieser Klasse zu und geben Sie dannItemCopyzurück:C++/** * Creates and returns a copy of this Item Definition. * @return a copy of the item. */ UItemDefinition* UItemDefinition::CreateItemCopy() const { UItemDefinition* ItemCopy = NewObject<UItemDefinition>(StaticClass()); ItemCopy->ID = this->ID; ItemCopy->ItemType = this->ItemType;
Gestalten Sie als Nächstes Ihre InitializePickup()-Funktion um, indem Sie den Code entfernen, der ReferenceItem manuell einrichtet, und diesen Code durch einen CreateItemCopy()-Aufruf ersetzen.
Befolgen Sie diese Schritte, um InitializePickup() mit Ihrer neuen CreateItemCopy()-Funktion zu aktualisieren:
Öffnen Sie
PickupBase.cppund gehen Sie zuInitializePickup().Löschen Sie diese fünf Zeilen, die
ReferenceItemdefinieren und festlegen:C++ReferenceItem = NewObject<UItemDefinition>(this, UItemDefinition::StaticClass()); ReferenceItem->ID = ItemDataRow->ID; ReferenceItem->ItemType = ItemDataRow->ItemType; ReferenceItem->ItemText = ItemDataRow->ItemText; ReferenceItem->WorldMesh = ItemDataRow->ItemBase->WorldMesh;In
ReferenceItemdurch Aufrufen vonTempoItemDefinition->CreateItemCopy():C++// Create a copy of the item with the class type ReferenceItem = TempItemDefinition->CreateItemCopy();
Speichern Sie PickupBase.cpp. Ihre Funktion InitializePickup() sollte jetzt wie folgt aussehen:
if (PickupDataTable && !PickupItemID.IsNone())
{
// Retrieve the item data associated with this pickup from the data table
const FItemData* ItemDataRow = PickupDataTable->FindRow<FItemData>(PickupItemID, PickupItemID.ToString());
UItemDefinition* TempItemDefinition = ItemDataRow->ItemBase.Get();
// Create a copy of the item with the class type
ReferenceItem = TempItemDefinition->CreateItemCopy();
}Daten für ausrüstbare Werkzeuge definieren
Im vorherigen Abschnitt haben Sie gelernt, wie Sie interaktive Abholpunkt-Objekte in Ihrem Level erstellen, die konkrete Repräsentationen von Tabellendaten sind. In diesem Abschnitt erfahren Sie, wie Sie Werkzeuge zum Ausrüsten für Ihren Charakter erstellen.
Um ein neues ausrüstbares Werkzeug einzurichten, erstellen Sie:
EquippableToolDefinition: Eine vonItemDefinitionabgeleitete Daten-Asset-Klasse, in der die Daten des Werkzeugs gespeichert werden.EquippableToolBase: Eine Actor-Klasse, die das Werkzeug in-game repräsentiert. Sie gibt Ihrem Charakter die Animationen, Input-Mappings und das Mesh, damit der Charakter das Werkzeug halten und bedienen kann.
Damit Ihr Charakter Werkzeuge aufheben und ausrüsten kann, fügen Sie hinzu:
Einen Ort zum Lagern von Gegenständen.
Eine Möglichkeit, den Typ jedes Gegenstands im Inventar zu erfahren.
Eine Möglichkeit, Werkzeuge auszurüsten.
Zur Erinnerung: Der EquippableToolBase-Actor repräsentiert das Werkzeug, das Ihr Charakter hält und verwendet, während der PickupBase-Actor den Abholpunkt-Gegenstand in Ihrem Level repräsentiert. Ihr Charakter muss mit dem Abholpunkt-Gegenstand kollidieren, bevor er ihn ausrüsten kann. Deshalb müssen Sie auch PickupBase anpassen, damit er den Gegenstand nach einer erfolgreichen Kollision erhält.
Dann kombinieren Sie Ihre neue Werkzeugklasse mit den Abholpunkten und der Datentabelle, die Sie bereits erstellt haben, um einen benutzerdefinierten Launcher zu erstellen und ihn an Ihren Charakter anzukoppeln!
Zuerst definieren Sie die Daten Ihres Werkzeugs in einer neuen ItemDefinition-Klasse.
Um eine neue EquippableToolDefinition-Klasse zu erstellen, befolgen Sie diese Schritte:
Gehen Sie im Unreal Editor zu Werkzeuge > Neue C++-Klasse. Gehen Sie zu Alle Klassen, suchen Sie nach ItemDefinition als Parent-Klasse und klicken auf Weiter.
Geben Sie der Klasse den Namen
EquippableToolDefinitionund klicken Sie auf Klasse erstellen.Fügen Sie in Visual Studio oben in der Datei
EquippableToolDefinition.hein include für„ItemDefinition.h“hinzu und fügen Sie dann die folgenden Vorwärts-Deklarationen ein:class UInputMappingContext: Jedes ausrüstbare Werkzeug sollte eine Referenz zu einem Input-Mapping-Kontext enthalten, den Sie auf den Charakter anwenden, der dieses Werkzeug führt.class AEquippableToolBase: Der Actor, der Ihre Werkzeuge in-game repräsentiert. Du wirst dies im nächsten Schritt erstellen.C++#pragma once #include "CoreMinimal.h" #include "ItemDefinition.h" #include "EquippableToolDefinition.generated.h" class AEquippableToolBase; class UInputMappingContext; UCLASS(BlueprintType, Blueprintable)
Fügen Sie im
public-Abschnitt eineTSubclassOf-Eigenschaft des TypsAEquippableToolBasenamensToolAssethinzu. Geben Sie diesem einUPROPERTY()-Makro mitEditDefaultsOnly.C++// The tool actor associated with this item UPROPERTY(EditDefaultsOnly) TSubclassOf<AEquippableToolBase> ToolAsset;TSubclassOf<AEquippableToolBase>ist ein Vorlagen-Wrapper umUClass, der es Ihnen ermöglicht, auf Blueprint-Unterklassen vonAEquippableToolBasezu referenzieren und dabei Typsicherheit zu gewährleisten. Das ist nützlich in Gameplay-Szenarien, in denen Sie verschiedene Actor-Typen dynamisch spawnen wollen.Sie verwenden
ToolAsset, um einen Werkzeug-Actor dynamisch zu spawnen, wenn Ihr Charakter damit ausgerüstet wird.Deklarieren Sie einen Override für die
CreateItemCopy()-Funktion, die Sie inUItemDefinitiondeklariert haben. Dieser Override erstellt und gibt eine Kopie derUEquippableToolDefinition-Klasse zurück.Ihre fertige Datei
EquippableToolDefinition.hsollte wie folgt aussehen:C++// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "ItemDefinition.h" #include "EquippableToolDefinition.generated.h" class AEquippableToolBase; class UInputMappingContext;Implementieren Sie in
EquippableToolDefinition.cppdie FunktionCreateItemCopy(). Das sollte ähnlich aussehen wie die FunktionCreateItemCopy()inItemDefinition.cpp, abgesehen davon, dass Sie jetzt auchToolAssetkopieren.C++// Copyright Epic Games, Inc. All Rights Reserved. #include "EquippableToolDefinition.h" UEquippableToolDefinition* UEquippableToolDefinition::CreateItemCopy() const { UEquippableToolDefinition* ItemCopy = NewObject<UEquippableToolDefinition>(StaticClass()); ItemCopy->ID = this->ID; ItemCopy->ItemType = this->ItemType;
Speichern Sie beide EquippableToolDefinition-Klassendateien.
Einen ausrüstbaren Werkzeug-Actor einrichten
Beginnen Sie als Nächstes mit der Erstellung Ihres ausrüstbaren Werkzeug-Actors. Dies ist die In-game-Darstellung, die dem Charakter die Animationen, Steuerelemente und das Mesh des Werkzeugs hinzufügt.
Um einen neuen ausrüstbaren Basis-Werkzeug-Actor zu erstellen und einzurichten, befolgen Sie diese Schritte:
Gehen Sie im Unreal Editor zu Werkzeuge > Neue C++-Klasse. Wählen Sie Actor als übergeordnete Klasse aus und benennen Sie die Klasse EquippableToolBase.
Klicken Sie auf Klasse erstellen. Die Unreal Engine öffnet die Dateien Ihrer neuen Klasse automatisch in VS.
Erstellen Sie oben in der Datei
EquippableToolBase.hVorwärtsdeklarationen der KlassenAAdventureCharacterundUInputAction. Das ausrüstbare Werkzeug muss wissen, für welchen Charakter es ausgerüstet ist, damit es werkzeugspezifische Input-Actions an diesen Charakter binden kann.Fügen Sie im
UCLASS-Makro der Klassendeklaration die BezeichnerBlueprintTypeundBlueprint-fähighinzu, um diese Klasse für Blueprints bereitzustellen.C++UCLASS(BlueprintType, Blueprintable) class ADVENTUREGAME_API AEquippableToolBase : public AActor
Werkzeug-Animationen deklarieren
Fügen Sie in EquippableToolBase.h im public-Abschnitt zwei TObjectPtr zu UAnimBlueprint-Eigenschaften namens FirstPersonToolAnim und ThirdPersonToolAnim hinzu. Dies sind die First-Person- und Third-Person-Animationen, die der Charakter verwendet, wenn er mit diesem Werkzeug ausgerüstet ist.
Geben Sie diesen Eigenschaften ein UPROPERTY()-Makro mit EditAnywhereund BlueprintReadOnly.
// First Person animations
UPROPERTY(EditAnywhere, BlueprintReadOnly)
TObjectPtr<UAnimBlueprint> FirstPersonToolAnim;
// Third Person animations
UPROPERTY(EditAnywhere, BlueprintReadOnly)
TObjectPtr<UAnimBlueprint> ThirdPersonToolAnim;Das Mesh des Werkzeugs erstellen
Fügen Sie in EquippableToolBase.h im public-Abschnitt einen TObjectPtr zu einer USkeletalMeshComponent namens ToolMeshComponent hinzu. Das ist das Skelett-Mesh des Werkzeugs, das der Charakter sieht, wenn es ausgerüstet ist. Geben Sie ihm ein UPROPERTY()-Makro mit EditAnywhere und BlueprintReadOnly.
// Tool Skeletal Mesh
UPROPERTY(EditAnywhere, BlueprintReadOnly)
TObjectPtr<USkeletalMeshComponent> ToolMeshComponent;Passen Sie in EquippableToolBase.cpp die Constructor-Funktion AEquippableToolBase() an, um eine standardmäßige USkeletalMeshComponent zu erstellen, und weisen Sie diese ToolMeshComponent zu. Prüfen Sie anschließend, ob die ToolMeshComponent nicht null ist, um sicherzustellen, dass Ihr Werkzeug ein Modell hat, wenn es geladen wird.
AEquippableToolBase::AEquippableToolBase()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
// Create this tool's mesh component
ToolMeshComponent = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("ToolMesh"));
check(ToolMeshComponent != nullptr);
}
Den Besitzer des Werkzeugs deklarieren
Erstellen Sie in EquippableToolBase.h im public-Abschnitt einen TObjectPtr zu einer Instanz Ihrer Charakter-Klasse namens OwningCharacter. Geben Sie ihm ein UPROPERTY()-Makro mit EditAnywhere und BlueprintReadOnly.
Dies ist der Charakter, für den dieses Werkzeug aktuell ausgerüstet ist.
// The character holding this tool
UPROPERTY(EditAnywhere, BlueprintReadOnly)
TObjectPtr<AAdventureCharacter> OwningCharacter;Deklarieren eines Inputs und einer Werkzeug-verwenden-Funktion
Ihr Werkzeug verfügt über einen Input-Mapping-Kontext und eine Input-Aktion, die es dem Charakter geben muss.
Um den Input-Mapping-Kontext hinzuzufügen, deklarieren Sie im öffentlichen Abschnitt einen TObjectPtr für einen UInputMappingContext mit dem Namen ToolMappingContext. Geben Sie ihm ein UPROPERTY()-Makro mit EditAnywhere und BlueprintReadOnly.
// The input mapping context associated with this tool
UPROPERTY(EditAnywhere, BlueprintReadOnly)
TObjectPtr<UInputMappingContext> ToolMappingContext;Ähnlich wie bei der Implementierung von Bewegungssteuerelementen fügen Sie eine Funktion hinzu, die eine Werkzeug-verwenden-Action implementiert, sowie eine neue Funktion, die eine Input-Action an die Funktion bindet.
Deklarieren Sie in EquippableToolBase.h im public-Abschnitt zwei virtuelle void-Funktionen namens Use() und BindInputAction().
Bei der Implementierung von Charakter-Bewegungssteuerelementen haben Sie die BindAction()-Funktion der Input-Komponente genutzt und müssen den genauen Namen der Zielfunktion angeben. Sie kennen noch nicht den vollständigen Name der Funktion, also benötigen Sie eine benutzerdefinierte BindInputAction()-Funktion, die Sie in jeder EquippableToolBase-Subklasse implementieren können, um BindAction aufzurufen und [ToolChildClass]::Use zu übergeben.
Die BindInputAction()-Funktion nimmt einen konstanten UInputAction-Zeiger und bindet die entsprechende Input-Action an die Use()-Funktion des Charakters.
// Use the tool
UFUNCTION()
virtual void Use();
// Binds the Use function to the owning character
UFUNCTION()
virtual void BindInputAction(const UInputAction* ActionToBind);Iimplementieren Sie in EquippableToolBase.cpp die Funktionen Use() und BindInputAction(). Diese tun in der Parent-Klasse nichts, also können Sie sie vorerst leer lassen. Sie fügen diesen eine Logik hinzu, wenn Sie EquippableToolBase-Subklassen erstellen. Zum Beispiel sollte die Use()-Funktion werkzeugspezifische Actions wie das Abfeuern eines Projektils oder das Öffnen einer Tür umfassen.
void AEquippableToolBase::Use()
{
}
void AEquippableToolBase::BindInputAction(const UInputAction* ActionToBind)
{
}
Speichern Sie Ihren Code und kompilieren Sie ihn in VS.
Ihre EquippableToolBase.h-Datei sollte jetzt wie folgt aussehen:
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "EquippableToolBase.generated.h"
class AAdventureCharacter;
class UInputAction;
EquippableToolBase.cpp sollte nun wie folgt aussehen:
// Copyright Epic Games, Inc. All Rights Reserved.
#include "EquippableToolBase.h"
#include "AdventureCharacter.h"
AEquippableToolBase::AEquippableToolBase()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
Charakteren Gegenstände gewähren
Sie haben Werkzeuge definiert, die Ihr Charakter verwenden kann, aber er kann sie noch nicht ausrüsten. Als Nächstes fügen Sie ein Inventarsystem hinzu, damit der Charakter Gegenstände lagern und ausrüsten kann, wenn er sie aufhebt.
Eine Inventarkomponente erstellen
Das Inventar Ihres Charakters sollte dem Charakter Funktionalität hinzufügen, aber nicht in der Spielwelt existieren. Deshalb verwenden Sie eine Actor-Komponenten-Klasse, um ein Inventar zu definieren, das weiß, welche Gegenstände ein Charakter hat, Werkzeuge tauschen kann und verhindert, dass der Charakter mehr als ein Werkzeug desselben Typs erhält.
Gehen Sie im Unreal Editor zu Werkzeuge > Neue C++-Klasse. Wählen Sie Actor-Komponente als Parent-Klasse aus und nennen Sie die Klasse InventoryComponent.
Klicken Sie auf Klasse erstellen.
Vorwärtsdeklarieren Sie in VS Sie oben in der Datei InventoryComponent.h eine UEquippableToolDefinition. Das ist die Klasse, die Sie in Ihrem Inventar speichern.
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "InventoryComponent.generated.h"
class UEquippableToolDefinition;
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class ADVENTUREGAME_API UInventoryComponent : public UActorComponent
{
GENERATED_BODY()
Deklarieren Sie im public-Abschnitt ein neues TArray von UEquippableToolDefinition-Zeigern namens ToolInventory.. Geben Sie ihm das UPROPERTY()-Makro mit VisibleAnywhere, BlueprintReadOnly und Category = Tools.
public:
// Sets default values for this component's properties
UInventoryComponent();
// The array of tools stored in this inventory.
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Tools)
TArray<UEquippableToolDefinition*> ToolInventory;In diesem Inventar werden nur Werkzeuge abgelegt, aber Sie können es um beliebige Gegenstandstypen erweitern. Eine generischere Implementierung würde nur UItemDefinition- oder TSubclassOf<UItemDefinition>-Werte speichern, um ein komplexeres Inventar mit Benutzeroberfläche, Symbolen, Soundeffekten, Kosten und anderen Gegenstandseigenschaften zusammenzustellen.
Ihre fertige InventarComponent.h-Datei sollte nun so aussehen:
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "InventoryComponent.generated.h"
class UEquippableToolDefinition;
Werkzeug- und Inventardeklarationen zum Charakter hinzufügen
Nun, da Sie einen Ort zum Aufbewahren Ihrer Gegenstände haben, sind Sie bereit, Ihren Charakter mit Logik zu erweitern, die ihm Gegenstände gewährt.
Vorwärtsdeklarieren Sie zunächst in der .h-Datei Ihres Charakters die Klassen AEquippableToolBase, UEquippableToolDefinition und UInventoryComponent.
#include "CoreMinimal.h"
#include "Camera/CameraComponent.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "GameFramework/Character.h"
#include "InputActionValue.h"
#include "AdventureCharacter.generated.h"
class AEquippableToolBase;
class UAnimBlueprint;
Implementieren Sie im protected-Abschnitt einen TObjectPtr zu einer UInputAction namens UseAction. Das ist die „Werkzeug-verwenden“-Input-Action, die Sie an die Use()-Funktion des Werkzeugs binden.
// Use Input Actions
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input)
TObjectPtr<UInputAction> UseAction;Die Inventarkomponente des Charakters erstellen
Deklarieren Sie in der .h-Datei des Charakters im public-Abschnitt einen TObjectPtr zu einer UInventoryComponent namens InventoryComponent. Geben Sie ihm ein UPROPERTY()-Makro mit VisibleAnywhere und Category = Inventory.
// Inventory Component
UPROPERTY(VisibleAnywhere, Category = Inventory)
TObjectPtr<UInventoryComponent> InventoryComponent;Erstellen Sie in der Constructor-Funktion Ihres Charakters nach dem Erstellen des Mesh- Komponente-Teilobjekts ein Standard-UInventoryComponent-Teilobjekt namens InventoryComponent. Dies stellt sicher, dass Ihr Inventar richtig eingerichtet ist, wenn der Charakter spawnt.
// Create an inventory component for the owning player
InventoryComponent = CreateDefaultSubobject<UInventoryComponent>(TEXT("InventoryComponent"));Vorhandenes Inventar prüfen
Bevor Sie das Werkzeug ankoppeln, prüfen Sie, ob der Spieler das Werkzeug bereits hat, damit Sie es nicht mehrfach ausrüsten.
Deklarieren Sie in der .h-Datei des Charakters im public-Abschnitt eine Funktion namens IsToolAlreadyOwned(), die einen UEquippableToolDefinition-Zeiger entgegennimmt und “True zurückgibt, wenn das Werkzeug bereits im Inventar des Spielers existiert.
// Returns whether or not the player already owns this tool
UFUNCTION()
bool IsToolAlreadyOwned(UEquippableToolDefinition* ToolDefinition);Implementieren Sie in der .cpp-Datei Ihres Charakters, AdventureCharacter.cpp, die Funktion IsToolAlreadyOwned(). Rufen Sie darin in einer for-Schleife jedes Werkzeug im Inventar des Charakters ab, indem Sie auf das Array InventoryComponent->ToolInventory zugreifen.
bool AAdventureCharacter::IsToolAlreadyOwned(UEquippableToolDefinition* ToolDefinition)
{
// Check that the character does not yet have this particular tool
for (UEquippableToolDefinition* InventoryItem : InventoryComponent->ToolInventory)
{
}
}
Prüfen Sie dann in einer if-Anweisung, ob die ToolDefinition->ID des an diese Funktion übergebenen Werkzeugs mit der InventoryItem->ID übereinstimmt. Wenn ja, geben Sie mit “return true True zurück, da der Charakter dieses Werkzeug bereits besitzt. Geben Sie andernfalls nach der for--Schleife mit return false False zurück, weil ToolDefinition mit keinem der bestehenden Inventargegenstände übereinstimmte und daher ein neuer Gegenstand ist.
bool AAdventureCharacter::IsToolAlreadyOwned(UEquippableToolDefinition* ToolDefinition)
{
// Check that the character does not yet have this particular tool
for (UEquippableToolDefinition* InventoryItem : InventoryComponent->ToolInventory)
{
if (ToolDefinition->ID == InventoryItem->ID)
{
return true;
}
}
Ein Werkzeug ankoppeln
Deklarieren Sie in der .h-Datei Ihres Charakters im public-Abschnitt eine Funktion namens AttachTool(), die einen UEquippableToolDefinition-Zeiger entgegennimmt. Diese Funktion versucht, das Werkzeug innerhalb der ToolDefinition für den Spieler auszurüsten.
// Attaches and equips a tool to the player
UFUNCTION()
void AttachTool(UEquippableToolDefinition* ToolDefinition);Deklarieren Sie im protected-Abschnitt einen TObjectPtr zu einem AEquippableToolBase namens EquippedTool. Geben Sie ihm die Bezeichner VisibleAnywhere, BlueprintReadOnly und Category = Tools UPROPERTY().
// The currently-equipped tool
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Tools)
TObjectPtr<AEquippableToolBase> EquippedTool;Implementieren Sie in der .cpp-Datei Ihres Charakters AttachTool()-Datei. Prüfen Sie zuerst in einer if-Anweisung, ob der Charakter das Werkzeug bereits hat, indem Sie IsToolAlreadyOwned() aufrufen.
void AAdventureCharacter::AttachTool(UEquippableToolDefinition* ToolDefinition)
{
// Only equip this tool if it isn't already owned
if (not IsToolAlreadyOwned(ToolDefinition))
{
}
}
Einen Gegenstand spawnen
Das AEquippableToolBase-Werkzeug, gespeichert in ToolDefinition, ist ein Actor, also wird es möglicherweise nicht geladen, wenn AttachTool() aufgerufen wird. Um das zu tun, spawnen Sie mithilfe der Funktion SpawnActor() eine neue Instanz des Werkzeugs.
SpawnActor() ist Teil des UWorld-Objekts, welches das Kernobjekt ist, das die Karte und die darin enthaltenen Actors repräsentiert. Greifen Sie darauf zu, indem Sie die Funktion GetWorld() von einem beliebigen Actor aus aufrufen.
Deklarieren Sie in der if-Anweisung einen neuen AEquippableToolBase-Zeiger namens ToolToEquip. Setzen Sie dies auf das Ergebnis des Aufrufs von GetWorld()->SpawnActor(), wobei das ToolDefinition->ToolAsset als der zu spawnende Actor undthis->GetActorTransform() als Spawn-Position übergeben wird.
// Only equip this tool if it isn't already owned
if (not IsToolAlreadyOwned(ToolDefinition))
{
// Spawn a new instance of the tool to equip
AEquippableToolBase* ToolToEquip = GetWorld()->SpawnActor<AEquippableToolBase>(ToolDefinition->ToolAsset, this->GetActorTransform());
}Wenn Sie ToolDefinition->ToolAsset an SpawnActor übergeben, kann die UE nach dem Klassentyp von ToolAsset suchen und diesen Actor-Typ spawnen. (ToolAsset ist der EquippableToolBase-Actor, der mit dieser ToolDefinition assoziiert ist.)
Einen Gegenstand an den Charakter ankoppeln
Um das gespawnte Werkzeug an Ihren Charakter anzukoppeln, müssen Sie ein neues FAttachementTransformRules namens AttachementRules deklarieren.
FAttachementTransformRules ist eine Struktur, die definiert, wie Ort, Drehung und Skalierung beim Ankoppeln gehandhabt werden. Es braucht EAttachmentRules und eine Boolesche Variable InWeldSimulatedBodies am Ende, um der UE zu sagen, ob Physik beteiligt ist. Bei True verschweißt UE beide Körper miteinander, sodass sie bei Bewegung als einer interagieren können. Einige gängige Ankopplungsregeln sind KeepRelative (relative Transformation des Parents beibehalten), KeepWorld (Welt-Transformation beibehalten) und SnapToTarget (an der Parent-Transformation andocken).
Fügen Sie in Ihrer AttachmentRoles-Definition EAttachmentRule::SnapToTarget und true hinzu.
// Attach the tool to the First Person Character
FAttachmentTransformRules AttachmentRules(EAttachmentRule::SnapToTarget, true);Rufen Sie dann ToolToEquip->AttachToActor() auf, um das Werkzeug an den Charakter anzukoppeln, gefolgt von ToolToEquip->AttachToComponent(), um das Werkzeug an den Rechte-Hand-Socket der First-Person-Mesh-Komponente anzukoppeln.
AttachToActor koppelt einen Actor an einen Ziel-Parent-Actor und AttachToComponent koppelt die Stammkomponente des Actor an die Zielkomponente. Sie haben die folgende Syntax:
MyActor->AttachToActor(ParentActor, AttachmentRules, OptionalSocketName)
// Attach the tool to this character, and then the right hand of their first-person mesh
ToolToEquip->AttachToActor(this, AttachmentRules);
ToolToEquip->AttachToComponent(FirstPersonMeshComponent, AttachmentRules, FName(TEXT("HandGrip_R")));Animationen des Gegenstands zum Charakter hinzufügen
Legen Sie die Animationen für die First- und Third-Person-Meshs mit SetAnimInstanceClass() fest und übergeben Sie die First-Person- und Third-Person-Animationen des Werkzeugs.
// Set the animations on the character's meshes.
FirstPersonMeshComponent->SetAnimInstanceClass(ToolToEquip->FirstPersonToolAnim->GeneratedClass);
GetMesh()->SetAnimInstanceClass(ToolToEquip->ThirdPersonToolAnim->GeneratedClass);SetAnimInstanceClass ändert den Animations-Blueprint für ein Skelett-Mesh dynamisch zur Laufzeit und wird häufig verwendet, wenn Gegenstände und Waffen mit unterschiedlichen Animationssets ausgestattet werden. GeneratedClass ruft die tatsächliche AnimInstance-Klasse ab, die aus dem Blueprint generiert wurde.
Gegenstand zum Inventar hinzufügen
Fügen Sie das Werkzeug mithilfe von ToolInventory.Add() dem Inventar des Charakters hinzu
// Add the tool to this character's inventory
InventoryComponent->ToolInventory.Add(ToolDefinition);
Das Werkzeug ist jetzt angekoppelt; setzen Sie nun ToolToEquip->OwningCharacter auf diesen Charakter.
ToolToEquip->OwningCharacter = this;Sie haben das neue Werkzeug vollständig an den Charakter gekoppelt. Setzen Sie nun EquippedTool auf ToolToEquip
EquippedTool = ToolToEquip;Steuerelemente eines Gegenstands dem Charakter hinzufügen
Fügen Sie als Nächstes die Input-Action und den Input-Mapping-Kontext des Werkzeugs dem Charakter hinzu.
Sie werden dies ähnlich dazu einrichten, wie Sie AAdventureCharacter::BeginPlay() im Abschnitt Bind the Input Mapping to the Character von Charakterbewegung konfigurieren eingerichtet haben: Abrufen des PlayerController, dann des erweiterten lokalen Input-Subsystems, während Sie mit if-Anweisungen auf Null-Zeiger prüfen.
// Get the player controller for this character
if (APlayerController* PlayerController = Cast<APlayerController>(Controller))
{
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
{
Subsystem->AddMappingContext(ToolToEquip->ToolMappingContext, 1);
}
}
Wenn Sie dieses Mal den Input-Mapping-Kontext des Werkzeugs zum Spieler-Subsystem hinzufügen, setzen Sie die Priorität auf 1. Die Priorität des Haupt-Mapping-Kontexts des Spielers (FirstPersonContext) ist niedriger (0). Wenn beide Mapping-Kontexte dieselbe Tastenbindung haben, hat die Input-Bindung in ToolToEquip->ToolMappingContext Priorität über FirstPersonContext.
Nachdem Sie den Mapping-Kontext hinzugefügt haben, rufen Sie ToolToEquip->BindInputAction() auf und übergeben Sie die UseAction, um die Input-Action des Charakters an die Use()-Funktion des Werkzeugs zu binden.
// Get the player controller for this character
if (APlayerController* PlayerController = Cast<APlayerController>(Controller))
{
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
{
Subsystem->AddMappingContext(ToolToEquip->ToolMappingContext, 1);
}
ToolToEquip->BindInputAction(UseAction);
}
Ihre fertige Funktion AttachTool() sollte wie folgt aussehen:
void AAdventureCharacter::AttachTool(UEquippableToolDefinition* ToolDefinition)
{
// Only equip this tool if it isn't already owned
if (not IsToolAlreadyOwned(ToolDefinition))
{
// Spawn a new instance of the tool to equip
AEquippableToolBase* ToolToEquip = GetWorld()->SpawnActor<AEquippableToolBase>(ToolDefinition->ToolAsset, this->GetActorTransform());
// Attach the tool to the First Person Character
Verschiedene Gegenstandstypen mit GiveItem() unterstützen
Es gibt eine Möglichkeit, Werkzeuge anzukoppeln, aber da Abholpunkte und ihre Item-Definitionen mehr als nur Werkzeuge enthalten können, benötigen Sie eine Möglichkeit, zu wissen, mit welcher Art von Gegenstand Ihr Charakter interagiert, bevor Sie AttachTool() aufrufen.
Erstellen Sie eine GiveItem()-Funktion, um verschiedene Aktionen basierend auf dem übergebenen ItemDefinition-Typ auszuführen. Sie haben verschiedene Gegenstandstypen mit der EItemType Enum in ItemData.h deklariert und können diese Daten nun nutzen, um zwischen verschiedenen Item-Definitionen zu unterscheiden.
Deklarieren Sie in AdventureCharacter.h im public-Abschnitt eine Funktion namens GiveItem(), die einen UItemDefinition()-Zeiger entgegennimmt. Andere Klassen rufen diese Funktion auf, wenn Sie versuchen, dem Spieler einen Gegenstand zu geben.
// Public function that other classes can call to attempt to give an item to the player
UFUNCTION()
void GiveItem(UItemDefinition* ItemDefinition);Implementieren Sie in AdventureCharacter.cpp die Funktion GiveItem(). Beginnen Sie damit, eine Switch-Anweisung zu bestimmen, die Case-Fälle auf der Grundlage des ItemTypes des an diese Funktion übergebenen Gegenstands verwendet.
void AAdventureCharacter::GiveItem(UItemDefinition* ItemDefinition)
{
// Case based on the type of the item
switch (ItemDefinition->ItemType)
{
}
}
Deklarieren Sie in der Switch-Anweisung Case-Fälle für EItemType::Tool, EItemType::Consumable sowie einen Default-Case. In diesem Tutorial implementieren Sie nur den Werkzeug-Gegenstand. Protokollieren Sie also in den Fällen Consumable und default den Typ des Gegenstands und verlassen Sie die Switch-Case-Struktur.
// Case based on the type of the item
switch (ItemDefinition->ItemType)
{
case EItemType::Tool:
{
}
case EItemType::Consumable:
{
// Not yet implemented
break;
Casten Sie innerhalb des Tool-Falls die die ItemDefinition zu einem UEquippableToolDefinition-Zeiger namens ToolDefinition.
Stellen Sie anschließend sicher, dass der Cast erfolgreich war, indem Sie prüfen, ob ToolDefinition null ist. Wenn es nicht null ist, rufen Sie AttachTool() auf, um das Werkzeug an den Charakter anzukoppeln. Geben Sie andernfalls mit print den Fehler aus und verlassen Sie die Switch-Struktur mit break.
case EItemType::Tool:
{
// If the item is a tool, attempt to cast and attach it to the character
UEquippableToolDefinition* ToolDefinition = Cast<UEquippableToolDefinition>(ItemDefinition);
if (ToolDefinition != nullptr)
{
AttachTool(ToolDefinition);
}
Ihre fertige Funktion GiveItem() sollte wie folgt aussehen:
void AAdventureCharacter::GiveItem(UItemDefinition* ItemDefinition)
{
// Case based on the type of the item
switch (ItemDefinition->ItemType)
{
case EItemType::Tool:
{
// If the item is a tool, attempt to cast and attach it to the character
Zu guter Letzt brauchen Sie einen In-game-Trigger, um Ihre Gegenstandsgeber-Logik in Bewegung zu setzen. Wenn ein Charakter mit einem Abholpunkt kollidiert, sollte der Abholpunkt die GiveItem()-Funktion des Charakters aufrufen, um dem Charakter das ReferenceItem des Abholpunkts zu gewähren.
Öffnen Sie dazu PickupBase.cpp.
Rufen Sie in OnSphereBeginOverlap() nach der Prüfung, ob der Charakter gültig ist,Character->GiveItem(ReferenceItem) auf, um den Gegenstand Ihrem Charakter zu gewähren.
// Checking if it is a First Person Character overlapping
AAdventureCharacter* Character = Cast<AAdventureCharacter>(OtherActor);
if (Character != nullptr)
{
// Give the item to the character
Character->GiveItem(ReferenceItem);
// Unregister from the Overlap Event so it is no longer triggered
SphereComponent->OnComponentBeginOverlap.RemoveAll(this);
Nun, da Sie Ihre Werkzeugdaten und den Actor eingerichtet haben, können Sie damit ein echtes Werkzeug erstellen, das Ihr Charakter in-game ausrüsten kann!
Einen Dart-Launcher implementieren
Als Ihr erstes ausrüstbares Werkzeug erstellen Sie einen Launcher, mit dem Projektile abgeschossen werden können. In diesem Abschnitt erstellen Sie zunächst das Werkzeug, das Ihr Charakter halten und benutzen kann. Im nächsten Abschnitt dieses Tutorials implementieren Sie Projektil-Logik.
Neue DartLauncher-Klasse einrichten
Gehen Sie im Unreal Editor zu Werkzeuge > Neue C++-Klasse.
Gehen Sie zu Alle Klassen, suchen Sie nach EquippableToolBase und wählen Sie diese als Parent-Klasse aus. Nennen Sie die Klasse DartLauncher. Erstellen Sie einen neuen Ordner namens Werkzeuge, um den Code für Ihre Werkzeuge zu speichern. Klicken Sie auf Klasse erstellen.
In Visual Studio oben in der Datei DartLauncher.h:
Fügen Sie eine include-Anweisung für
„[Projektname]/EquippableToolBase.h“hinzu.Fügen Sie die Bezeichner
BlueprintTypeundBlueprint-fähigdemUCLASS()-Makro hinzu.Deklarieren Sie im
public-Abschnitt Overrides für die FunktionenUse()undBindInputAction()ausAEquippableToolBase.
Ihre fertige DartLauncher.h- Klasse sollte wie folgt aussehen:
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "AdventureGame/EquippableToolBase.h"
#include "DartLauncher.generated.h"
UCLASS(BlueprintType, Blueprintable)
class ADVENTUREGAME_API ADartLauncher : public AEquippableToolBase
Fügen Sie in DartLauncher.cpp, oben in der Datei eine include-Anweisung für „[Projektname]/AdventureCharacter.h“ hinzu. Sie benötigen diese in der Funktion BindInputAction().
#include "DartLauncher.h"
#include "AdventureGame/AdventureCharacter.h"Werkzeug-Steuerelemente implementieren
Da Sie nun mit einem bestimmten Werkzeug arbeiten und wissen, welche Funktion Sie binden, können Sie BindInputAction() implementieren.
Implementieren Sie zuerst die Use()-Funktion. Fügen Sie in Use() eine Debug-Nachricht hinzu, die meldet, wenn der Spieler die Funktion auslöst.
#include "DartLauncher.h"
#include "AdventureGame/AdventureCharacter.h"
void ADartLauncher::Use()
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("Using the dart launcher!"));
}
Implementieren Sie als Nächstes die Funktion BindInputAction(). Rufen Sie innerhalb der Funktion, in einer if-Anweisung den Player-Controller für den OwningCharacter ab, indem Sie GetController() verwenden, und casten Sie ihn dann zu APlayerController. Das ähnelt dem Hinzufügen eines Mapping-Kontexts in der Funktion AAdventureCharacter::BeginPlay().
void ADartLauncher::BindInputAction(const UInputAction* InputToBind)
{
// Set up action bindings
if (APlayerController* PlayerController = Cast<APlayerController>(OwningCharacter->GetController()))
{
}
}
Genau wie Sie Ihre Bewegungs-Actions im Abschnitt Bindung von Bewegungs-Actions unter Charakterbewegung konfigurieren gebunden haben: Deklarieren Sie in einer anderen if-Anweisung einen neuen UEnhancedInputComponent-Zeiger namens EnhancedInputComponent. Setzen Sie dies auf das Ergebnis des Aufrufs von Cast() für die PlayerInputComponent, die an diese Funktion übergeben wurde, während sie zu UEnhancedInputComponent gecastet wird.
Nutzen Sie abschließend BindAction, um die ADartLauncher::Use-Action an die InputToBind-Action zu binden, die an diese Funktion übergeben wurde, und verwenden Sie BindAction(). Dies bindet die InputAction an Use();, sodass Use() aufgerufen wird, wenn die entsprechende Action stattfindet.
// Set up action bindings
if (APlayerController* PlayerController = Cast<APlayerController>(OwningCharacter->GetController()))
{
if (UEnhancedInputComponent* EnhancedInputComponent = Cast<UEnhancedInputComponent>(PlayerController->InputComponent))
{
// Fire
EnhancedInputComponent->BindAction(InputToBind, ETriggerEvent::Triggered, this, &ADartLauncher::Use);
}
}
Beim Einrichten der Bewegung Ihres Charakters haben Sie CastChecked<> verwendet, was das Spiel zum Absturz bringt, wenn die Ausführung fehlschlägt. Hier wollen Sie das Spiel nicht stoppen, wenn die Abholpunkt-Steuerelemente nicht korrekt initialisiert werden, also verwenden Sie einfach Cast<>. Verwenden Sie CastChecked<> nur, wenn ein fehlgeschlagener Cast auf einen schwerwiegenden Bug hindeutet.
Speichern Sie Ihren Code und kompilieren Sie ihn.
Ihre BindInputAction()-Funktion und Ihre fertige DartLauncher.cpp-Klasse sollten nun so aussehen:
// Copyright Epic Games, Inc. All Rights Reserved.
#include "DartLauncher.h"
#include "AdventureGame/AdventureCharacter.h"
void ADartLauncher::Use()
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("Using the dart launcher!"));
}
Einen Animations-Blueprint für Ihren Charakter anpassen
Die First-Person-Vorlage enthält einen Beispiel-Animations-Blueprint für waffenartige Gegenstände, aber Sie müssen noch ein paar Änderungen am Blueprint vornehmen, damit er mit Ihrem Dart-Launcher funktioniert.
Um einen bestehenden Animations-Blueprint für Ihren Charakter anzupassen, führen Sie folgende Schritte aus:
Gehen Sie im Inhaltsbrowser zum Ordner Inhalt > Variant_Shooter > Anim, rechtsklicken Sie auf den Animations-Blueprint
ABP_FP_Pistolund wählen Sie Duplizieren.Nennen Sie diese Kopie ABP_FP_DartLauncher, ziehen Sie sie in den Ordner Inhalt > FirstPerson > Anims und wählen Sie Hierher verschieben.
ABP_TP_Pistolverwendet keine spezifische Logik für denBP_FPShooter-Charakter; Sie müssen ihn nicht für Ihren Charakter modifizieren.Zoomen Sie oben im Event-Diagramm in die Gruppe der Knoten, die mit dem Knoten Event Blueprint Begin Play beginnt.
Dieser Blueprint ruft die First-Person-Mesh- und First-Person-Kamera-Variablen von
BP_FPShooterab. Sie müssen das also ändern, um stattdessen Ihren Charakter-Blueprint zu verwenden (dieses Tutorial verwendetBP_AdventureCharacter).Klicken Sie auf jeden dieser Knoten und drücken Sie Entfernen:
Casten zu BP_FPShooter
Ego-Person-Mesh
First-Person-Kamera
Klicken Sie mit der rechten Maustaste auf das Event-Diagramm und suchen und wählen Sie dann einen Casten zu BP_AdventureCharacter-Knoten aus.
Verbinden Sie die Ausführungs-Pins von Event Blueprint Begin Play mit dem neuen Knoten und dann mit dem Knoten First-Person-Mesh-Knoten festlegen.
Verbinden Sie den Ergebniswert-Pin des Knotens Versuche, Pawn-Besitzer abzurufen mit dem Pin Casten zu Objekt des Knotens.
Um einen neuen Knoten aus Casten zu BP_AdventureCharacter anzulegen, klicken Sie auf den Pin Als BP Mein Abenteuer-Charakter und ziehen Sie ihn auf eine leere Stelle im Diagramm.
Suchen Sie nach Mesh abrufen und wählen Sie es unter Variablen > Charakter aus. Verbinden Sie den Mesh-Pin des neuen Knotens mit dem Knoten First-Person-Mesh-Knoten festlegen.
Ziehen Sie für die Kamera einen weiteren Knoten vom Pin Ala BP Mein First-Person-Charakter und suchen und wählen Sie Komponente nach Klasse abrufen.
Stellen Sie sicher, dass Sie einen Komponente nach Klasse abrufen-Knoten erstellen, dessen „nach“ in Kleinbuchstaben geschrieben ist.
Setzen Sie auf dem neuen Knoten die Komponentenklasse auf Kamera-omponente. Verbinden Sie dann den Ergebniswert-Pin mit dem First-Person-Kamera festlegen-Knoten.
Speichern Sie Ihren ABP_FP_DartLauncher-Blueprint und kompilieren Sie ihn.
Dart-Launcher-Steuerelemente definieren
Ihr Dart-Launcher benötigt eine Input-Action und einen Input-Mapping-Kontext, damit der Charakter Projektile mit dem Werkzeug abschießen kann.
Befolgen Sie diese Schritte, um Spieler-Steuerelemente für Ihr Dart-Launcher-Werkzeug zu erstellen:
Gehen Sie im Inhaltsbrowser zum Ordner Input > Actions.
Erstellen Sie eine „Werkzeug verwenden“-Input-Action und richten Sie sie ein:
Klicken Sie auf Hinzufügen, gehen Sie zu Input und wählen Sie Input-Action. Geben Sie ihr den Namen IA_UseTool.
Doppelklicken Sie auf IA_UseTool, um sie zu öffnen. Achten Sie im Details-Panel darauf, dass Werttyp Digital (Boolesche Variable) ist.
Klicken Sie neben Trigger auf das Pluszeichen (+) und wählen Sie Gedrückt aus der Liste der Trigger aus.
Speichern und schließen Sie die Input-Action.
Zurück im Inhaltsbrowser gehen Sie in den Input-Ordner.
Erstellen Sie einen neuen Input-Mapping-Kontext, der die linke Maustaste und den rechten Gamepad-Trigger der Verwenden-Action des Dart-Launchers zuordnet:
Erstellen Sie einen neuen Input-Mapping-Kontext namens IMC_DartLauncher.
Öffnen Sie IMC_DartLauncher. Klicken Sie auf die Plus-Schaltfläche neben Mappings.
Wählen Sie in der Dropdown-Liste-Liste den Eintrag
IA_UseToolaus.Klicken Sie auf den Pfeil, um das Mapping zu erweitern. Klicken Sie auf die Taste und drücken Sie dann die linke Maustaste, um diese Taste an
IA_UseToolzu binden.Klicken Sie neben IA_UseTool auf die Plus-Schaltfläche, um eine weitere Bindung hinzuzufügen. Erweitern Sie in der Dropdown-Liste den Eintrag Gamepad und wählen Sie Gamepad Rechte Trigger-Achse.
Speichern und schließen Sie den Input-Mapping-Kontext.
DartLauncher-Blueprint erstellen
Zurück im Haupt-Editor gehen Sie im Asset-Baum des Inhaltsbrowsers zu Ihrem C++-Klassen-Ordner, rechtsklicken Sie auf Ihre DartLauncher-Klasse und erstellen Sie eine neue Blueprint-Klasse.
Nennen Sie sie BP_DartLauncher. Gehen Sie in den Ordner FirstPerson > Blueprints und erstellen Sie einen neuen Ordner namens Werkzeuge, um Ihre ausrüstbaren Gegenstände zu speichern. Schließen Sie dann die Erstellung des Blueprints ab.
Legen Sie im Details-Panel des Blueprints die folgenden Standardeigenschaften fest:
Setzen Sie First Person Tool Anim auf
ABP_FP_DartLauncher.Setzen Sie Third Person Tool Anim auf
ABP_TP_Pistol.Setzen Sie Tool-Mapping-Kontext auf
IMC_DartLauncher.
Wählen Sie im Tab Komponenten die Werkzeug-Mesh-Komponente und setzen Sie das Skelett-Mesh-Asset auf SKM_Pistol.
Dart-Launcher-Daten-Asset erstellen
Um ein Daten-Asset zu erstellen, welches die Daten dieses Blueprints speichert, befolgen Sie diese Schritte:
Erstellen Sie im Inhaltsbrowser im Ordner FirstPerson > Daten ein neues Daten-Asset und wählen Sie Ausrüstbares Werkzeug Definition als Daten-Asset-Instanz. Nennen Sie dieses Asset
DA_DartLauncher.Legen Sie in
DA_DartLauncherim Details-Panel die folgenden Eigenschaften fest:Setzen Sie Werkzeug-Asset auf
BP_DartLauncher.Setzen Sie ID auf tool_001.
Setzen Sie Gegenstandstyp auf Werkzeug.
Setzen Sie Welt-Mesh auf
SM_Pistol.
Geben Sie einen Namen und eine Beschreibung ein.
Speichern Sie Ihr Daten-Asset.
Datentabelle für Werkzeuge erstellen
Dieses Werkzeug könnte zwar in Ihrer DT_PickupData-Tabelle landen, aber es ist hilfreich, Ihre Tabellen zu organisieren, um bestimmte Dinge zu verfolgen. Beispielsweise könnten Sie verschiedene Tabellen für Gegenstände einrichten, die bestimmte Klassen ausrüsten können, oder Tabellen mit Gegenständen, die verschiedene Feinde fallen lassen, wenn sie besiegt werden. In diesem Tutorial haben Sie eine Tabelle für Verbrauchsgegenstände und eine Tabelle für Werkzeuge.
Um eine neue Datentabelle zum Verfolgen Ihrer Werkzeuggegenstände zu erstellen, befolgen Sie diese Schritte:
Gehen Sie im Inhaltsbrowser in den Ordner FirstPerson > Daten und erstellen Sie eine neue Datentabelle.
Wählen Sie ItemData als Zeilenstruktur aus.
Nennen Sie die Tabelle DT_ToolData und doppelklicken Sie dann darauf, um sie zu öffnen.
Klicken Sie in DT_ToolData auf Hinzufügen, um eine neue Zeile für Ihren Dart-Launcher zu erstellen.
Wählen Sie die neue Zeile aus und legen Sie folgende Felder fest:
Setzen Sie Zeilenname und ID auf tool_001.
Setzen Sie Gegenstandstyp auf Werkzeug.
Setzen Sie Gegenstandsbasis auf den
DA_DartLauncher.
Speichern und schließen Sie die Datentabelle.
Aufnehmen des Dart-Launchers im Spiel testen
Sie haben Ihre Abholpunkt-Klasse modifiziert, um dem Nutzer einen Gegenstand zu gewähren, eine ausrüstbare Gegenstandsklasse erstellt, die dem Spieler ein neues Mesh, Animationen und Steuerelemente bietet, und ein Dart-Launcher-Werkzeug. Jetzt ist es an der Zeit, alles zusammenzuführen und einen In-game-Abholpunkt zu erstellen, der die Logik für ausrüstbare Gegenstand auslöst, die Sie in diesem Teil des Tutorials eingerichtet haben.
Gehen Sie im Inhaltsbrowser zu Inhalt > FirstPerson > Blueprints und ziehen Sie einen neuen BP_PickupBase in das Level. Setzen Sie die Abholpunkt-Gegenstand-ID auf tool_001 und die Abholpunkt-Datentabelle auf DT_ToolData.
Klicken Sie auf Spielen, um Ihr Spiel zu testen. Wenn das Spiel beginnt, sollte Ihr Abholpunkt mit dem Dart-Launcher initialisieren. Wenn Sie über den Abholpunkt laufen, sollte der Charakter das Werkzeug an sich nehmen!
Als Nächstes
Im letzten Abschnitt implementieren Sie Projektil-Physik in Ihrem Launcher und lassen diesen Schaumstoffpfeile abschießen!
Ein Projektil implementieren
Lernen Sie, C++ zu verwenden, um Projektile zu implementieren und sie während des Gameplays zu spawnen.
Vollständiger Code
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "ItemData.h"
#include "ItemDefinition.generated.h"
/**
* Defines a basic item with a static mesh that can be built from the editor.
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "ItemDefinition.h"
#include "EquippableToolDefinition.generated.h"
class AEquippableToolBase;
class UInputMappingContext;
// Copyright Epic Games, Inc. All Rights Reserved.
#include "EquippableToolDefinition.h"
UEquippableToolDefinition* UEquippableToolDefinition::CreateItemCopy() const
{
UEquippableToolDefinition* ItemCopy = NewObject<UEquippableToolDefinition>(StaticClass());
ItemCopy->ID = this->ID;
ItemCopy->ItemType = this->ItemType;
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "InventoryComponent.generated.h"
class UEquippableToolDefinition;
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "AdventureGame/EquippableToolBase.h"
#include "DartLauncher.generated.h"
UCLASS(BlueprintType, Blueprintable)
class ADVENTUREGAME_API ADartLauncher : public AEquippableToolBase
// Copyright Epic Games, Inc. All Rights Reserved.
#include "DartLauncher.h"
#include "AdventureGame/AdventureCharacter.h"
void ADartLauncher::Use()
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("Using the dart launcher!"));
}
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "EquippableToolBase.generated.h"
class AAdventureCharacter;
class UInputAction;
// Copyright Epic Games, Inc. All Rights Reserved.
#include "EquippableToolBase.h"
#include "AdventureCharacter.h"
AEquippableToolBase::AEquippableToolBase()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Camera/CameraComponent.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "GameFramework/Character.h"
#include "InputActionValue.h"
// Copyright Epic Games, Inc. All Rights Reserved.
#include "AdventureCharacter.h"
#include "EquippableToolBase.h"
#include "EquippableToolDefinition.h"
#include "ItemDefinition.h"
#include "InventoryComponent.h"
// Sets default values
AAdventureCharacter::AAdventureCharacter()