Logging Actor Names

Hey there,

This is a category that might also evolve into a request, based on the answer provided.

How do you log the names of actors, and then concatenate them to an existing log statement?

In unrealscript, we would do this:

`log(“Testing what the name of this actor is:” @ MyActor);

And it would return this:

“Testing what the name of this actor is: MyActor_0”

Thing about unrealscript was concatenation was a breeze. It had its own special operator – two in fact. Is there any way that the epic devs could code a special concat operator at the native level? Or if not, how can I roll my own so that this common operation becomes less cumbersome? (This is also so I can avoid a recurrence of my carpal tunnel, which is something that would most certainly happen if I had to keep doing all this lengthy typing just to do the same thing)

All I know was how unrealscript allowed for creating custom operators via
"function static final operator(TokenID) "

But with C++ doing things a lot differently – including string concatenation and creating custom operators – I’m at a bit of a loss for how to do even this most basic task.

To make this easier, I’ll just throw out some code and see what I should do with it:

void ClassName::LogActorName(AActor& TheActor)
{
    UE_Log(TEXT(strcat("This a testing statement. ", TheActor.GetActorNameToken())));
}

I know GetActorNameToken doesn’t exist, just trying to find out the equivalent of doing such in the R++ architecture. :slight_smile:

UE_LOG uses printf markup for parameterization (http://www.cplusplus.com/reference/cstdio/printf/)

The code you want will look something like:

void ClassName::LogActorName(AActor& TheActor)
{
    UE_LOG(LogClass, Log, TEXT("This a testing statement. %s"), *TheActor.GetName());
}

LogClass is the log category, you can use an existing category or define your own using DEFINE_LOG_CATEGORY_STATIC. Log is the verbosity level to use. Then you have the text you wish to output including the markup for the parameters. And then you have the parameter list. GetName returns an FString and the * operator will return the TCHAR* required for a %s parameter.

1 Like

Duh, I should have remembered the printf stuff from Fabrice’s earlier log question. Thanks Marc, I appreciate you being patient with me. :slight_smile:

I just have one follow up, and then I’ll get out of your hair about this.

I’d like to save myself the trouble of having to create a shorthand log function in every class file if that’s possible. Where would I need to put the declaration and definition for this shorthand function?

I know that to register logs, you put them in the MyProject.h module file and define it in MyProject.cpp. And so I figure the means for propogating functions across all project classes must be the same. But it appears that this file does not inherit from any base classes, nor does it have any actual classes /in/ it in which to recognize things like AActor.

So if I want to create universal functions, what do I need to do? Am I okay to write a custom class in MyProject.h/cpp or will this be problematic to how Unreal handles things? Or what do you suggest?

There’s a lot of ways you could go about doing it, but I’d probably create a uclass called something like UMyDebugFunctions and then declare some static functions in that class. That you can call from anywhere, something like: UMyDebugFunctions::LogActorName(*TheActor);

The reason I would make it a uclass instead just a plain c++ class is then you could also expose those functions as blueprint callable functions similar to how those in GameplayStatics or the various Kismet libraries are set up.

I’m confused about the parameters for UE_LOG.

/** 
 * A  macro that outputs a formatted message to log if a given logging category is active at a given verbosity level
 * @param CategoryName name of the logging category
 * @param Verbosity, verbosity level to test against
 * @param Format, format text
 ***/

What is an example of category name?

The same for verbosity and format.

I just want a simple log function where I can write"

UE_LOG(object);

and it prints the name of the object. And if the object doesn’t exist, then just return “null”.

ie- JavaScript:

// returns “Actor”
console.log(BulletProjectile)

UE_LOG is a system that allows you categorize and toggle the verbosity of each log category

You can define a CategoryName for use in a file using DECLARE_LOG_CATEGORY_STATIC(, , All) (technically All is a verbosity level, but I’m not sure of the value, everything in our code puts all there)
You can define a CategornyName for a system using DECLARE_LOG_CATEGORY_EXTERN macro in a header (same parameters as STATIC), and then DEFINE_LOG_CATEGORY() in a cpp

So an example might look like DECLARE_LOG_CATEGORY_STATIC(LogMyFile, Log, All)

Verbosity is defined in the ELogVerbosity enum. Valid values are Fatal, Error, Warning, Display, Log, Verbose, VeryVerbose.

I will flag the logging system as something that could use some better documentation.

Thank for for the response Marc.

That helped to clarify things a bit. Yes, please improve the docs for debugging, or logging in particular. Despite how simple it is, I find it invaluable for seeing how things are called, and the order in which it occurs. I know that we can do this by looking at the call stack, but having a log file on screen makes it far, far easier).