
Una vez, fue necesario escribir un módulo para ocultar objetos entre la cámara y el personaje, o entre varios personajes para un juego de estrategia en tiempo real. Quiero compartir para aquellos que comenzaron su viaje en Unreal Engine. Este tutorial, si puede llamarlo así, usará C ++, pero en el proyecto adjunto en github habrá una opción en Blueprint, la funcionalidad de ambos es idéntica.
Y entonces, vamos. Dividimos nuestra tarea en varias pequeñas:
- Consigue objetos entre la cámara y el personaje.
- Cambie el material de estos objetos al deseado.
- Cambie el material a lo que era si el objeto no interfiere con la revisión de nuestro personaje.
Necesitamos 2 temporizadores, uno para agregar objetos a la matriz para trabajar con ellos, y el segundo para cambiar el objeto en sí, en este caso cambio el material de normal a ligeramente transparente. Puede reemplazar este material con cualquier adecuado para usted.
SFadeObjectsComponent.h
FTimerHandle timerHandle_ObjectComputeTimer; FTimerHandle timerHandle_AddObjectsTimer;
Tan pronto como el objeto esté en la matriz, para seguir trabajando necesitamos recordar algunas de sus propiedades, por ejemplo, qué material tenía antes de cambiarlo, porque tenemos que volver a cambiarlo. Además, en nuestro caso, nos escondemos y, cuando es necesario, devolvemos el estado inicial del objeto gradualmente, por lo que debemos recordar su estado actual.
Para hacer esto, crearemos una estructura: 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; }
También necesitamos algunas configuraciones disponibles de Blueprint para la operación flexible de nuestro componente. Tal como el tipo de colisión para identificar objetos, el tamaño de la cápsula (el rayo mismo) del personaje a la cámara, cuanto mayor sea el tamaño, más objetos serán capturados alrededor del personaje.
La distancia a la que se ocultarán los objetos.
UPROPERTY(EditAnywhere, Category = "Fade Objects") float workDistance;
Y, por supuesto, la clase de personaje en sí u otros actores en la escena.
UPROPERTY(EditAnywhere, Category = "Fade Objects") UClass* playerClass;
No analizaremos todas las variables utilizadas, puede familiarizarse independientemente con las fuentes.
Pasemos a la implementación. En BeginPlay, ejecuta nuestros temporizadores. En lugar de temporizadores, puede, por supuesto, usar EventTick, pero es mejor no hacerlo, la operación en sí misma para cambiar materiales si una gran cantidad de objetos es bastante costosa para la CPU.
SFadeObjectsComponent.cpp
GetWorld()->GetTimerManager().SetTimer(timerHandle_AddObjectsTimer, this, &USFadeObjectsComponent::AddObjectsToHide, addObjectInterval, true); GetWorld()->GetTimerManager().SetTimer(timerHandle_ObjectComputeTimer, this, &USFadeObjectsComponent::FadeObjWorker, calcFadeInterval, true);
La función de agregar un objeto a una matriz. Aquí me gustaría señalar que agrega no solo el propio actor en la escena, sino también sus componentes y SkeletalMesh, si es necesario. 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;
Una función para trabajar con objetos que cambia el material del original al requerido y viceversa. void USFadeObjectsComponent::FadeObjWorker() { if (fadeObjects.Num() > 0) {
No hay nada especial que contar aquí, algunas piezas de código, etc. con comentarios. El video al principio muestra el resultado. Quiero agregar solo la configuración con la que se inicializa el componente.
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;
Quizás alguien sea útil. O alguien dirá su opinión en los comentarios.
Enlace a la fuente