
Uma vez, foi necessário escrever um módulo para ocultar objetos entre a câmera e o personagem, ou entre vários personagens para um jogo de RTS. Quero compartilhar para aqueles que começaram sua jornada no Unreal Engine. Este tutorial, se você pode chamar assim, estará usando C ++, mas no projeto anexo no github haverá uma opção no Blueprint, a funcionalidade de ambos é idêntica.
E então vamos lá. Dividimos nossa tarefa em várias pequenas:
- Coloque objetos entre a câmera e o personagem.
- Mude o material desses objetos para o desejado.
- Mude o material de volta para o que era se o objeto não interferisse na revisão de nosso personagem.
Precisamos de 2 temporizadores, um adiciona objetos à matriz para trabalhar com eles e o segundo para alterar o objeto em si. Nesse caso, altero o material de normal para ligeiramente transparente. Você pode substituir este material por outro adequado para você.
SFadeObjectsComponent.h
FTimerHandle timerHandle_ObjectComputeTimer; FTimerHandle timerHandle_AddObjectsTimer;
Assim que o objeto estiver na matriz, para mais trabalhos, precisamos lembrar algumas de suas propriedades, por exemplo, que material ele possuía antes de alterá-lo, porque precisamos alterá-lo novamente. Além disso, no nosso caso, ocultamos e, quando necessário, retornamos o estado inicial do objeto gradualmente, portanto, precisamos lembrar seu estado atual.
Para fazer isso, criaremos uma estrutura: 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; }
Também precisamos de algumas configurações disponíveis no Blueprint para a operação flexível de nosso componente. Como o tipo de colisão para identificar objetos, o tamanho da cápsula (o próprio feixe) do personagem para a câmera, quanto maior o tamanho, mais objetos ao redor do personagem serão capturados.
A distância em que os objetos serão ocultados.
UPROPERTY(EditAnywhere, Category = "Fade Objects") float workDistance;
E, claro, a classe de personagens em si ou outros atores na cena.
UPROPERTY(EditAnywhere, Category = "Fade Objects") UClass* playerClass;
Não analisaremos todas as variáveis usadas, você pode se familiarizar independentemente com as fontes.
Vamos para a implementação. No BeginPlay, execute nossos temporizadores. Em vez de temporizadores, você pode, é claro, usar o EventTick, mas é melhor não fazer isso, a operação em si é para alterar materiais se um grande número de objetos for muito caro para a CPU.
SFadeObjectsComponent.cpp
GetWorld()->GetTimerManager().SetTimer(timerHandle_AddObjectsTimer, this, &USFadeObjectsComponent::AddObjectsToHide, addObjectInterval, true); GetWorld()->GetTimerManager().SetTimer(timerHandle_ObjectComputeTimer, this, &USFadeObjectsComponent::FadeObjWorker, calcFadeInterval, true);
A função de adicionar um objeto a uma matriz. Aqui, eu gostaria de observar que ele adiciona não apenas o próprio ator na cena, mas também seus componentes e SkeletalMesh, se necessário. 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;
Uma função para trabalhar com objetos que alteram o material do original para o necessário e vice-versa. void USFadeObjectsComponent::FadeObjWorker() { if (fadeObjects.Num() > 0) {
Não há nada especial para contar aqui, alguns trechos de código e assim por diante com comentários. O vídeo no início mostra o resultado. Quero adicionar apenas as configurações com as quais o componente é inicializado.
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;
Talvez alguém seja útil. Ou alguém dirá sua opinião nos comentários.
Link para fonte