Why are breakpoints being triggered excessively on start debugging?

Hey,

I have a default Code Side Scroller project with one additional class, implemented in all C++ code. The code compiles and runs just fine. The constructor for the class is below.

AExplosiveObject::AExplosiveObject(const class FPostConstructInitializeProperties& PCIP)
	: Super(PCIP)
{
	
	PrimaryActorTick.bCanEverTick = true;
	
	TouchSphere = PCIP.CreateDefaultSubobject<USphereComponent>(this, TEXT("TouchSphereComponent"));
	TouchSphere->SetSphereRadius(20.f, false);
	RootComponent = TouchSphere;
	
	RotationRate = 200.f;
	
	//TouchSphere->OnComponentBeginOverlap.AddDynamic(this, &AExplosiveObject::OnOverlap);
	//TouchSphere->OnComponentEndOverlap.AddDynamic(this, &AExplosiveObject::OnOverlap);
}

When I add a breakpoint to the first line of the constructor and Start debugging with DebugGame Editor, I believe it should break once I start playing the game in the editor, however, that breakpoint will get triggered excessively before the editor has even loaded. I repeated it while writing this post and I had to continue through the breakpoint 14 times before the editor opened. While I am just learning to use UE4, I am sure that this could be a serious issue for large projects in the future.

What can be done to resolve this issue?

Thanks,
Mike

For every UObject (including Actors) the Engine will create a so called Class Default Object (CDO) that represents the default state of your class. This happens as part of module initialization when loading your module, which is why you see the constructor being called early on.

You should use the class constructor to initialize basic properties of your object, i.e. properties that are declared directly on your class. You should not do any game play relevant work in the constructor.

For the initialization of class instances that are created at run-time by your actual game and to update the object while the game is running there are several other methods provided by AActor that you can override. To initialize a game instance of your class you would probably want to override the BeginPlay() method, which is called by the Engine when the actor enters game play.

You probably want to move all the code that is currently in your constructor into a new method AExplosiveObject::BeginPlay(). In your class declaration, declare the function as virtual void BeginPlay() OVERRIDE; Search the code base and sample projects for examples.

Wow, thanks so much. This is some serious service we are receiving for $19/month. Hasn’t even been 15 minutes!

Anyway, that makes perfect sense. However, when you say that we should not do gameplay relevant work in the class constructor, could you give an example of what should go in the class constructor? A link to an example would even suffice. I only ask because I only followed the UE4 Intro to Programming tutorial by Jeff on youtube to create this class.

Thanks again!

If you search for existing constructors (i.e. by searching for FPostConstructInitializeProperties in .cpp files of sample projects), you will notice that almost all of them are empty, and the remaining ones are doing very rudimentary initialization of class properties. The kind of initialization performed is usually of the kind that gets the object into a valid default state, i.e. set enums or integers to a certain default value.

The CDO instance that is created for all UObject based classes is never used in any game logic. It only serves as a template for when you create (or spawn) actual game objects (or actors). When you create a new object, the initial property values will be copied from the CDO.

By the way, if you ever need to access the CDO to get access to the default values, it is actually quite easy to do so. We provide the GetDefault<> template function for getting read-only copies, and with GetMutableDefault<> you can even get a writable version of the CDO. You would call, for example, GetDefault<AExplosiveObject>()->SomeProperty to access the default value of some property.

I hope this all makes sense.

This definitely makes sense! Thank you again very much.