DrawDebugString messes up placement of the string

Hey there, im trying to have some debug info attached on to the player character. I am using the TopDown code approach from the prebuilt projects, so basically its a guy that you control running around.

I post this here as i could not find a real example of how to use the method, so maybe this helps other people as well. This is what i am using.

    void DrawDebugString
    (
        const UWorld * InWorld,
        FVector const & TextLocation,
        const FString & Text,
        class AActor * TestBaseActor,
        FColor const & TextColor,
        float Duration
    )

I call it in the Tick method of the controller. so what i do is, inside PlayerTick() of the playercontroller.cpp i call:

FString bla = Fstring("dkldkal");

FColor red = FColor::Red;
DrawDebugString
(
    getWorld(),   // i want it to be inside the current level
    getPawn()->getActorLocation(),   // i want it to be where my character is
    bla, //  thats the text i want to display
    getPawn(),  // i dont really know what to put here, but i guess it should be my character right ? 
    red,
    -1.0 // for now display it all the time
);

i would like to have the string only once and floating over the head of my char.

So what happens is it appears, and it appears multiple times , which i expected as every string just stays in the wold, as of time duration set to -1.0f.

What is really weird is the position: it seems to be way of off the character, but not only that, as i move, the position accelerates, relative to the character. This leads to the text flying in and out of the viewscreen.

i can understand its offset form the char, as i have wrong location, because of getActorLocation() giving location of root of actor, but that weird acceleration confuses me.

what is my mistake ? where should i call that DrawDebugString message anyway ? i cannot find game loop function in unreal engine, so i guess the PlayerTick servers as that , as thats where i am calling it .
How can i make this message only appear once ?

thank you for any helpful answers !!

Hi and sorry to resurrect this old thread but maybe this will help you or others.

This is how I understand DrawDebugString:

When you call it, it will add a piece of text to a list in HUD to be rendered every time the HUD is rendered. Thus if you call it in the PlayerTick, it will create a new text every tick. Instead you should only call the DrawDebugString once.

The location of the text will be the TestBaseActor’s location plus the TextLocation. Since you updated both of them each tick, the text’s location was moved “twice” thus giving the “accelerated effect” you saw.

To correctly use DrawDebugString, you’d like to do is call something like the code below somewhere else than in the Tick (for example in BeginPlay):

DrawDebugString
(
  GetWorld(), 
  FVector(0.0f, 0.0f, 100.0f), 
  TEXT("PLAYER 1"), 
  GetWorld()->GetFirstPlayerController()->GetPawn(), 
  FColor::Red, 
  -1.0f
);

BUT I assume that your purpose was that the text would follow the Pawn’s location. Unfortunately at least right now you can’t pass an argument to the DrawDebugString to do that. But you can do it by sending the text directly to the HUD via its AddDebugText function (which DrawDebugString actually uses too) and passing true for the bKeepAttachedToActor argument. Example below attaches red text PLAYER 1 to the Pawn and its location gets automatically updated each tick by the HUD:

void ADungeonCharacter::BeginPlay()
{
	Super::BeginPlay();

	// iterate through the player controller list
	for (FConstPlayerControllerIterator Iterator = GetWorld()->GetPlayerControllerIterator(); Iterator; ++Iterator)
	{
		APlayerController* PlayerController = *Iterator;
		if (PlayerController->MyHUD)
		{
			PlayerController->MyHUD->AddDebugText(
				TEXT("PLAYER 1"), 
				GetWorld()->GetFirstPlayerController()->GetPawn(), 
				-1.0f, 
				FVector(0.0f, 0.0f, 100.0f), 
				FVector(0.0f, 0.0f, 100.0f), 
				FColor::Red, 
				true, 
				false, //Set bAbsoluteLocation false since we want it to relative to the given Pawn
				true   //Set bKeepAttachedToActor true to make the text "follow" the given Pawn		
				);
		}
	}
}

BTW these pieces of text don’t get rendered if you just Simulate the game in the editor. You need to Play it.

EDIT:
If you want to change the actual message, I think you’ll need to first remove the text from the list of debug messages and then re-add it. I haven’t tried it yet but the HUD has a function RemoveDebugText which seems to do the trick. I hope this helps! (Also this forum’s formatting still seems to make massive gaps between paragraphs…)

We get the same problem with DrawDebugString when the game is launch from the editor. The text is shift by a vertical offset.
Is due to the black bands at the top and the bottom of the viewport if the camera is specified with the option “Constrain Aspect Ratio”. Obviously the projection of the location ignore this black band.

Short answer: When TestBaseActor is not null, the position you give is used as an offset from that actor’s position.

So, if you want the text above your pawn’s head, you can do one of two things. Either you can pass the actor to the DrawDebugString and give a position of, say, FVector(0,0,100), or you can manually calculate the absolute world position where the text should be positioned and pass null for the actor. Personally, I’d recommend the former. It’ll be faster and easier.