Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why the UPROPERTY specifiers Visible*/Edit* are used together with BlueprintRead*

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:

  • For VisibleAnywhere, VisibleInstanceOnly, VisibleDefaultsOnly:

    ... cannot be edited at all.

  • For 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:

  1. 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;
    
  2. 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;
    
  3. Are the 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))
like image 777
Roi Danton Avatar asked Aug 25 '18 11:08

Roi Danton


People also ask

What is a Uproperty?

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.

Why is Blueprint read only?

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.

What is TSubclassOf?

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.

Does Unreal have a garbage collector?

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.


1 Answers

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 with BlueprintReadOnly? 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: Blueprint Editor snapshot for TpsCharacter_BP

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.

  1. 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.
  2. When you have neither 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.
  3. 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: Get variable from Event Graph

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.

like image 60
Qi Ye Avatar answered Sep 27 '22 20:09

Qi Ye