Crash while drawing HUD

Hi,

in my current C++ Project I try to create a custom HUD. I want to mark important actors on the screen.

I extended AHUD and in the DrawHUD() function, I draw a marker Material and a Text for each object. The following is the code of my HUD class:

// In ShipHUD.h
UCLASS()
class AShipHUD : public AHUD
{
	GENERATED_UCLASS_BODY()

	void BeginPlay() override;
	void DrawHUD() override;

protected:
	UPROPERTY(Category = Marker, EditAnywhere)
	float MarkerSize;

	UPROPERTY(Category = Marker, EditAnywhere)
	float MarkerFontScale;

private:
	struct FMarkerType
	{
		UMaterialInstance* Material;
		FLinearColor Color;

		FMarkerType() : Material(nullptr), Color(FLinearColor::White) { }
		FMarkerType(UMaterialInstance* Material, const FLinearColor& Color) :
			Material(Material), Color(Color) { }
	};

	void AddMarkerType(ERelationship Relationship, UMaterial* BaseMaterial, 
         const FLinearColor& Color);

	UPROPERTY() UFont* Font;

	/// Multiple instances of the same marker material with 
    /// different colors for friendly / neutral / hostile
	TMap<ERelationship, FMarkerType> MarkerTypes;

	/// This array just prevents the MaterialInstances from being garbage collected
	TArray<UMaterialInstance*> MarkerInstances;

	TWeakObjectPtr<AShip> Ship;
};

// In ShipHUD.cpp
AShipHUD::AShipHUD(const class FPostConstructInitializeProperties& PCIP)
	: Super(PCIP),
	MarkerSize(16.f),
	MarkerFontScale(0.6f)
{
	static ConstructorHelpers::FObjectFinder<UMaterial> MarkerMaterialOb(TEXT("/Game/UI/HUD/M_Marker"));
	static ConstructorHelpers::FObjectFinder<UFont> FontOb(TEXT("/Engine/EngineFonts/RobotoDistanceField"));
	
	// Markers
	if(MarkerMaterialOb.Succeeded() && GEngine)
	{
		AddMarkerType(ERelationship::NEUTRAL, MarkerMaterialOb.Object, FLinearColor::White);
		AddMarkerType(ERelationship::HOSTILE, MarkerMaterialOb.Object, FLinearColor::Red);
		AddMarkerType(ERelationship::FRIENDLY, MarkerMaterialOb.Object, FLinearColor::Green);
	}

	if(FontOb.Succeeded())
	{
		Font = FontOb.Object;
	}
}

void AShipHUD::BeginPlay()
{
	AHUD::BeginPlay();
	Ship = Cast<AShip>(GetOwningPawn());
}

void AShipHUD::DrawHUD()
{
	AHUD::DrawHUD();

	// Target points
	ASunAndStarsGameState* GameState = GetWorld()->GetGameState<ASunAndStarsGameState>();
	AShipPlayerController* Controller = 
        Cast<AShipPlayerController>(GetOwningPlayerController());
	if(GameState && Controller && Ship.IsValid())
	{
		uint32 PlayerTeam = Ship->GetTeam();
		for(auto It = Controller->GetTrackedObjects().CreateConstIterator(); It; ++It)
		{
			AActor* Object = It->Get();
			ERelationship Relationship = ERelationship::NEUTRAL;
			
			// See if the object has a team. If this is the case, color marker accordingly
			ITeamAssignable* TeamAssignable = InterfaceCast<ITeamAssignable>(Object);
			if(TeamAssignable)
			{
				uint32 ObjectTeam = TeamAssignable->GetTeam();
				Relationship = GameState->Diplomacy->GetRelationship(PlayerTeam, ObjectTeam);
			}

			FVector ObjectLocation = Object->GetActorLocation();
			FVector ScreenCoordinates = Project(ObjectLocation);
			if(ScreenCoordinates.Z != 0.f)
			{
				// Target point is on screen. Draw the following for each target: 
				// A crosshair marker and the name of the object with the current distance.
				// ####### The game crashes here! ########
				DrawMaterialSimple(MarkerTypes[Relationship].Material,
					ScreenCoordinates.X - MarkerSize / 2, 
					ScreenCoordinates.Y - MarkerSize / 2, 
					MarkerSize, 
					MarkerSize);
				DrawText(FString::Printf(TEXT("%s (%s)"), *Object->GetName(), 
                       *FUnrealDistance::Format(Ship->GetActorLocation(), ObjectLocation)),
					MarkerTypes[Relationship].Color,
					ScreenCoordinates.X + MarkerSize,
					ScreenCoordinates.Y - Font->GetMaxCharHeight() * MarkerFontScale / 2,
					Font,
					MarkerFontScale);
			}
		}
	}
}

inline void AShipHUD::AddMarkerType(ERelationship Relationship, UMaterial* BaseMaterial, 
    const FLinearColor& Color)
{
UMaterialInstanceDynamic* MaterialInstance = 
        UMaterialInstanceDynamic::Create(BaseMaterial, this);
MarkerInstances.Add(MaterialInstance);
MaterialInstance->SetVectorParameterValue(TEXT("Color"), Color);
MarkerTypes.Add(Relationship, FMarkerType(MaterialInstance, Color));
}

When I run the code, everything is fine, it works and I see the markers. But every time after exactly 60 Seconds, the application crashes with the following error message:

Unhandled exception at 0x00007FFB10CBC3AA (UE4Editor-Engine-Win64-Debug.dll) in UE4Editor-Win64-Debug.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.

According to the debugger, it crashes in Line 587 of Runtime/Engine/Private/HUD.cpp (I am working with the full source code version from GitHub). This is the function DrawMaterialSimple() I call in my HUD class (I marked the line in the code).

I don’t know what’s going on here. I already tried to check all memory allocations, but the fact that the program works well for 60 Seconds leads me to believe that it might be the Garbage Collector that deletes an object from right under me. But I think I made every relevant Object a UPROPERTY() Reference, so the GC should not delete it, right?

I don’t know how I can find out more about what I am doing wrong. I would really appreciate any help or guidance to solve the problem.

Thanks in advance and sorry for the long post

David

Try making your MarkerInstances array a UPROPERTY() - your comment claims it’s to keep them referenced to avoid GC, but the array needs to be a UPROPERTY() for that to happen.

Yeah, I found the answer like 2 Minutes after I posted but I couldn’t post an answer somehow. But thanks for your help and for making it clear to others what the problem was!

Your question contained a word blacklisted by our word filter (the American slang term for your bottom, or a British term for a Donkey), so it went to moderation :slight_smile:

Ah I see :slight_smile: Sorry for that!