
Einmal musste ein Modul geschrieben werden, um Objekte zwischen der Kamera und dem Charakter oder zwischen mehreren Charakteren für ein RTS-Spiel zu verbergen. Ich möchte für diejenigen teilen, die ihre Reise in Unreal Engine begonnen haben. Dieses Tutorial, wenn Sie es so nennen können, wird C ++ verwenden, aber im angehängten Projekt auf Github gibt es eine Option auf Blueprint, die Funktionalität von beiden ist identisch.
Und so, lass uns gehen. Wir teilen unsere Aufgabe in mehrere kleine auf:
- Holen Sie sich Objekte zwischen der Kamera und dem Charakter.
- Ändern Sie das Material dieser Objekte in das gewünschte.
- Ändern Sie das Material wieder in den ursprünglichen Zustand, wenn das Objekt die Überprüfung unseres Charakters nicht beeinträchtigt.
Wir benötigen zwei Timer, einen zum Hinzufügen von Objekten zum Array, um mit ihnen zu arbeiten, und den zweiten zum Ändern des Objekts selbst. In diesem Fall ändere ich das Material von normal auf leicht transparent. Sie können dieses Material durch ein für Sie geeignetes ersetzen.
SFadeObjectsComponent.h
FTimerHandle timerHandle_ObjectComputeTimer; FTimerHandle timerHandle_AddObjectsTimer;
Sobald sich das Objekt im Array befindet, müssen wir uns für weitere Arbeiten einige seiner Eigenschaften merken, z. B. welches Material es hatte, bevor wir es geändert haben, da wir es zurück ändern müssen. In unserem Fall verstecken wir uns und geben bei Bedarf schrittweise den Ausgangszustand des Objekts zurück, sodass wir uns an seinen aktuellen Zustand erinnern müssen.
Dazu erstellen wir eine Struktur: USTRUCT() struct FFadeObjStruct { GENERATED_USTRUCT_BODY() UPROPERTY() UPrimitiveComponent* primitiveComp; UPROPERTY() TArray<UMaterialInterface*> baseMatInterface; UPROPERTY() TArray<UMaterialInstanceDynamic*> fadeMID; UPROPERTY() float fadeCurrent; UPROPERTY() bool bToHide; void NewElement(UPrimitiveComponent* newComponent, TArray<UMaterialInterface*> newBaseMat, <UMaterialInstanceDynamic*> newMID, float currentFade, bool bHide) { primitiveComp = newComponent; baseMatInterface = newBaseMat; fadeMID = newMID; fadeCurrent = currentFade; bToHide = bHide; } void SetHideOnly(bool hide) { bToHide = hide; } void SetFadeAndHide(float newFade, bool newHide) { fadeCurrent = newFade; bToHide = newHide; }
Für den flexiblen Betrieb unserer Komponente benötigen wir auch einige von Blueprint verfügbare Einstellungen. Wie die Art der Kollision zum Identifizieren von Objekten, die Größe der Kapsel (der Strahl selbst) vom Charakter zur Kamera, je größer die Größe, desto mehr Objekte um den Charakter herum werden erfasst.
Die Entfernung, in der Objekte ausgeblendet werden.
UPROPERTY(EditAnywhere, Category = "Fade Objects") float workDistance;
Und natürlich die Charakterklasse selbst oder andere Akteure in der Szene.
UPROPERTY(EditAnywhere, Category = "Fade Objects") UClass* playerClass;
Wir werden nicht alle verwendeten Variablen analysieren, Sie können sich unabhängig mit den Quellen vertraut machen.
Fahren wir mit der Implementierung fort. Führen Sie in BeginPlay unsere Timer aus. Anstelle von Timern können Sie natürlich EventTick verwenden, aber es ist besser, dies nicht zu tun. Der Vorgang selbst zum Ändern von Materialien, wenn eine große Anzahl von Objekten für die CPU recht teuer ist.
SFadeObjectsComponent.cpp
GetWorld()->GetTimerManager().SetTimer(timerHandle_AddObjectsTimer, this, &USFadeObjectsComponent::AddObjectsToHide, addObjectInterval, true); GetWorld()->GetTimerManager().SetTimer(timerHandle_ObjectComputeTimer, this, &USFadeObjectsComponent::FadeObjWorker, calcFadeInterval, true);
Die Funktion zum Hinzufügen eines Objekts zu einem Array. An dieser Stelle möchte ich darauf hinweisen, dass nicht nur der Schauspieler selbst in die Szene aufgenommen wird, sondern gegebenenfalls auch seine Komponenten und SkeletalMesh. void USFadeObjectsComponent::AddObjectsToHide() { UGameplayStatics::GetAllActorsOfClass(this, playerClass, characterArray); for (AActor* currentActor : characterArray) { const FVector traceStart = GEngine->GetFirstLocalPlayerController(GetWorld())->PlayerCameraManager->GetCameraLocation(); const FVector traceEnd = currentActor->GetActorLocation(); const FRotator traceRot = currentActor->GetActorRotation(); FVector traceLentgh = traceStart - traceEnd; const FQuat acQuat = currentActor->GetActorQuat(); if (traceLentgh.Size() < workDistance) { FCollisionQueryParams traceParams(TEXT("FadeObjectsTrace"), true, GetOwner()); traceParams.AddIgnoredActors(actorsIgnore); traceParams.bTraceAsyncScene = true; traceParams.bReturnPhysicalMaterial = false;
Eine Funktion zum Arbeiten mit Objekten, die das Material vom Original zum gewünschten und umgekehrt ändert. void USFadeObjectsComponent::FadeObjWorker() { if (fadeObjects.Num() > 0) {
Hier gibt es nichts Besonderes zu erzählen, einige Codeteile und so weiter mit Kommentaren. Das Video am Anfang zeigt das Ergebnis. Ich möchte nur die Einstellungen hinzufügen, mit denen die Komponente initialisiert wird.
PrimaryComponentTick.bCanEverTick = false; bEnable = true; addObjectInterval = 0.1f; calcFadeInterval = 0.05f; fadeRate = 10.0f; capsuleHalfHeight = 88.0f; capsuleRadius = 34.0f; workDistance = 5000.0f; nearCameraRadius = 300.0f; nearObjectFade = 0.3; farObjectFade = 0.1; immediatelyFade = 0.5f;
Vielleicht ist jemand nützlich. Oder jemand wird seine Meinung in den Kommentaren sagen.
Link zur Quelle