Pass variable data from class to Slate

Hey all. Sorry if the title isn’t a great explanation, but here it goes.

The TL;DR here is: Can a variable from a C++ class (in this case, an AI Controller) be passed into a Slate UI class?

I’ve got a simple game where if the AI spots the player, the game will end displaying the distance between them. I have some debug text (using GEngine->AddOnScreenDebugMessage) which achieves this, but obviously that’ll get stripped out in a Release build. I’ve been fighting with Slate but managed to get it working, which currently displays some text on the viewport.

I have a variable in my AI Controller C++ class m_bCanSeekerSee, and I’m wanting to pass this into my Slate UI class so the text will change based on the value of m_bCanSeekerSee. The way I have it set up currently,

SSMainMenu.h

ASeekerAIController* seekerController = NewObject<class ASeekerAIController>();

SSMainMenu.cpp

	const FText seekerNotLooking = LOCTEXT("AIState", "[PH] - Seeker is resting, hide!");
	const FText seekerIsLooking = LOCTEXT("AIState", "[PH] - Seeker is looking for you!");

	FSlateFontInfo seekerTextStyle = FCoreStyle::Get().GetFontStyle("EmbossedText");
	seekerTextStyle.Size = 30.0f;

	bool canSeekerSee = seekerController->m_bCanSeekerSee;
	
	if(canSeekerSee)
	{
		ChildSlot
		[
			SNew(SOverlay)
			+ SOverlay::Slot()
			.HAlign(HAlign_Fill)
			.VAlign(VAlign_Fill)
			.Padding(contentPadding)
			[
				SNew(SVerticalBox)
				// Seeker AI Info
				+ SVerticalBox::Slot()
				[
					SNew(STextBlock)
					.Font(seekerTextStyle)
					.Text(seekerNotLooking)
					.ColorAndOpacity(FColor::Green)
					.ShadowOffset(FVector2D(2.0f, 2.0f))
					.Justification(ETextJustify::Left)
				]
			]
		];
	}
	else
	{
		ChildSlot
		[
			SNew(SOverlay)
				+ SOverlay::Slot()
				.HAlign(HAlign_Fill)
				.VAlign(VAlign_Fill)
				.Padding(contentPadding)
				[
					SNew(SVerticalBox)
					// Seeker AI Info
					+ SVerticalBox::Slot()
				[
				SNew(STextBlock)
				.Font(seekerTextStyle)
				.Text(seekerIsLooking)
				.ColorAndOpacity(FColor::Red)
				.ShadowOffset(FVector2D(2.0f, 2.0f))
				.Justification(ETextJustify::Left)
		]
	]
];
	}
}

Breaking into the debugger, the variable gets set once the player first starts, but the class doesn’t seem to get hit again during game play, so the on screen message is always the same. Could it be the fact that each time I’m creating a new object, so the variable technically never changes? But it’s strange why the breakpoint only gets hit once, unless as it’s UI it only needs to be called when the game starts (which makes more sense).

I am trying to avoid using Widget Blueprints, just to get more experience with Unreals C++ API (and a ton of learning in the process). I know in Widget Blueprints Bindings can be made, but I’m trying to achieve this all in C++ for the challenge.

Does anyone have any advice on how best to approach this?

You should get familiar with Actors and Components before attempting to create Slate in C++ since it is a more advanced topic.

You can make two classes. The one you have SMainMenu (the S is a class prefix for SWidget) and UMainMenu inheriting from UWidget (the U is a class prefix for UObject).

The difference between SWidget and UObject is that UObjects are using UE garbage collection and UE Property System (reflection) which allows you to use property specifiers (UPROPERTY) and function specifiers (UFUNCTION). Without this you can’t do things like expose to Blueprints.

SWidget uses Smart Pointers specifically TSharedPtr instead of UE garbage collection.

Side note.
You should never use NewObject for ASeekerAIController (A is a prefix for Actor). Actors are created with SpawnActor but if it is a AIController it should already be created for you by the AI Controlled Pawn.

You pass a variable from UMainMenu (UWidget) to SMainMenu (SCompoundWidget) by using a SLATE_ATTRIBUTE.
I recommend you take a look at STextBlock and UTextBlock and see how they communicate.

I hope this gets you started.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.