Defaults changed in C++ constructors do not propagate through BPs inheriting them after Hot Reload

Let’s say you have a CustomGameCharacter, and in it’s constructor you have CameraBoom->bUsePawnControlRotation = true;
You also have a BP inheriting CustomGameCharacter, and you have changed nothing in it (all the properties are at the default values, there is no ‘reset to default’ arrow next to any of them).
Now you change CameraBoom->bUsePawnControlRotation to false in the c++ constructor, and go Compile->Recompile C++ code.
The BP inheriting CustomGameCharacter will now have CameraBoom->Use Pawn Control Rotation checked, with the ‘reset to default’ arrow next to it. This is very unintuitive and might seem like Hot Reload didn’t apply any changes. WORSE YET, if you don’t do anything to the BP at this moment, just close and reopen the editor, the BP inheriting CustomGameCharacter will NOT have CameraBoom->Use Pawn Control Rotation checked (and no little arrow next to it either).

So Hot Reload is NOT behaving like an editor close/restart, which is what I would have be expected (and to me is the least suprising) behavior.

UE4 version 4.6 preview compiled from source commit eaf05d951d2345782be4464a77d895d029ff482c

Reposting what I said on another similar question:

You’re saying that UPROPERTYs that have their default value changed in native code don’t update to the new value when you recompile? I think this is by design.

I’m going to speculate as to what’s going on here - perhaps someone from Epic can confirm this.

By way of an example: Your NativeActor class has a property, int32 MeaningOfLife = 42;

You create a blueprint based on the native code class. At this point, your blueprint has the same value, 42, for its variable. When the blueprint is stored to disk, the value 42 is saved as the blueprint-defined value, effectively overriding the default. I guess you can think of this as though the blueprint-based derived class saves MeaningOfLife = 42 in its ‘constructor’ .

If you then change the native code default to 43, when you open the blueprint version the blueprint’s ‘constructor’ runs and overrides the 43, with the value that it’s been told to use (42) (really, it is deserializing the value 42 over the top of the native code default, but thinking of it in terms of a constructor might help).

The object loader has no way of differentiating a saved value of ‘42 because that is the default’ with ‘42 because the user typed 42’ and so it preserves the user value rather than assuming you wanted to just use the default.

You could implement something that checks the values on a blueprint during serialization and only saves values that are different from the defaults. However, this then leads to the opposite problem, that if you change the default, you’d then manually need to alter any blueprints where you wanted the original value.

I thought derived BPs stored all the property values too, regardless if you changed them or not (the little arrow is present or not), but they don’t. They only save the ones you explicitly changed (this is evidenced by the fact that if I don’t use HOT RELOAD, instead closing/reopening the editor, the BP re-inherits the value from the C++ constructor, as I explained in the original post).

The problem here is that when you do HOT RELOAD, the BP (and it’s CDO, with all the properties already set) is already loaded and in memory, and that’s why the change from C++ doesn’t take any effect. This is very counter intuitive, it should work as if the editor is closed and then reopened.

Yeah, I’m learning that from comments made by staff in the other thread I posted this. Will wait to hear what they say there regarding why the CDO/constructor isn’t being run again when a hot reload is done. I know they’re already hotpatching some structures and whatnot in memory when the reload happens, so I’m wondering why they don’t re-run the constructor too.

Hi ,

Sorry for the delay in getting back to you. We are aware that changes to code in constructors not being reflected in the Editor after a Hot Reload is performed. There is a ticket in place to have this investigated (UE-1201). I am not sure what the estimated timeframe is for this, unfortunately.

I just wanted to provide a quick update on this issue. A fix was recently submitted to correct this. I ran a quick test using the fix and it appears that everything is working as expected. If you built the Engine from source code, you can find the commit containing the fix here. If you are using the binary version of the Engine installed by the Launcher, the fix will be included in a future released version of the Engine.