c++ toggle visibility?

This seems like a simple thing, but I can’t find it anywhere…

How do i toggle an actor’s visibility in c++?

thanks!

I dont think you can toggle an actor’s visibility but you can do that on a Scene Component by doing this:


YourComponent->ToggleVisibility();

To hide an actor you can use this:


YourActor->SetActorHiddenInGame( false );

thanks! I have this:



void ATransformSelection::ToggleHidden(AActor* Actor)
{	
	
	USceneComponent* node = Cast<USceneComponent>(Actor);
	node->ToggleVisibility(true);

}


but it crashes my game… Can i cast to a USceneComponent like this?

It will crash because you cannot cast Actor to SceneComponent. Both are two different things. Try this code:


void ATransformSelection::ToggleHidden( AActor* Actor, bool bNewHidden )
{
    Actor->SetActorHiddenInGame( bNewHidden );
}

Thanks! Much appreciated!

To make that bool blueprint accessible i can make it a UProperty, right?

You can expose that whole function to Blueprints by doing this in your header file:



UFUNCTION( BlueprintCallable, Category = "My Custom Category Name Here" )
void ToggleHidden( AActor* Actor, bool bNewHidden );


Cool, yup i have that. Weirdly, when i run the game and use these commands (mapped to a UMG button) If i GetHiddenInGame, it tells me the actor is hidden, but i can still see it. When i close and relaunch the game, the actor stays hidden and i can’t see it.

Do i need a tick event or something?

…Cancel that, it was this:



TObjectIterator<AStaticMeshActor> WorldItr;
UWorld* TheWorld = WorldItr->GetWorld();


…should have been:



TObjectIterator<AActor> WorldItr;
UWorld* TheWorld = WorldItr->GetWorld();


thanks again!

Sorry for bumping this old thread however I need some help with this. How do I go about setting ‘this’ as hidden in game?

You mean, if ‘this’ is an actor?
Just use the actor’s method
SetActorHiddenInGame(true);

You might also think about collision and ticking, when you hide your actor.

I’ve written a plugin which not only filters the visibilty of actors and actor groups,
but considers collision disabling and also works in edit mode.
Show-Productivity-Plugin
Feel free to ask again, if I got your question wrong.

I figured out what I meant to ask after some further experimentation. I was using the wrong parent class for starters. In addition though, I seem unable to create a pointer to call a (public) method within another actor? The pointer is always returning null.

In my class I am trying accessing from’s header:



AIntroDecal* MyChar;


in that same class’ cpp:



MyChar = Cast<AIntroDecal>(OtherActor);
if (MyChar)
	{
		MyChar->ToggleHidden(true);     // this should be being called
	}
	else
	{
		Debug("MyChar not working");   // this is always occurring instead of above
	}


==============================================
In IntroDecal’s header:



void ToggleHidden(bool bNewHidden);


In IntroDecal’s cpp:



void AIntroDecal::ToggleHidden(bool bNewHidden)
{
	this->SetActorHiddenInGame(bNewHidden);
}


Any idea as to what I am doing wrong to cause it to be a null pointer?

If the object being cast is not of the type specified in the template argument, it will return null.


AIntroDecal* MyChar = Cast<AIntroDecal>(actor); // if actor is not a AIntroDecal, this will cast to null.

How would I check what the other actor is?

In attempting to discover the name of what the other actor is, I attempted the following however get the error “error C3867: ‘UObjectBaseUtility::GetName’: non-standard syntax; use ‘&’ to create a pointer to member” regardless of what I do/try and solve the error. What is the proper way to get the class name that will not generate said error?


Debug(OtherActor->GetClass()->GetName);

The debug method is fairly simple:


void AMap3_LevelIntro_Trigger::Debug(FString Msg)
{
	if (GEngine)
	{
		GEngine->AddOnScreenDebugMessage(-1, 1, FColor::Red, Msg);
	}
}

My whole goal with this is to walk through a UBoxComponent (already set up) and, upon doing so, it makes a decal disappear on a wall. That is what I am attempting to do, is this the right area to even do it or?

Sorry to bump this, but I still need help

It looks from the outside like you’re going a very roundabout way of achieving the goal. First thing to note is that iterating all actors (or objects even more so) isn’t a cheap operation and get’s more expensive the larger the scene. In this case, it sounds like you want a direct pointer to the decal. The best way to do that is this.

(I’m typing this out in the forum text editor so this probably has errors)/

Create a weak pointer to the decal that you can edit when the box actor is placed in the world. Use a weak pointer to make sure the object isn’t accidentally kept around forever.

MyBox.h



UPROPERTY(EditAnywhere, Category = "Decal")
TWeakObjectPtr<UDecalComponent> DisappearingDecal;


I’m assuming your trigger is setup via an overlap or something? If so just add this to that trigger function.

MyBox.cpp



if (DisappearingDecal.IsValid())
{
    DisappearingDecal->SetActorHiddenInGame(true);
}


Since your two actors are meant to be linked to each other, it makes sense to do things this way.

Just to expand on the original answer:



void ATransformSelection::ToggleHidden(AActor* Actor)
{	
	USceneComponent* node = Cast<USceneComponent>(Actor);
	node->ToggleVisibility(true);
}


You already know now that you can’t cast an Actor to a Scene Component, since they are entirely different things. However the reason this code crashes your game is because you’re trying to dereference a ‘null’ pointer. When you do casting operations like this, if you’re not certain of the outcome you should always check that the object is valid before trying to call any functions or access any variables.



USceneComponent* node = Cast<USceneComponent>(Actor);
if (node != nullptr)
{
    node->ToggleVisibility(true);
}


However - if you know that ‘node’ should be valid, it’s probably better to use an assertion. Asserts are like crashes, but you can force them to happen when something goes wrong. The engine has a bunch of built in macros for assertions you can use, which will crash the game - but also give you a helpful message as to where and why the error occured. For example:



USceneComponent* node = Cast<USceneComponent>(Actor);

// Force-crash the game with a message if 'node' is invalid
checkf(node != nullptr, TEXT("node is invalid"));

node->ToggleVisibility(true);


Thank you so much for your response! I do get the error however that SetActorHiddenInGame is not a member of UDecalComponent?

Ah yeah, a Decal Component is just that a Component, not an Actor.

There might be such a thing as ADecalActor. If so, use that instead (it’ll be something similar).

It worked! Thank you! The one question I do have though is would it be possible to access the class of the decal itself and call a method from it or not?

Yeh it should be, technically that’s what you’re doing already by calling SetActorHidden etc.

If it doesn’t compile, try adding #include “DecalActor.h” at the top of the cpp file.

I think you misunderstood? I mean the custom class that I created and that the decal is attached to (more of a theory question/is this actually possible to do at all).

.h



UCLASS()
class FPSTEMPLATE_API AIntroDecal : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AIntroDecal(const FObjectInitializer& ObjectInitializer);
	AIntroDecal();

	UPROPERTY(EditAnywhere)
	UDecalComponent* decal;
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;
	
	// Called every frame
	virtual void Tick( float DeltaSeconds ) override;

	//UPROPERTY()
		void ToggleHidden(bool bNewHidden);
	
};


and cpp



// Sets default values
AIntroDecal::AIntroDecal(const FObjectInitializer& ObjectInitializer)
	:Super(ObjectInitializer)
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
	decal = ObjectInitializer.CreateDefaultSubobject<UDecalComponent>(this, TEXT("trigVolume"));
	RootComponent = decal;
}

// Called when the game starts or when spawned
void AIntroDecal::BeginPlay()
{
	Super::BeginPlay();
	//SetActorHiddenInGame(true);
	//ToggleHidden(true);
}

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

}

void AIntroDecal::ToggleHidden(bool bNewHidden)
{
	this->SetActorHiddenInGame(bNewHidden);
}
//some method