Avant de commencer
Assurez-vous d'avoir terminé les objectifs suivants dans la section précédente, Équiper votre personnage :
Vous avez créé un objet à ramasser qui réapparaît et l'avez ajouté à votre niveau.
Vous avez créé un lance-fléchettes à équiper que votre personnage peut attraper et utiliser.
Projectiles de base
Votre personnage peut attraper votre lance-fléchettes, et votre outil dispose de liaisons de contrôle pour l'utiliser, mais cela ne correspond pas tout à fait à son nom. Dans cette section, vous allez implémenter la logique de projectile pour que l'objet équipé lance des fléchettes.
L'Unreal Engine possède une classe de composant de mouvement de projectile que vous pouvez ajouter à un acteur pour le convertir en projectile. Il inclut de nombreuses variables utiles, telles que la vitesse du projectile, l'effet de rebond et l'échelle de gravité.
Pour gérer les calculs liés à l'implémentation des projectiles, vous devez prendre en compte plusieurs facteurs :
Quelles sont la transformation initiale, la vitesse et la direction du projectile ?
Souhaitez-vous faire apparaître des projectiles depuis le centre du personnage ou depuis l'outil dont il est équipé ?
Quel doit être le comportement du projectile lorsqu'il entre en collision avec un autre objet ?
Créer une classe de projectile de base
Vous allez commencer par créer une classe de projectile de base, puis en créer une sous-classe afin de concevoir des projectiles uniques pour vos outils.
Pour commencer à configurer une classe de projectile de base, procédez comme suit :
Dans l'Unreal Editor, accédez à Outils > Nouvelle classe C++. Sélectionnez Acteur comme classe parente et nommez la classe
FirstPersonProjectile. Cliquez sur Créer une classe.Dans VS, accédez à
FirstPersonProjectile.h. En haut du fichier, déclarez unUProjectileMovementComponentet unUSphereComponent.Vous utiliserez le composant de sphère pour simuler les collisions entre le projectile et d'autres objets.
C++// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "FirstPersonProjectile.generated.h" class UProjectileMovementComponent; class USphereComponent;Ajoutez les spécificateurs
BlueprintTypeetBlueprintablepour exposer cette classe aux blueprints :C++UCLASS(BlueprintType, Blueprintable) class FIRSTPERSON_API AFirstPersonProjectile : public AActorOuvrez
FirstPersonProjectile.cpp. En haut du fichier, ajoutez une instruction include pour"GameFramework/ProjectileMovementComponent.h"afin d'inclure la classe de composant de déplacement de projectile.
#include "FirstPersonProjectile.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "Components/SphereComponent.h"
// Sets default values
AFirstPersonProjectile::AFirstPersonProjectile()Implémenter le comportement des projectiles lorsqu'ils touchent des objets
Pour rendre votre projectile plus réaliste, vous pouvez le configurer pour qu'il exerce une force (une impulsion) sur les objets qu'il touche. Par exemple, si vous visez un bloc activé par la physique, le projectile pousse le bloc le long du sol. Ensuite, retirez le projectile après l'impact au lieu de le laisser atteindre sa durée de vie par défaut. Créez une fonction OnHit() pour implémenter ce comportement.
Pour implémenter le comportement d'un projectile « à l'impact », procédez comme suit :
Dans
FirstPersonProjectile.h, dans la sectionpublic, définissez une propriétéfloatappeléePhysicsForce.Attribuez-lui une macro
UPROPERTY()avecEditAnywhere,BlueprintReadOnlyetCategory = "Projectile | Physics".Il s'agit de la force exercée par le projectile lorsqu'il touche un objet.
C++// The amount of force this projectile imparts on objects it collides with UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Projectile | Physics") float PhysicsForce = 100.0f;Définissez une fonction
voidOnHit(). Cette fonction est appelée lorsque l'acteur entre en collision avec un autre composant ou acteur. Elle prend les arguments suivants :HitComp: composant ayant été touché.OtherActor: acteur ayant été touché.OtherComp: composant ayant créé l'impact (dans ce cas, le composant de collision du projectile).NormalImpulse: impulsion normale de l'impact.Hit: référenceFHitResultqui contient des données supplémentaires sur l'événement de collision, comme la durée, la distance et l'emplacement.
C++// Called when the projectile collides with an object UFUNCTION() void OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);Dans
FirstPersonProjectile.cpp, implémentez la fonctionOnHit()définie dans votre fichier d'en-tête. DansOnHit(), dans une instructionif, vérifiez les points suivants :OtherActorn'est pas nul et n'est pas le projectile proprement dit.OtherCompn'est pas nul et simule également la physique.
C++void AFirstPersonProjectile::OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit) { // Only add impulse and destroy projectile if we hit a physics if ((OtherActor != nullptr) && (OtherActor != this) && (OtherComp != nullptr) && OtherComp->IsSimulatingPhysics()) { } }Cela permet de vérifier que le projectile a touché un objet qui n'était pas lui-même et qui simulait la physique.
Dans l'instruction
if, utilisezAddImpulseAtLocation()pour ajouter une impulsion au composantOtherComp.Transmettez à cette fonction la vitesse du projectile multipliée par l'attribut
PhysicsForceet appliquez-la à l'emplacement de l'acteur de projectile.C++if ((OtherActor != nullptr) && (OtherActor != this) && (OtherComp != nullptr) && OtherComp->IsSimulatingPhysics()) { OtherComp->AddImpulseAtLocation(GetVelocity() * PhysicsForce, GetActorLocation()); }AddImpulseAtLocation()est une fonction physique de l'Unreal Engine qui applique une force (impulsion) instantanée à un objet physique simulé à un emplacement spécifique dans l'espace du monde. Elle est utile pour simuler un impact, par exemple une explosion qui projette un objet, une balle qui frappe un objet ou une porte qui s'ouvre brusquement.Enfin, dans la mesure où ce projectile a touché un autre acteur, retirez le projecteur de la scène en appelant
Destroy().
Votre fonction OnHit() complète doit ressembler à ce qui suit :
void AFirstPersonProjectile::OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
{
// Only add impulse and destroy projectile if we hit a physics
if ((OtherActor != nullptr) && (OtherActor != this) && (OtherComp != nullptr) && OtherComp->IsSimulatingPhysics())
{
OtherComp->AddImpulseAtLocation(GetVelocity() * PhysicsForce, GetActorLocation());
Destroy();
}
}Ajouter les composants de maillage, de mouvement et de collision du projectile
Vous devez ensuite ajouter un maillage statique, une logique de déplacement de projectile et une sphère de collision à votre projectile, puis déterminer le mode de déplacement du projectile.
Pour ajouter ces composants à votre projectile, procédez comme suit :
Dans
FirstPersonProjectile.h, dans la sectionpublic, déclarez unTObjectPtrdans unUStaticMeshComponentappeléProjectileMesh. Il s'agit du maillage statique du projectile dans le monde.Attribuez-lui une macro
UPROPERTY()avecEditAnywhere,BlueprintReadOnlyetCategory = “Projectile | Mesh“.C++// Mesh of the projectile in the world UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Projectile | Mesh") TObjectPtr<UStaticMeshComponent> ProjectileMesh;Dans la section
protected, déclarez :Un
TObjectPtrdans unUSphereComponentappeléCollisionComponent.Un
TObjectPtrdans unUProjectileMovementComponentappeléProjectileMovement.
Attribuez à ces deux composants une macro
UPROPERTY()avecVisibleAnywhere,BlueprintReadOnlyetCategory = "Projectile | Components".C++// Sphere collision component UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Projectile | Components") TObjectPtr<USphereComponent> CollisionComponent; // Projectile movement component UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Projectile | Components") TObjectPtr<UProjectileMovementComponent> ProjectileMovement;Le composant ProjectileMovementComponent gère la logique de déplacement pour vous. Il calcule la direction que doit parcourir l'acteur parent en fonction de la vitesse, de la gravité et d'autres variables. Ensuite, pendant le
tick, il applique le déplacement au projectile.Dans
FirstPersonProjectile.cpp, dans la fonction de constructeurAFirstPersonProjectile(), créez des sous-objets par défaut pour les composants de maillage, de collision et de déplacement du projectile. Ensuite, reliez le maillage du projectile au composant de collision.C++// Sets default values AFirstPersonProjectile::AFirstPersonProjectile() { // 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; // Use a sphere as a simple collision representation CollisionComponent = CreateDefaultSubobject<USphereComponent>(TEXT("CollisionComponent")); check(CollisionComponent != nullptr);Appelez
InitSphereRadius()pour initialiser leCollisionComponentavec un rayon de5.0f.Définissez le nom du profil de collision du composant de collision sur
"Projectile"en utilisantBodyInstance.SetCollisionProfileName().Dans l'Unreal Editor, vos profils de collision sont stockés sous Paramètres du projet > Moteur > Collision, et vous pouvez définir jusqu'à 18 profils de collision personnalisés à utiliser dans le code. Le comportement par défaut de ce profil de collision "Projectile" est défini sur Block. Il crée des collisions sur tout objet avec lequel il entre en collision.
C++CollisionComponent->InitSphereRadius(5.0f); // Set the collision profile to the "Projectile" collision preset CollisionComponent->BodyInstance.SetCollisionProfileName("Projectile");Vous avez déjà précédemment défini une fonction
OnHit()pour qu'elle s'active lorsque le projectile touche un objet, mais vous devez disposer d'un mode de notification indiquant quand cette collision se produit. Pour ce faire, utilisez la macroAddDynamic()pour abonner une fonction àOnComponentHitEventdansCollisionComponent. Transmettez à cette macro la fonctionOnHit().C++// Set up a notification for when this component hits something blocking CollisionComponent->OnComponentHit.AddDynamic(this, &AFirstPersonProjectile::OnHit);Définissez le
CollisionComponenten tant queRootComponentdu projectile et en tant queUpdatedComponentdu composant de déplacement à suivre.C++// Set as root component RootComponent = CollisionComponent; ProjectileMovement->UpdatedComponent = CollisionComponent;Initialisez le composant
ProjectileMovementavec les valeurs suivantes :InitialSpeed: vitesse initiale du projectile lorsqu'il apparaît. Définissez cette option sur3000.0f.MaxSpeed: vitesse maximale du projectile. Définissez cette option sur3000.0f.bRotationFollowVelocity: indique si l'objet doit pivoter pour suivre la direction de sa vitesse. Par exemple, la façon dont un avion en papier plonge vers le haut et vers le bas lorsqu'il monte et descend. Définissez cette option surtrue.bShouldBounce: indique si le projectile doit rebondir sur les obstacles. Définissez cette option surtrue.
C++ProjectileMovement->UpdatedComponent = CollisionComponent; ProjectileMovement->InitialSpeed = 3000.f; ProjectileMovement->MaxSpeed = 3000.f; ProjectileMovement->bRotationFollowsVelocity = true; ProjectileMovement->bShouldBounce = true;
Définir la durée de vie du projectile
Par défaut, le projectile disparaît quelques secondes après avoir été lancé. Cependant, une fois que vous avez dérivé vos blueprints de projectiles dans l'éditeur, vous pouvez essayer de modifier ou de supprimer ce délai par défaut pour remplir votre niveau de fléchettes en mousse.
Pour faire disparaître le projectile au bout de quelques secondes, procédez comme suit :
Dans
FirstPersonProjectile.h, dans la sectionpublic, déclarez un float appeléProjectileLifespan.Attribuez-lui une macro
UPROPERTY()avecEditAnywhere,BlueprintReadOnlyetCategory = "Projectile | Lifespan".Il s'agit de la durée de vie du projectile, en secondes.
C++// Despawn after 5 seconds by default UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Projectile | Lifespan") float ProjectileLifespan = 5.0f;Dans
FirstPersonProjectile.cpp, à la fin de la fonction de constructeurAFirstPersonProjectile(), définissez l'optionInitialLifeSpandu projectile surProjectileLifespanpour qu'il disparaisse au bout de cinq secondes.C++// Disappear after 5.0 seconds by default. InitialLifeSpan = ProjectileLifespan;La propriété
InitialLifeSpanest héritée de AActor. Il s'agit d'un float qui détermine la durée de vie d'un acteur avant de disparaître. Une valeur de0signifie que l'acteur reste en vie jusqu'à la fin de la partie.
Votre FirstPersonProjectile.h complet doit ressembler à ce qui suit :
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "FirstPersonProjectile.generated.h"
class UProjectileMovementComponent;
class USphereComponent;
Votre fonction de constructeur AFirstPersonProjectile complète doit ressembler à ce qui suit :
// Sets default values
AFirstPersonProjectile::AFirstPersonProjectile()
{
// 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;
// Use a sphere as a simple collision representation
CollisionComponent = CreateDefaultSubobject<USphereComponent>(TEXT("CollisionComponent"));
check(CollisionComponent != nullptr);
Obtenir la direction de caméra du personnage
Les projectiles doivent apparaître depuis le lance-fléchettes proprement dit. Vous devrez donc effectuer certains calculs pour déterminer l'emplacement du lance-fléchettes et la direction dans laquelle il est orienté. Dans la mesure où le lance-fléchettes est associé au personnage joueur, ces valeurs vont changer en fonction de la position du personnage et de la direction dans laquelle il regarde.
Votre personnage à la première personne contient certaines des informations de position dont vous avez besoin pour lancer une fléchette. Commencez par modifier votre classe de personnage pour capturer ces informations avec un tracé de ligne et renvoyer le résultat.
Pour utiliser un tracé afin d'obtenir les informations nécessaires sur votre personnage, procédez comme suit :
Dans VS, ouvrez les fichiers
.het.cppde votre personnage.Dans le fichier
.h, dans la sectionpublic, déclarez une nouvelle fonction appeléeGetCameraTargetLocation()qui renvoie unFVector. Cette fonction renvoie la position dans le monde que le personnage regarde.C++// Returns the location in the world the character is looking at UFUNCTION() FVector GetCameraTargetLocation();Dans le fichier
.cppde votre personnage, implémentez la fonctionGetCameraTargetLocation(). Commencez par déclarer un FVector appeléTargetPositionà renvoyer.Créez un pointeur vers
UWorlden appelantGetWorld().C++// The target position to return FVector TargetPosition; UWorld* const World = GetWorld();Ajoutez une instruction
ifpour vérifier que lemonden’est pas nul. Dans l'instructionif, déclarez unFHitResultappeléHit.C++if (World != nullptr) { // The result of the line trace FHitResult Hit;FHitResultest une structure dans l'UE qui stocke des informations sur le résultat d'une requête de collision, y compris l'acteur ou le composant qui a été touché et l'emplacement de l'impact.Pour trouver le point vers lequel votre personnage regarde, vous allez simuler un tracé de ligne le long du vecteur que le personnage regarde vers un point distant. Si le tracé de ligne entre en collision avec un objet, vous savez dans quelle direction le personnage regarde.
Déclarez deux valeurs const FVector appelées TraceStart et TraceEnd :
Définissez
TraceStartsur l'emplacement duFirstPersonCameraComponent.Définissez
TraceEndsurTraceStart, plus le vecteur avant du composant de caméra multiplié par une valeur très élevée. Cela garantit que le tracé ira suffisamment loin pour entrer en collision avec la plupart des objets de votre monde, à condition que votre personnage ne regarde pas vers le ciel. (Si le personnage regarde vers le ciel,TraceEndest le point final du tracé de ligne.)C++// Simulate a line trace from the character along the vector they're looking down const FVector TraceStart = FirstPersonCameraComponent->GetComponentLocation(); const FVector TraceEnd = TraceStart + FirstPersonCameraComponent->GetForwardVector() * 10000.0;
Appelez
LineTraceSingleByChannel()à partir deUWorldpour simuler le tracé. Transmettez-luiHit,TraceStart,TraceEndet unECollisionChannel::ECC_Visibility.Cela simule un tracé de ligne de
TraceStartversTraceEnd, qui entre en collision avec des objets visibles et stocke le résultat du tracé dansHit.ECollisionChannel::ECC_Visibilityest le canal à utiliser pour le tracé, et ces canaux déterminent les types d'objets que votre tracé doit tenter de toucher. UtilisezECC_Visibilitypour les contrôles de caméra en ligne de mire.C++World->LineTraceSingleByChannel(Hit, TraceStart, TraceEnd, ECollisionChannel::ECC_Visibility);La valeur
Hitcontient désormais des informations sur le résultat de l'impact, notamment la position et l'orientation de l'impact. Elle indique également si l'impact est dû à une collision d'objet. Le point d’impact (ou le point d’arrivée de la ligne de tracé) correspond à l'emplacement cible de la caméra à renvoyer.Utilisez un opérateur temporaire pour définir
TargetPositionsurHit.ImpactPointsi l'impact est un tir bloquant, ou surHit.TraceEndsi ce n'est pas le cas. Ensuite, renvoyezTargetPosition.C++TargetPosition = Hit.bBlockingHit ? Hit.ImpactPoint : Hit.TraceEnd; } return TargetPosition;
Votre fonction GetCameraTargetLocation() complète doit ressembler à ce qui suit :
FVector AADventureCharacter::GetCameraTargetLocation()
{
// The target position to return
FVector TargetPosition;
UWorld* const World = GetWorld();
if (World != nullptr)
{
// The result of the line trace
FHitResult Hit;
Faire apparaître des projectiles avec DartLauncher::Use()
Maintenant que vous avez un moyen de savoir dans quelle direction le personnage regarde, vous pouvez implémenter le reste de la logique du projectile dans la fonction Use() de votre lance-fléchettes. Vous allez obtenir l'emplacement et la direction dans lesquels lancer le projectile, puis le faire apparaître.
Pour obtenir l'emplacement et la rotation auxquels le projectile doit apparaître, procédez comme suit :
Dans
DartLauncher.h, en haut du fichier, ajoutez une déclaration avancée pourAFirstPersonProjectile.Dans la section
public, déclarez une propriétéTSubclassOf<AFirstPersonProjectile>appelée ProjectileClass. Il s'agit du projectile généré par le lance-fléchettes. Attribuez-lui la macroUPROPERTY()avecEditAnywhereetCategory = Projectile.DartLauncher.hdoit maintenant ressembler à ce qui suit :C++// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "AdventureGame/EquippableToolBase.h" #include "AdventureGame/FirstPersonProjectile.h" #include "DartLauncher.generated.h" class AFirstPersonProjectile;DartLauncher.cpp, ajoutez une instruction include pour"Kismet/KismetMathLibrary.h". Les calculs liés aux projectiles peuvent être complexes, et ce fichier comprend plusieurs fonctions pratiques que vous utiliserez pour lancer des projectiles.C++#include "DartLauncher.h" #include "Kismet/KismetMathLibrary.h" #include "AdventureGame/AdventureCharacter.h"Commencez à implémenter la fonction
Use()de DartLauncher :Obtenez le
UWorlden appelantGetWorld().Ajoutez une instruction
ifpour vérifier que lemondeet laclasse Projectilene sont pas nuls.Dans l'instruction
if, obtenez la position vers laquelle le personnage regarde en appelantOwningCharacter->GetCameraTargetLocation().
C++void ADartLauncher::Use() { UWorld* const World = GetWorld(); if (World != nullptr && ProjectileClass != nullptr) { FVector TargetPosition = OwningCharacter->GetCameraTargetLocation(); } }Même si vous souhaitez générer des projectiles à partir de l'outil que tient le personnage, vous ne souhaitez peut-être pas les générer directement à partir du centre de l'objet. Le maillage
SKM_Pistoldu lance-fléchettes est doté d'un connecteur de « canon » qui permet de définir un point d'apparition précis pour vos fléchettes.Déclarez un nouveau
FVectornomméSocketLocationet configurez-le de manière à obtenir le résultat de l'appel deGetSocketLocation("Muzzle")sur leToolMeshComponent.C++// Get the correct socket to spawn the projectile from FVector SocketLocation = ToolMeshComponent->GetSocketLocation("Muzzle");Ensuite, déclarez un
FRotatorappeléSpawnRotation. Il s'agit de la rotation (valeurs de tangage, de lacet et de roulis) du projectile lorsqu'il apparaît.Définissez cette valeur sur le résultat de l'appel de
FindLookAtRotation()depuis la bibliothèque de calculs Kismet, en transmettant les valeursSocketLocationetTargetPositionque vous avez obtenues du personnage joueur.C++FRotator SpawnRotation = UKismetMathLibrary::FindLookAtRotation(SocketLocation, TargetPosition);FindLookAtRotationcalcule et renvoie la rotation dont vous avez besoin àSocketLocationpour faire face àTargetPosition.Déclarez un
FVectornomméSpawnLocationet définissez-le sur le résultat de l'ajout deSocketLocationet du vecteur avant deSpawnRotationmultiplié par10,0.Le connecteur de canon ne se trouve pas tout à fait à l'avant du lance-fléchettes. Vous devrez donc multiplier le vecteur par un décalage pour que le projectile soit tiré de l'emplacement correct.
C++FVector SpawnLocation = SocketLocation + UKismetMathLibrary::GetForwardVector(SpawnRotation) * 10.0;
Maintenant que vous avez déterminé l'emplacement et la rotation, vous pouvez faire apparaître le projectile.
Pour faire apparaître un projectile, procédez comme suit :
Toujours dans la fonction
Use(), déclarez uneFActorSpawnParametersnomméeActorSpawnParams. Cette classe contient des informations sur l'emplacement et le mode d'apparition de l'acteur.C++//Set Spawn Collision Handling Override FActorSpawnParameters ActorSpawnParams;Définissez la valeur
SpawnCollisionHandlingOverridedansActorSpawnParamssurESpawnActorCollisionHandlingMethod::AdjustIfPossibleButDontSpawnIfColliding.Cette fonction tente de trouver un emplacement où générer le projectile sans qu'il n'entre en collision avec un autre acteur (à l'intérieur d'un mur, par exemple) et ne le lance pas si aucun emplacement approprié n'est trouvé.
C++ActorSpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButDontSpawnIfColliding;Utilisez
SpawnActor()pour générer le projectile au niveau du canon du lance-fléchettes, en transmettantProjectileClass,SpawnLocation,SpawnRotationetActorSpawnParams.C++// Spawn the projectile at the muzzle World->SpawnActor<AFirstPersonProjectile>(ProjectileClass, SpawnLocation, SpawnRotation, ActorSpawnParams);
Votre fonction Use() complète doit maintenant ressembler à ce qui suit :
void ADartLauncher::Use()
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("Using the dart launcher!"));
UWorld* const World = GetWorld();
if (World != nullptr && ProjectileClass != nullptr)
{
FVector TargetPosition = OwningCharacter->GetCameraTargetLocation();
// Get the correct socket to spawn the projectile from
Obtenir un blueprint et une classe de fléchette en mousse
Maintenant que la logique d'apparition est terminée, vous devez créer un véritable projectile ! Pour déclencher votre classe de lance-fléchettes, vous devez disposer d'une sous-classe de AFirstPersonProjectile. Vous devrez donc en créer une dans le code pour l'utiliser dans votre niveau.
Pour obtenir une classe de projectile de fléchette en mousse utilisable dans le jeu, procédez comme suit :
Dans l'Unreal Editor, accédez à Outils > Nouvelle classe C++.
Accédez à Toutes les classes, recherchez et sélectionnez la classe parente Projectile à la première personne, puis nommez la classe
FloatDart. Cliquez sur Créer une classe.Dans VS, laissez ces fichiers tels quels, enregistrez votre code et compilez-le.
Dans ce tutoriel, vous n'implémenterez aucun code de projectile personnalisé au-delà de ce que vous avez défini dans FirstPersonProjectile, mais pouvez modifier la classe FloatDart à votre convenance pour répondre aux besoins de votre projet. Par exemple, vous pourriez essayer de faire en sorte que les fléchettes adhèrent aux objets au lieu de disparaître ou de rebondir.
Pour créer un blueprint de fléchette en mousse, procédez comme suit :
Dans l'Unreal Editor, créez une classe de blueprint à partir de FloatDart et nommez-la
BP_FoamDart. Enregistrez-la dans le dossierFirstPerson/Blueprints/Outils.Une fois le blueprint ouvert, sélectionnez le composant de maillage de projectile et définissez le maillage statique sur SM_FoamBullet.
Enregistrez et compilez votre blueprint.
Dans le navigateur de contenu, ouvrez
BP_DartLauncher.Dans la section Projectile du panneau Détails, définissez la classe de projectile sur
BP_FoamDart, puis enregistrez et compilez le blueprint.Si
BP_FoamDartne s'affiche pas dans la liste, accédez au navigateur de contenu, sélectionnezBP_FoamDart, puis revenez à la propriété Classe de projectile et cliquez sur Utiliser la ressource sélectionnée dans le navigateur de contenu.
C'est le moment de vérité ! Enregistrez vos ressources et cliquez sur Jouer. Lorsque le jeu commence, vous pouvez courir vers le lance-fléchettes pour le ramasser. Faites un clic gauche pour faire apparaître un projectile dans le canon du lance-fléchettes et le faire rebondir dans le niveau. Ces projectiles doivent disparaître au bout de 5 secondes et générer une légère force physique sur les objets avec lesquels ils entrent en collision (y compris vous-même !).
Suivant
Félicitations ! Vous avez terminé le tutoriel Programmeur à la première personne et avez beaucoup appris en cours de route !
Vous avez implémenté des personnages et des déplacements personnalisés, créé des objets à ramasser et des ressources de données, et même fabriqué des outils à équiper avec leurs propres projectiles. Vous disposez de tous les éléments dont vous avez besoin pour transformer ce projet en fonction de vos envies.
Voici quelques suggestions :
Pouvez-vous enrichir l'inventaire du joueur avec différents types d'objets ? Qu'en est-il des piles d'objets ?
Pouvez-vous combiner des objets à ramasser et des projectiles pour créer des munitions à ramasser ? Que diriez-vous d'implémenter ce système de munitions dans le lance-fléchettes ?
Pourriez-vous développer l'idée d'objets à usage unique pour en faire des objets à usage unique dont il est possible de s'équiper ? Que diriez-vous d'un pack de PV que le joueur pourrait porter sur lui, ou d'une balle qu'il pourrait ramasser et lancer ?
Code complet
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "FirstPersonProjectile.generated.h"
class UProjectileMovementComponent;
class USphereComponent;
// Fill out your copyright notice in the Description page of Project Settings.
#include "FirstPersonProjectile.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "Components/SphereComponent.h"
// Sets default values
AFirstPersonProjectile::AFirstPersonProjectile()
{
// 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()
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "AdventureGame/EquippableToolBase.h"
#include "AdventureGame/FirstPersonProjectile.h"
#include "DartLauncher.generated.h"
class AFirstPersonProjectile;
// Copyright Epic Games, Inc. All Rights Reserved.
#include "DartLauncher.h"
#include "Kismet/KismetMathLibrary.h"
#include "AdventureGame/AdventureCharacter.h"
void ADartLauncher::Use()
{
UWorld* const World = GetWorld();