Bug on C++ Documentation

There is a bug on the “Class Creatoin Basics” page of the Documentation.

This data-member has been depreciated, it’s no longer there, it causes the compile-time error

Al is not lost however, as I said, it was depreciated, not removed. You simply use the SetBrightness() method of the class instead.

I hate to have to use the forum for this, but there wasn’t any way to report the error on the documentation itself.

Also, there is no “Components” data-member in the AActor class anymore.

I’m not sure what you use instead, but there is a public function named AddComponent. Although I’ll have to dig deeper to find out how to properly call it (if it’s the right tool).

I was able add a componenet using the AddComponent(…) function, although I have no idea if it works or is “equivalent” to the previous Components.Add() call. But here’s what I did.

It built, but whether it works the way the Documentation writer intended is another story (maybe yes, maybe no, I don’t know). I had to do the same thing for the Sphere1 component mentioned in the previously mentioned Document.

PS, you don’t need to use the “this” pointer, you could just make a call to AddComponent directly, I only used it to get a grasp on IntelliSense.

PPS: I’m not up and up on the proper way to init m_FTransform, the default constructor inits it with “garbage values”, which I assume is not zeroes, so that might cause some issue with placement of the component in the engine/editor. I’ll see about getting it filled with zeroes, I think that’s what we’d want.

EDIT: This should do it

PS, if you’re wondering why i used 0.0 instead of 0, it’s because 0 is an INT and 0.0 is a floating point value. No need for implicit conversions here.

Thanks for the catch on this, I’ll make sure to email so we get it fixed up :).

We recently changed away from requiring adding things directly to the components array and removed it as you found out. When you create components in the constructor as in the example on the documentation, those components will automatically be added/registered with the actor that is its outer (the first parameter to the CreateDefaultSubobject call). So it should work as written, you just don’t have to manually add it to a components array anymore. An important thing to note though is that you should assign components you make this way to UPROPERTY variables, as the example does, because without the components array that used to exist keeping a reference to them, they would otherwise be garbage collected.

Just looking for a hard-confirmation on this. My understanding is that when we call

PointLight1 = PCIP.CreateDefaultSubobject<UPointLightComponent>( this, "PointLight1");

from the constructor, the component is added to the components array automatically? Also, do we need to save a reference to it or will it be added to the component list regardless? For example…

PCIP.CreateDefaultSubobject<UPointLightComponent>( this, "PointLight1");

definitely less useful, but would it do the trick?

I’m curious, would they be garbage collected even if you kept a pointer/reference to them in your class? I’m familiar with garbage collection happening when no references to the heap memory location is on the stack, does this mean that Actors “live” on the heap themselves? I guess that makes sense, you can’t always tell what actors are needed before runtime.

Anyway, I hope you understand this leaves a bit of a gap in the usefulness of the tutorial. Sure, we know how to add components in the constructor, but what if we wanted to add/remove them dynamically during runtime? Would a call to PCIP.CreateDefaultSubObject<type>(this, “name”) be enough in a regular member function too? I’ll try out a couple test builds and report what I find, but some confirmation would be nice. If this thread gets some more love I’ll work on getting it’s SEO spot up on Google.

PS: Thanks Billy.

The components array itself is gone now, but yes, if you call CreateDefaultSubobject in the constructor, it should do the equivalent of what the components array used to do for you automatically. You do need to save a reference to it, so you want something more like your first code snippet there instead of the second one. As long as you have a UPROPERTY pointer to it in your class, it shouldn’t get garbage collected.

I agree with you re: the tutorial, but thankfully due to your report, I confirmed we already entered a bug in our database to get that fixed up. Thanks again for the find! You can add and remove components dynamically at run-time, though I’m pretty sure the syntax differs and I don’t recall it off the top of my head. I’m actually at home right now and don’t have the full source downloaded on this PC yet, so I’ll have to wait until I’m back in the office tomorrow to get you a better answer for that particular part of your question though.

Thanks again and you’re most welcome :).

Quick follow-up on this now that I’m back at the office:

If you want to create a component during run-time, you’d want to do something like this (example of adding another static mesh component to an actor at run-time):

SampleMeshComponent = ConstructObject<UStaticMeshComponent>(UStaticMeshComponent::StaticClass(), this);

// Set whatever additional variables, etc. on the component you want here. For a static mesh component, you'd probably want to give it an actual mesh to use (SampleMeshComponent->SetStaticMesh(SomeUStaticMeshAssetHere))

// Attach the component to whichever scene component you want it attached to. For this example, attached to the root component of the actor.

// Register the component

Also, there are some templated helper functions NewObject and NewNamedObject you can use instead of ConstructObject, if you prefer. If you want to destroy the component later, you can just call DestroyComponent() on it.

Sorry, not trying to high-jack your thread just to be the grammar police, but, the word you spelled (and Im guessing how you pronounce it) are wrong; its “deprecated” and is pronounced differently as well. I worked with a guy that would always tell me things were “depreciated” and it confused the hell out of me :slight_smile:

For the Brightness member variable, it looks like it was also renamed to “Intensity” so you could just do: PointLight1->Intensity= DesiredBrightness; or you could use the SetBrightness() function like Bleakwise mentioned. Though if you look at the source code of that function you’ll see it just sets the Intensity variable.

mind blown

So, you’re saying, even with CreateDefaultSubObject, you still need to assign it to a UPROPERTY() to keep it from being garbage collected?

Yes, without some form of property reference the garbage collection system will not identify it as referenced and clean it up.

The purpose of the CreateDefaultSubObject is to properly set up the sub object’s relationship to the class such that when you instantiate an instance of the class from the default object you get a unique copy of the sub object rather than a reference to the same sub object.

I take it the UDK garbage collector keeps track of it’s references independently of the language.

For example, assuming these pointers are indeed on the stack

Contrary to Java, or CSharp, for example, which only delete objects that have no references on the stack.

The UE4 garbage collection is restricted to objects that inherit from UObject. Something like your example above would require you to manage your memory manually (I’m pretty sure flagging it with UPROPERTY would result in a UBT error). Unreal’s garbage collection is touched on briefly here:

This works, but DesiredBrightness needs to be changed to something like 1500 for the light to be visible.

To anyone getting here from google: change PointLight1->Brightness = DesiredBrightness to PointLight1->Intensity = DesiredBrightness and comment out both Components.Add calls

This worked beautifully. Thanks for the code fixes!!

Thanks to everyone for pointing out the code fixes and helping each other out. :slight_smile: The tutorial has been updated to include these changes! Going over it just now, I noticed a few more Brightness -> Intensity changes that needed to be made, but those are cleaned up and should be fixed in the next version of the tutorial. Thanks again for the feedback - keep it coming!