Klasa UActorComponent

UActorComponent klasa jest klasą bazową wykorzystywane do tworzenia komponentów, które mogą być dodawane do aktorów.

Instancja UActorComponent nie ma transformacji, nie może być dołączone do innego składnika i nie ma geometrii do renderowania lub użycia w kolizji. Istnieją podklasy UActorComponent, które dodają te funkcje.

Jako przykład spójrzmy na hierarchię klas klasy UStaticMeshComponent. Ta hierarchia jest dostępna w Unreal Engine API Reference.

Oto główne podklasy  UActorComponent:

  • USceneComponent:  Instancja tej klasy ma wartość Transform i może zostać dołączona do innego składnika. 
  • UPrimitiveComponent:  wystąpienie tej klasy ma lub generuje geometrię, która może być renderowana lub używana w kolizji. 

Jeśli chcesz uzyskać odwołanie do aktora zawierającego komponent, użyj funkcji GetOwner() w Component:

AActor* ActorOwner = GetOwner();

Przykładowe użycie :

Stworzymy ActorComponent, który będzie zawierał zmienne do przechowywania zdrowia, many i poziomu gracza. Komponent będzie miał funkcję UpgradeLevel(), która zwiększy poziom gracza i zaktualizuje maksymalne wartości zdrowia i many. Ten składnik może być używany w C ++ i Blueprints.

Utwórz klasę C ++ o nazwie HealthManaComponent, używając klasy Actor Component jako klasy nadrzędnej, jak pokazano na poniższym obrazku. 

Zobacz w pliku HealthManaComponent.h, że makro UCLASS ma pewne specyfikatory, które pozwalają na użycie komponentu w Blueprints. Dodaj zmienne i funkcje, jak pokazano w poniższym kodzie:

#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "HealthManaComponent.generated.h"


UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class TUTOPROJECT_API UHealthManaComponent : public UActorComponent
{
  GENERATED_BODY()

public:	
  // Sets default values for this component's properties
  UHealthManaComponent();

  // Called every frame
  virtual void TickComponent(float DeltaTime, ELevelTick TickType,
                 FActorComponentTickFunction* ThisTickFunction) override;
	
  UFUNCTION(BlueprintPure, Category = HealthMana)
  int32 GetCurrentHealth();
	
  UFUNCTION(BlueprintCallable, Category = HealthMana)
  void SetCurrentHealth(int32 newHealth);
	
  UFUNCTION(BlueprintPure, Category = HealthMana)
  int32 GetCurrentMana();
	
  UFUNCTION(BlueprintCallable, Category = HealthMana)
  void SetCurrentMana(int32 newMana);
	
  UFUNCTION(BlueprintPure, Category = HealthMana)
  int32 GetPlayerLevel();
	
  UFUNCTION(BlueprintCallable, Category = HealthMana)
  void UpgradeLevel();
	
protected:
  // Called when the game starts
  virtual void BeginPlay() override;

  int32 CurrentHealth;
  int32 MaxHealth;
  
  int32 CurrentMana;
  int32 MaxMana;
  
  int32 PlayerLevel;
};

Funkcja FMath :: Clamp() została użyta w implementacji funkcji SetCurrentHealth() i SetCurrentMana(), aby zapobiec wartości mniejszej od zera lub większej od maksymalnej dozwolonej wartości.

Plik HealthManaComponent.cpp powinien mieć następującą zawartość:

#include "HealthManaComponent.h"

UHealthManaComponent::UHealthManaComponent()
{
  PrimaryComponentTick.bCanEverTick = true;

  CurrentHealth = 100;
  MaxHealth = 100;
  
  CurrentMana = 100;
  MaxMana = 100;
  
  PlayerLevel = 1;
}

int32 UHealthManaComponent::GetCurrentHealth()
{
  return CurrentHealth;	
}
	
void UHealthManaComponent::SetCurrentHealth(int32 NewHealth)
{
  CurrentHealth = FMath::Clamp<int32>(NewHealth, 0, MaxHealth);
}
	
int32 UHealthManaComponent::GetCurrentMana()
{
  return CurrentMana; 
}
	
void UHealthManaComponent::SetCurrentMana(int32 NewMana)
{
  CurrentMana = FMath::Clamp<int32>(NewMana, 0, MaxMana);
}

int32 UHealthManaComponent::GetPlayerLevel()
{
  return PlayerLevel;
}	
	
void UHealthManaComponent::UpgradeLevel()
{
  PlayerLevel++;

  MaxHealth = PlayerLevel * 100;
  CurrentHealth = MaxHealth;

  MaxMana = PlayerLevel * 100;
  CurrentMana = MaxMana;  
}

// Called when the game starts
void UHealthManaComponent::BeginPlay()
{
  Super::BeginPlay();
}

// Called every frame
void UHealthManaComponent::TickComponent(float DeltaTime, ELevelTick TickType,
                                FActorComponentTickFunction* ThisTickFunction)
{
  Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
}  

Najpierw zobaczmy, jak używać HealthManaComponent w Blueprint. Skompiluj kod C ++ i utwórz Blueprint. Na karcie Blueprint Components kliknij przycisk Add Component. HealthManaComponent jest w niestandardowej kategorii, jak pokazano w tym obrazie:

Na wykresie zdarzeń Blueprint można uzyskać dostęp do funkcji HealthManaComponent:

Teraz użyjmy HealthManaComponent w klasie C +. Utwórz klasę C++ o nazwie TestUActorComponent, używając klasy Actor jako klasy nadrzędnej. Plik TestUActorComponent.h powinien mieć następującą zawartość:

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "TestUActorComponent.generated.h"

UCLASS()
class TUTOPROJECT_API ATestUActorComponent : public AActor
{
  GENERATED_BODY()
	
public:	
  // Sets default values for this actor's properties
  ATestUActorComponent();

protected:
  // Called when the game starts or when spawned
  virtual void BeginPlay() override;

public:	
  // Called every frame
  virtual void Tick(float DeltaTime) override;
	
  UPROPERTY(VisibleAnywhere)
  class UHealthManaComponent* HealthManaComponent;
	
  FTimerHandle TimerHandle;

  void UpgradePlayerLevel();
};    

TestUActorComponent klasa posiada stoper, który wywołuje UpgradePlayerLevel() funkcja co 5 sekund. Funkcja ta nazywa HealthManaComponent UpgradeLevel () funkcji, a następnie wyświetla składowe wartości prądu na ekranie.

Oto zawartość pliku TestUActorComponent.cpp:

#include "TestUActorComponent.h"
#include "HealthManaComponent.h"

// Sets default values
ATestUActorComponent::ATestUActorComponent()
{
  // Set this actor to call Tick() every frame.
  PrimaryActorTick.bCanEverTick = true;
	
  HealthManaComponent = CreateDefaultSubobject<UHealthManaComponent>(
                                              TEXT("HealthManaComponent"));

}

// Called when the game starts or when spawned
void ATestUActorComponent::BeginPlay()
{
  Super::BeginPlay();
	
  GetWorldTimerManager().SetTimer(TimerHandle, this,
       &ATestUActorComponent::UpgradePlayerLevel, 5.f, true);	
}

void ATestUActorComponent::UpgradePlayerLevel()
{
  HealthManaComponent->UpgradeLevel();
	
  FString Message = FString::Printf(TEXT("Level: %d - Health: %d - Mana: %d"), 
                                    HealthManaComponent->GetPlayerLevel(),
                                    HealthManaComponent->GetCurrentHealth(),
                                    HealthManaComponent->GetCurrentMana());
       
  if(GEngine)
  {
    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, Message);
  }	
}

// Called every frame
void ATestUActorComponent::Tick(float DeltaTime)
{
  Super::Tick(DeltaTime);
}    

Skompiluj kod C ++ i dodaj instancje TestUActorComponent na swoim poziomie. Uruchom grę i poczekaj 5 sekund, aby zobaczyć komunikat na ekranie. Poniższy obrazek pokazuje, kiedy komponent osiągnął poziom 3:


Źródło:https://romeroblueprints.blogspot.com/2020/11/the-uactorcomponent-class.html

Klasa AActor

AActor klasa podklasą UObject i reprezentuje rozgrywki obiektów, które mogą być dodawane do poziomu. Klasy dziedziczące z AActor są poprzedzone A.

Niektóre funkcje AActor są osiągane poprzez użycie komponentów. Informacje o translacji, obrocie i skali AActor są uzyskiwane z jego RootComponent . Dlatego AActor musi mieć co najmniej jeden składnik USceneComponent zdefiniowany jako jego RootComponent.

Możesz użyć edytora poziomów, aby dodać aktorów i można ich tworzyć w czasie wykonywania za pomocą funkcji SpawnActor () . Istnieje kilka wersji funkcji SpawnActor () , poniższy przykład pokazuje jedną z nich, przy założeniu, że klasa AActorChild jest podklasą klasy AActor:

FVector SpawnLocation = FVector(0.0f, 0.0f, 0.0f);
    
FRotator SpawnRotation = FRotator(0.0f, 0.0f, 0.0f);    
	
GetWorld()->SpawnActor<AActorChild>(AActorChild::StaticClass(),
                                    SpawnLocation, SpawnRotation );

Kiedy chcesz zniszczyć AActor przykład, można użyć Destroy() funkcję AActor klasie . Możesz również użyć funkcji SetLifeSpan(), aby wskazać czas w sekundach, w którym AActor powinien pozostać przy życiu. Kiedy ten czas minie, AActor zostanie automatycznie zniszczony.

Przykładowe użycie:

W tym przykładzie potrzebujesz zawartość ze Starter Content

Mamy zamiar stworzyć dwóch aktorów: CannonActor i BulletActor . CannonActor utworzy jedną instancję BulletActor na sekundę. BulletActor ruszy do przodu i zostanie zniszczony po 15 sekundach.

Utwórz klasę C ++ o nazwie BulletActor, używając klasy Actor jako klasy nadrzędnej. Plik BulletActor.h musi mieć następującą zawartość:

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "BulletActor.generated.h"

UCLASS()
class TUTOPROJECT_API ABulletActor : public AActor
{
  GENERATED_BODY()
	
public:	
  // Sets default values for this actor's properties
  ABulletActor();

  // Called every frame
  virtual void Tick(float DeltaTime) override;

  virtual void NotifyActorBeginOverlap(AActor* OtherActor) override;

  UPROPERTY(VisibleAnywhere)
  USceneComponent* RootScene;

  UPROPERTY(VisibleAnywhere)
  UStaticMeshComponent* StaticMesh;
	
  UPROPERTY(VisibleAnywhere)
  class UProjectileMovementComponent* ProjectileMovement;


protected:
  // Called when the game starts or when spawned
  virtual void BeginPlay() override;

}; 

BulletActor klasa składa się z trzech komponentów: 

  • USceneComponent:  ma transformację i będzie używany jako składnik główny.
  • UStaticMeshComponent: zawiera Static Mesh, która będzie wizualnie reprezentować aktora.
  • UProjectileMovementComponent : komponent używany do poruszania aktora. Zwróć uwagę, że słowo kluczowe class zostało umieszczone przed definicją zmiennej. Będziesz musiał dodać #include tej klasy w pliku cpp

W pliku BulletActor.cpp definicja konstruktora wygląda następująco:

#include "BulletActor.h"
#include "GameFramework/ProjectileMovementComponent.h"

// Sets default values
ABulletActor::ABulletActor()
{

  // Set this actor to call Tick() every frame.  
  PrimaryActorTick.bCanEverTick = true;

  RootScene = CreateDefaultSubobject<USceneComponent>(TEXT("RootScene"));
  RootComponent = RootScene;

  StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
  StaticMesh->SetupAttachment(RootScene);
  StaticMesh->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Overlap);

  ConstructorHelpers::FObjectFinder<UStaticMesh> MeshFile(
    TEXT("/Game/StarterContent/Shapes/Shape_Sphere.Shape_Sphere"));

  if (MeshFile.Succeeded())
  {
    StaticMesh->SetStaticMesh(MeshFile.Object);
  }
	
  ProjectileMovement = CreateDefaultSubobject<UProjectileMovementComponent>( 
                                             TEXT("ProjectileMovementComp") );
  ProjectileMovement->UpdatedComponent = StaticMesh;
  ProjectileMovement->InitialSpeed = 500.f;
  ProjectileMovement->MaxSpeed = 500.f;
  ProjectileMovement->ProjectileGravityScale = 0.f;

}

Te trzy składniki są inicjowane w konstruktorze. BulletActor wykorzystuje Static Mesh Sphere i będzie poruszać się z prędkością 500 jednostek na sekundę bez grawitacji.

Inne funkcje, które należy zaimplementować w BulletActor.cpp, to:

void ABulletActor::BeginPlay()
{
  Super::BeginPlay();		
	
  SetLifeSpan(15.f);
}

void ABulletActor::NotifyActorBeginOverlap(AActor* OtherActor)
{
  Super::NotifyActorBeginOverlap(OtherActor);

  Destroy();
}

W funkcji BeginPlay() zdefiniowano, że instancja ABulletActor zostanie zniszczona po 15 sekundach. Funkcja NotifyActorBeginOverlap() jest wywoływana, gdy wystąpienie nakłada się na innego aktora. W naszym przykładzie instancja ABulletActor jest niszczona, jeśli tak się stanie.

Teraz utwórz klasę C ++ o nazwie CannonActor, używając klasy Actor jako klasy nadrzędnej. Plik CannonActor.h musi mieć następującą zawartość:

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "CannonActor.generated.h"

UCLASS()
class TUTOPROJECT_API ACannonActor : public AActor
{
  GENERATED_BODY()
	
public:	
  // Sets default values for this actor's properties
  ACannonActor();

  // Called every frame
  virtual void Tick(float DeltaTime) override;

  UPROPERTY(VisibleAnywhere)
  USceneComponent* RootScene;

  UPROPERTY(VisibleAnywhere)
  UStaticMeshComponent* StaticMesh;
	
  FTimerHandle ShotTimerHandle;
	
  void ShootCannon();	

protected:
  // Called when the game starts or when spawned
  virtual void BeginPlay() override;
  
};

ACannonActor klasa posiada stoper, który wywołuje ShootCannon funkcji raz na sekundę, aby utworzyć wystąpienie ABulletActor.

Oto konstruktor znajdujący się w pliku CannonActor.cpp:

#include "CannonActor.h"
#include "BulletActor.h"

// Sets default values
ACannonActor::ACannonActor()
{
  // Set this actor to call Tick() every frame.
  PrimaryActorTick.bCanEverTick = true;

  RootScene = CreateDefaultSubobject<USceneComponent>(TEXT("RootScene"));
  RootComponent = RootScene;

  StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
  StaticMesh->SetupAttachment(RootScene);
	
  ConstructorHelpers::FObjectFinder<UStaticMesh> MeshFile(
    TEXT("/Game/StarterContent/Props/SM_MatPreviewMesh_02.SM_MatPreviewMesh_02"));

  if (MeshFile.Succeeded())
  {
    StaticMesh->SetStaticMesh(MeshFile.Object);
  }
		
}

Timer jest konfigurowany w funkcji BeginPlay(). Funkcja ShootCannon() używa funkcji SpawnActor() do tworzenia instancji ABulletActor w położeniu i obrocie w oparciu o działo:

void ACannonActor::BeginPlay()
{
  Super::BeginPlay();
	
  GetWorldTimerManager().SetTimer(ShotTimerHandle, this,  
                                  &ACannonActor::ShootCannon, 1.f, true);	
}

void ACannonActor::ShootCannon()
{
  FRotator SpawnRotation = GetActorRotation();
	
  FVector SpawnLocation = GetActorLocation() 
                        + SpawnRotation.RotateVector(FVector(180.0f, 0.0f, 180.0f));
	
	
  GetWorld()->SpawnActor<ABulletActor>(ABulletActor::StaticClass(),
                                       SpawnLocation, SpawnRotation );
}

Skompiluj kod C ++ i dodaj wystąpienie CannonActor na poziomie. Uruchom grę i obserwuj, jak armata strzela kulami: 


Źródło:https://romeroblueprints.blogspot.com/2020/11/the-aactor-class.html

Klasa UObject

UObject klasa jest klasą bazową dla wszystkich obiektów Unreal Engine. Zapewnia zestaw ważnych usług, takich jak odbicie, serializacja, obsługa sieci i zarządzanie pamięcią.

Instancji UObject nie można dodać do poziomu. Muszą być częścią aktora. Jeśli chcesz utworzyć klasę, której instancję można utworzyć na poziomie, musi ona dziedziczyć po AActor .

Klas, które dziedziczą z UObject ale nie dziedziczą z AActor mają prefiks U . Jako przykład mamy klasę UActorComponent, która reprezentuje komponenty dodane w Actor.

Aby utworzyć instancję podklasy UObject , użyj funkcji NewObject(). Poniższy wiersz przedstawia przykład, przy założeniu, że klasa UObjectChild jest podklasą klasy UObject :

UObjectChild* ObjectChild = NewObject<UObjectChild>(this,UObjectChild::StaticClass());

Unreal Engine zarządza pamięcią tego obiektu i niszczy go, gdy nie jest już potrzebny. Ale jeśli chcesz zniszczyć instancję UObject , możesz użyć funkcji ConditionalBeginDestroy () i przypisać nullptr do wskaźnika:

ObjectChild->ConditionalBeginDestroy();
ObjectChild = nullptr;

Przykładowe użycie:

Utwórz klasę C ++ o nazwie RpgDiceSet, używając klasy Object jako klasy nadrzędnej. Konieczne jest zaznaczenie opcji Pokaż wszystkie klasy , aby klasa Object była wyświetlana tak, jak pokazano na obrazku.

RpgDiceSet klasa będzie stanowić zbiór pięciu kości. Posiada funkcję RollDice () do rzucania kośćmi i funkcję ResultString (), która zwraca wynik kości.

W pliku RpgDiceSet.h dodaj następujący kod:

...

UCLASS()
class TUTOPROJECT_API URpgDiceSet : public UObject
{
  GENERATED_BODY()

//For simplicity, the variables are public.	
public: 
	
// Note for non-native English readers:
// Die is the singular of Dice.
  
  int32 Die1;
  int32 Die2;
  int32 Die3;
  int32 Die4;
  int32 Die5;
  
  void RollDice(int32 NumFaces);

  FString ResultString();
	
}; 

W pliku RpgDiceSet.cpp dodaj implementację dwóch funkcji pokazanych poniżej:

#include "RpgDiceSet.h"

void URpgDiceSet::RollDice(int32 NumFaces)
{  
  if(NumFaces >= 2 && NumFaces <= 20)
  {
    Die1 = FMath::RandRange(1, NumFaces);
    Die2 = FMath::RandRange(1, NumFaces);
    Die3 = FMath::RandRange(1, NumFaces);
    Die4 = FMath::RandRange(1, NumFaces);
    Die5 = FMath::RandRange(1, NumFaces);
  }
  else
  {
    Die1 = 0;
    Die2 = 0;
    Die3 = 0;
    Die4 = 0;
    Die5 = 0;	
  }
}
  
FString URpgDiceSet::ResultString()
{
	  
  FString Result = FString::Printf(
                      TEXT("Die 1: %d; Die 2: %d; Die 3: %d; Die 4: %d; Die 5: %d;"), 
                      Die1, Die2, Die3, Die4, Die5);
									 
  return Result;
									 
}

Funkcja  RollDice ()  ma  parametr NumFaces  , który wskazuje liczbę ścianek kości.  Należy przekazać liczbę całkowitą od 2 do 20 . Funkcja FMath :: RandRange (int32 Min, int32 Max) zwraca losową wartość całkowitą > = Min i <= Max .

Funkcja ResultString() zwraca FString zawierający wyniki wszystkich kości.

Teraz utwórz klasę C ++ o nazwie TestUObject, używając klasy Actor jako klasy nadrzędnej. W pliku TestUObject.cpp dodaj #include „RpgDiceSet.h” i zaimplementuj funkcję BeginPlay() w następujący sposób:

#include "TestUObject.h"
#include "RpgDiceSet.h"

void ATestUObject::BeginPlay()
{
  Super::BeginPlay();
	
  URpgDiceSet* RpgDiceSet = NewObject<URpgDiceSet>(this, URpgDiceSet::StaticClass());

  RpgDiceSet->RollDice(20);
	
  if(GEngine)
  {
    GEngine->AddOnScreenDebugMessage(-1, 10, FColor::Red, 
                                     RpgDiceSet->ResultString() );
  }

  RpgDiceSet->ConditionalBeginDestroy();
  RpgDiceSet = nullptr;	
}

...

Funkcja BeginPlay() tworzy instancję klasy URpgDiceSet, wywołuje jej funkcje, wyświetla wynik na ekranie, a następnie rozpoczyna niszczenie utworzonej instancji.

Skompiluj kod C ++ i dodaj wystąpienie TestUObject na poziomie. Uruchom grę i zobacz wyniki kostek wyświetlane na ekranie. Poniższy obraz przedstawia jedną z realizacji:


Źródło:https://romeroblueprints.blogspot.com/2020/11/the-uobject-class.html

Stworzenie Nowego Testowego Projektu

Uruchom Unreal Engine i wybierz Game w New Project Categories . Kliknij przycisk Next, aby kontynuować.

Na następnym ekranie wybierz szablon First Person i kliknij przycisk Next.

Na ekranie Project Settings zachowaj typ projektu jako Blueprint. Później dodamy klasy C ++. Inne opcje używane w tym projekcie to  Desktop / Console, Maximum Quality, Starter Content, Ray Tracing możemy wyłączyć.

Utworzyłeś właśnie projekt oparty wyłącznie na Blueprints. Aby przekonwertować go na projekt C ++, po prostu możesz utworzyć klasę C++, a edytor Unreal ją skonwertuje. Musisz mieć zainstalowany program Visual Studio. Blueprints projektu zostaną utworzone w katalogu FirstPersonBP\Blueprints.



Źródło: https://romeroblueprints.blogspot.com/2021/03/creating-sample-project.html

Przegląd projektu w C++ oraz Blueprints

Przykładowy projekt w 3 części oparty jest na szablonie First Person silnika Unreal Engine.

Projekt ma czterech aktorów: PlayerCharacter, PlayerProjectile, EnemyCannon i EnemyProjectile. Wszystkie mają klasę bazową w C++ i jeden lub więcej parent Blueprints.

Prosta biblioteka funkcji Blueprint została również utworzona w C++, aby pokazać, jak to działa.

Na poziomie są działka wroga, które wystrzeliwują w kierunku gracza pociski naprowadzające. Gracz może niszczyć działa i pociski. Możesz użyć klawisz TAB, aby zmienić typ pocisku wystrzeliwanego przez broń gracza.

Projekt został wykonany na silniku Unreal Engine w wersji 4.26. Projekt z kodem źródłowym jest dostępny pod tym linkiem:

Tutorial Part 3

Przy pierwszym otwarciu projektu pojawi się komunikat z pytaniem, czy chcesz przebudować moduły. Kliknij przycisk Tak .


Źródło:https://romeroblueprints.blogspot.com/2021/03/overview-of-sample-project-with-c-and.html

 

Shape Traces

Tracing można również wykonać za pomocą określonych kształtów. Istnieją funkcje śledzenia dla kształtów box, capsule czy sphere shapes, ale te funkcje są droższe dla wydajności w wykonaniu niż przy liniach.


Dla wszystkich tych kształtów istnieją funkcje do śledzenia według kanału i typu obiektu. Istnieją również funkcje dla pojedynczych trafień lub wielu trafień.

Line Trace By Channel

Funkcja LineTraceByChannel sprawdza kolizję wzdłuż zdefiniowanej linii za pomocą kanału śledzenia, którym może być „Visibility” lub „Camera”, i zwraca strukturę Hit Result z danymi dla pierwszego trafienia Actor w teście kolizji.


Punkty wejścia:

  • Start oraz End: wektory lokalizacji definiujące początek i koniec linii, która ma być użyta do testu zderzenia.
  • Trace Channel: kanał używany do testu kolizji. Może to być „Widoczność” lub „Kamera”.
  • Trace Complex, Actors to Ignore, Draw Debug Type: te parametry są używane do debuowania

Break Hit Result

Kiedy funkcja śledzenia koliduje z czymś, zwraca jedną lub więcej struktur Hit Result. Break Hit Result może być użyty do uzyskania dostępu do elementów wyniku trafienia, jak widać na obrazku po prawej stronie.
Niektóre elementy Break Hit Result:

  • Blocking Hit: wartość logiczna Boolean, która wskazuje, czy nastąpiło trafienie blokujące.
  • Location: lokalizacja trafienia
  • Normal: normalny wektor trafienia w przestrzeni świata
  • Hit Actor: Odniesienie do Aktora trafionego przez trace

Blueprint Interface

Blueprint Interface (BPI) zawiera tylko definicje funkcji, bez implementacji.
Jeśli klasa Blueprint implementuje BPI, używa dostarczonej definicji, a następnie implementuje własną logikę dla tej funkcji.

Aby utworzyć nowy Blueprint Interface, kliknij Create New w Content Browser a nastepnie z Blueprints wybierz Blueprint Interface

Aby dodać Blueprint Interface do klasy Blueprint, kliknij przycisk Class Settings na pasku narzędzi w edytorze Blueprints. W sekcji Interfejsy w panelu Szczegóły kliknij przycisk Dodaj i wybierz klasę Blueprint Interface.

W przykładzie powyżej klasy Third Person Character mamy odziedziczony interface “Nav Agent Interface” od klasy Character

Istnieje kilka funkcji narzędziowych związanych z interfejsami Blueprint.

  • Does Implement Interface: sprawdza czy konkretny obiekt ma zaimplementowany Blueprint Interface
  • Get All Actors with Interface: znajduje wszystkich aktorów na bieżącym poziomie, które mają wdrożony Blueprint Interface

Random Numbers From Streams

Możliwe jest utworzenie sekwencji powtarzalnych liczb losowych za pomocą zmiennej Random Stream.


Aby to zrobić, utwórz zmienną typu „Random Stream”. Ustaw właściwość Initial Seed w sekcji Default Value panelu Details dla zmiennej.


Wartość właściwości Initial Seed definiuje sekwencję liczb losowych.