Unreal Engine 4 provides three specifiers to control the visibility and editability of an C++ class member exposed to Blueprint via UPROPERTY()
.
The documentation in the UE4 source code (see also UE4 wiki, UE4 documentation) says the following regarding editability:
VisibleAnywhere
, VisibleInstanceOnly
, VisibleDefaultsOnly
:
... cannot be edited at all.
EditAnywhere
, EditInstanceOnly
, EditDefaultsOnly
:
... can be edited ...
For BlueprintReadOnly
:
... can be read by blueprints, but not modified.
and BlueprintReadWrite
:
... can be read or written from a blueprint.
Questions:
Since the Visible*
specifiers already restrict the usage to read only in Blueprints, why it is used in conjunction with BlueprintReadOnly
? Isn't the second specifier superfluous? Example:
UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly)
UMyActorComponent* MyActorComponent;
Even more confusing is the usage of Edit*
specifiers, which allow read and write in Blueprint, together with BlueprintReadOnly
which restricts to read only in Blueprint. Aren't both specifiers opposing each other? Example:
UPROPERTY(EditAnywhere, BlueprintReadOnly)
UMyActorComponent* MyActorComponent;
Visible*
/Edit*
specifiers valid in a different context than the BlueprintRead*
specifiers? (the question is not about InstanceOnly
(property windows for instances), DefaultsOnly
(property windows for archetypes) and Anywhere
(instances & archetypes))UPROPERTY is a macro that adds garbage collection and stuff like exposing to Blueprint, etc to plain properties. UFUNCTION is pretty much the same thing but for functions.
Blueprint Read Only This means that the variable's value can not be changed away from the established default value. In addition, all SET nodes for the variable will be disabled.
TSubclassOf is a template class that provides UClass type safety. For instance, let's imagine that you are creating a projectile class that allows the designer to specify the damage type.
Unreal implements a garbage collection scheme whereby UObjects that are no longer referenced or have been explicitly flagged for destruction will be cleaned up at regular intervals. The engine builds a reference graph to determine which UObjects are still in use and which ones are orphaned.
tl;dr
Visible*
/Edit*
specifiers allow you (typically a game designer) to access/modify a variable directly in Blueprint Editor for quick configurations of class properties. BlueprintRead*
allow you to get/set the value of a variable in the Event Graph when you're doing Visual Scripting.Explanation:
Some namings and explanations in the official documentation are indeed a little ambiguous, especially for beginners. In a nutshell, both Visible*
/Edit*
and BlueprintRead*
expose a variable in a class to the Unreal Engine, but do different things. In fact, both question 2 and 3 can be answered via question 1. Let's see your question 1:
Since the
Visible*
specifiers already restrict the usage to read only in Blueprints, why it is used in conjunction withBlueprintReadOnly
? Isn't the second specifier superfluous? Example:
UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly) UMyActorComponent* MyActorComponent;
Here you're exposing an ActorComponent
to the Engine. Here I'll explain a non-Component
member variable first, because specifiers for Component
"appears" to work differently from non-Component
variables.
Suppose I have a TpsCharacter
class for a Third Person Shooter character, which has the following 3 float
variables:
// The zooming speed
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Camera Zoom")
float ZoomSpeed;
// The FOV after zoom in
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Camera Zoom")
float ZoomInFov;
// The default FOV
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Camera Zoom")
float DefaultFov;
They're all specified as EditDefaultsOnly
, which means that, after we create a Blueprint class called TpsCharacter_BP
based on this C++ class and open this Blueprint, the values of these 3 variables are editable in the Details Panel for this Blueprint class, as shown in the picture:
Of course, by using Visible*
specifiers, they are read-only (greyed out in the Details Panel) so you can't change their values.
Now let's get back to your MyActorComponent
. Like I said, specifiers for Component
works somewhat differently.
Component
appear in the Components Panel together with its owner class in the Blueprint Editor instead of in Details Panel like a non-Component
variable. Visible*
nor Edit*
specifiers for a Component
, this Component
itself will always appear in the Editor, but you can't access properties/variables inside this Component., and Details Panel for this Component
will be empty.Visible*
specifier allows you to access the Component
's properties via its Details Panel, just like accessing the 3 variables in my TpsCharacter_BP
class. However, when you declare it as Edit*
, the Details Panel will show wired settings, allowing you to modify the Pointer value of this Component
rather than its contents. This is definitely one thing you should always avoid.Rule of thumb for Component
: NEVER declare them as Edit*
because it allows you change the pointer value to point to other things; always do Visible*
. For a non-Component
object you're free to set Edit*
.
Now it's much easier to understand BlueprintRead*
specifier. Is it superfluous with the presence of Visible*
? Is BlueprintReadOnly
opposing Edit*
specifiers? Absolutely no. Are they valid in different context? Yes. The BlueprintRead*
specifier allows you to read/write a variable in the Event Graph in the Blueprint Editor, that is, when you're doing Blueprint Visual Scripting. For my TpsCharacter
class above, since all 3 variables are declared BlueprintReadOnly
, I can get their values inside the Event Graph as shown here:
You can do the same for your MyActorComponent
. By using BlueprintReadWrite
, you can also set the value for these variables in Event Graph.
I write such long answer to explain because they can really confuse beginners though they're actually simple concepts.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With