FadeObjects - Hide the objects between the camera and the character

[img]https://i0.wp.com/i.imgur.com/E2NGjws.png?resize=1140%2C600[/img] 3r33426.  3r33434. 3r33426.  3r33434. Once, it was necessary to write a module to hide objects between the camera and the character, or between several characters for the RTS game. I want to share for those who started their journey in the Unreal Engine. This tutorial, if you can call it that, will be using C ++, but in the attached project on github there will be an option on Blueprint, the functionality of both is identical. 3r33426.  3r33434. 3r33426.  3r33434. 3r33333. 3r33333. Video example 3r33333. 3r33320.
3r318.

3r33426.  3r33434.
3r33426.  3r33434. And so, let's go. We divide our task into several smaller ones:
 3r33434. 3r33426.  3r33434. 3r3335.  3r33434.
Get the objects between the camera and the character.
 3r33434.
Change the material of these objects to the desired.
 3r33434.
Change the material back to the one that was, if the object does not interfere with the review of our character.
 3r33434.
3r33426.  3r33434. We will need 2 timers, one adds objects to the array to work with them, and the second to change the object itself, in this case I change the material from normal to slightly transparent. This material can be replaced by any suitable for you. 3r33426.  3r33434.
3r33434. 3r33426.  3r33434. SFadeObjectsComponent.h
 3r33434. 3r33426.  3r33434.
FTimerHandle timerHandle_ObjectComputeTimer; 3r33434. 3r33434. FTimerHandle timerHandle_AddObjectsTimer; 3r33420. 3r33421. 3r33426.  3r33434. As soon as the object is in the array, for further work we need to memorize some of its properties, for example, what material it had before we changed it, because we will have to change it back. Also, in our case, we hide, and when necessary we return the original state of the object gradually, so we need to remember its current state. 3r33426.  3r33434. 3r33426.  3r33434. 3r33333. 3r33333. To do this, we will create a structure: [/b] 3r33320.
USTRUCT ()
struct FFadeObjStruct
{
GENERATED_USTRUCT_BODY ()
3r33434. UPROPERTY ()
UPrimitiveComponent * primitiveComp; 3r33434. 3r33434. UPROPERTY ()
TArray
baseMatInterface; 3r33434. 3r33434. UPROPERTY ()
TArray
fadeMID; 3r33434. 3r33434. UPROPERTY ()
float fade Current; 3r33434. 3r33434. UPROPERTY ()
bool bToHide; 3r33434. 3r33434. void NewElement (UPrimitiveComponent * newComponent, TArray
newBaseMat,
newMID, float currentFade, bool bHide)
{
primitiveComp = newComponent; 3r33434. baseMatInterface = newBaseMat; 3r33434. fadeMID = newMID; 3r33434. fadeCurrent = currentFade; 3r33434. bToHide = bHide; 3r33434.}
3r33434. void SetHideOnly (bool hide)
{
bToHide = hide; 3r33434.}
3r33434. void SetFadeAndHide (float newFade, bool newHide)
{
fadeCurrent = newFade; 3r33434. bToHide = newHide; 3r33434.}
3r33434. //For Destroy
void Destroy ()
{
primitiveComp = nullptr; 3r33434.}
3r33434. //Constructor
FFadeObjStruct () 3r3343435. {
primitiveComp = nullptr; 3r33434. fadeCurrent = 0; 3r33434. bToHide = true; 3r33434.}
}; 3r33434. 3r33420. 3r33421. 3r33426.  3r33434.
3r33426.  3r33434. We also need some of the settings available from Blueprint for the flexible operation of our component. Such as the type of collision to identify objects, the size of the capsule (the beam itself) from character to camera, the larger the size, the more objects around the character will be captured. 3r33426.  3r33434. 3r33426.  3r33434.
//Check trace block by this
UPROPERTY (EditAnywhere, Category = "Fade Objects")
TArray
UPROPERTY (EditAnywhere, Category = "Fade Objects")
float workDistance; 3r33434. 3r33420. 3r33421. 3r33426.  3r33434. And of course, the character class itself or other actors in the scene. 3r33426.  3r33434. 3r33426.  3r33434.
UPROPERTY (EditAnywhere, Category = "Fade Objects")
UClass * playerClass; 3r33434. 3r33420. 3r33421. 3r33426.  3r33434. We will not parse all the variables used, you can independently get acquainted with the source code. 3r33426.  3r33434. 3r33426.  3r33434. Let's turn to implementation. In BeginPlay we will start our timers. Instead of timers, you can, of course, use EventTick, but it’s better not to do this, the operation itself for changing materials if a large number of objects is quite expensive for the CPU. 3r33426.  3r33434. 3r33426.  3r33434. SFadeObjectsComponent.cpp
 3r33434. 3r33426.  3r33434.
GetWorld () -> GetTimerManager (). SetTimer (timerHandle_AddObjectsTimer, this, & USFadeObjectsComponent :: AddObjectsToHide, addObjectInterval, true); 3r33434. 3r33434. GetWorld () -> GetTimerManager (). SetTimer (timerHandle_ObjectComputeTimer, this, & USFadeObjectsComponent :: FadeObjWorker, calcFadeInterval, true); 3r33434. 3r33420. 3r33421. 3r33426.  3r33434. 3r33333. 3r33333. The function of adding an object to an array. Here I would like to note that she adds not only the actor in the scene, but also its components and SkeletalMesh, if necessary. 3r33333. 3r33320.
void USFadeObjectsComponent :: AddObjectsToHide ()
{
UGameplayStatics :: GetAllActorsOfClass (this, playerClass, characterArray); 3r33434. 3r33434. for (AActor * currentActor: characterArray)
{
const FVector traceStart = GEngine-> GetFirstLocalPlayerController (GetWorld ()) -> PlayerCameraManager-> GetCameraLocation (); 3r33434. const FVector traceEnd = currentActor-> GetActorLocation (); 3r33434. const FRotator traceRot = currentActor-> GetActorRotation (); 3r33434. FVector traceLentgh = traceStart - traceEnd; 3r33434. const FQuat acQuat = currentActor-> GetActorQuat (); 3r33434. 3r33434. if (traceLentgh.Size () < workDistance)
{
FCollisionQueryParams traceParams (TEXT ("FadeObjectsTrace"), true, GetOwner (is));
3r33434. traceParams.AddIgnoredActors, Ia.a.au), 3 k3 traceParams.bReturnPhysicalMaterial = false;
//Not tracing the complexioner
traceParams.bTraceComplex = false;
.rrr.??? /Convert ECollisionChannel to ObjectType
For (int i = 0; i < objectTypes.Num(); ++i)
{3r33434.
GetWorld () -> SweepMultiByObjectType (hitArray, traceStart, traceEnd, acQuat, traceObjectTypes,
). FCollisionShape :: MakeCapsule (capsuleRadius, capsuleHalfHeight), traceParams); 3r33434. 3r33434. for (int hA = 0; hA < hitArray.Num(); ++hA)
{
if (hitArray[hA].bBlockingHit && IsValid (hitArray[hA].GetComponent ()) && fadeObjectsHit.Contains (hitArray[hA].GetComponent ()))
{
.! . fadeObjectsHit.AddUnique (hitArray[hA].GetComponent ());
}
}
}
} 3rrr3535.
. {
//If not contains this component in fadeObjectsTemp
If (! FadeObjectsTemp.Contains (fadeObjectsHit[fO])) 33r3435. {
TArray 3r.3. Empty (); 3r33534. LMidMaterials.Empty (); 3r33435.
FadeObjectsTemp.AddUnique (fadeObjectsHit[fO]);
////rtfpffrfdpfnfdpfncfdpfcfncfnfdpfnfnfnfnfnfnf.Aid.pdf report, 3r???[fO]- > GetNumMaterials (); ++ nM) 3r3435. {
lMidMaterials.Add (UMaterialInstanceDynamic :: Create (fadeMaterial, fadeObjectsHit[fO])); 3r33434. lBaseMaterials.Add (fadeObjectsHit[fO]-> GetMaterial (nM)); 3r33434. 3r33434. //Set new material on object
fadeObjectsHit[fO]-> SetMaterial (nM, lMidMaterials.Last ()); 3r33434.}
//Create new fade object in array of objects to fade
FFadeObjStruct newObject; 3r33434. newObject.NewElement (fadeObjectsHit[fO], lBaseMaterials, lMidMaterials, immediatelyFade, true); 3r33434. //Add object to array
fadeObjects.Add (newObject); 3r33434. 3r33434. //Set collision on Primitive Component
fadeObjectsHit[fO]-> SetCollisionResponseToChannel (ECC_Camera, ECR_Ignore); 3r33434.}
}
3r33434. //Set hide to visible true if contains
Dhp Dhs for (int fOT = 0; fOT < fadeObjectsTemp.Num(); ++fOT)
{
if (! fadeObjects ittch.Contains (fadeObjectsTemp[fOT]1))
/3 /Clear array
FadeObjectsHit.Empty ();
}
3r33321.
 3r33434.
3r33426.  3r33434. 3r33333. 3r33333. The function for working with objects that changes the material from the initial to the required and back. 3r33333. 3r33320.
3r33434. void USFadeObjectsComponent :: FadeObjWorker ()
{
if (fadeObjects.Num ()> 0)
{
//For loop all fade objects
for (int i = 0; i < fadeObjects.Num(); ++i)
{
//Index of iteration
int. fnID = i;
3rH33535. float adaptiveFade; 3rrh-3435. 3rr3435. if 3r33434. AdaptiveFade = nearObjectFade;
}
Else
{
AdaptiveFade = farObjectFade; 3) .Num (); ++ t)
{
Float targetF;
Const float currentF = fadeObjects[i].fadeCurrent;
adaptiveFade;
}
else
{
targetF = 1.0f; 3r 3r3435.}
3r33434. const float newFade = FMath :: FInterpConstantTo (currentF, targetF, GetWorld () -> GetDeltaSeconds (), fadeRate); 3r33434. 3r33434. fadeObjects[i].fadeMID[t]-> SetScalarParameterValue ("Fade", newFade); 3r33434. 3r33434. currentFade = newFade; 3r33434. 3r33434. fadeObjects[i].SetFadeAndHide (newFade, fadeObjects[i].BToHide); 3r33434.}
//remove index in array
if (currentFade == 1.0f)
{
for (int bmi = 0; bmi SetMaterial (bmi, fadeObjects[fnID].baseMatInterface[bmi]); 3r33434.}
3r33434. fadeObjects[fnID].primitiveComp-> SetCollisionResponseToChannel (ECC_Camera, ECR_Block); 3r33434. fadeObjects.RemoveAt (fnID); 3r33434. fadeObjectsTemp.RemoveAt (fnID); 3r33434.}
}
}
}
3r33420. 3r33421. 3r33426.  3r33434.
3r33426.  3r33434. There is nothing special to tell here, some pieces of code, and so with comments. The video at the beginning shows the result. I also want to add the settings with which the component is initialized. 3r33426.  3r33434. 3r33426.  3r33434.
PrimaryComponentTick.bCanEverTick = false; 3r33434. 3r33434. bEnable = true; 3r33434. 3r33434. addObjectInterval = 0.1f; 3r33434. calcFadeInterval = ???f; 3r33434. 3r33434. fadeRate = 10.0f; 3r33434. 3r33434. capsuleHalfHeight = 88.0f; 3r33434. capsuleRadius = 34.0f; 3r33434. 3r33434. workDistance = 5000.0f; 3r33434. nearCameraRadius = 300.0f; 3r33434. 3r33434. nearObjectFade = 0.3; 3r33434. farObjectFade = 0.1; 3r33434. 3r33434. immediatelyFade = 0.5f; 3r33434. 3r33434. //Add first collision type
objectTypes.Add (ECC_WorldStatic); 3r33434. 3r33420. 3r33421. 3r33426.  3r33434. Perhaps someone will be useful. Or someone will tell their opinion in the comments. 3r33426.  3r33434. 3r33426.  3r33434. 3r33434. Link to source
3r33434. 3r33434. 3r33333. ! function (e) {function t (t, n) {if (! (n in e)) {for (var r, a = e.document, i = a.scripts, o = i.length; o-- ;) if (-1! == i[o].src.indexOf (t)) {r = i[o]; break} if (! r) {r = a.createElement ("script"), r.type = "text /jаvascript", r.async =! ? r.defer =! ? r.src = t, r.charset = "UTF-8"; var d = function () {var e = a.getElementsByTagName ("script")[0]; e. ): d ()}}} t ("//mediator.mail.ru/script/2820404/"""_mediator") () (); 3r3r434. 3r33434.
+ 0 -

Add comment