I’m populating data for a new FActorProperties struct for each scene and adding it to SceneData like this:
FSceneData SceneData = FSceneData();
for(int i=0; i< SceneCount; i++)
{
FActorProperties ActorProperties;
// Derived struct of FMyProperty and the values for this are generated from a property list
FMyFloatProperty* FloatProp = GetStructPointerFromProperty<FMyFloatProperty>(Actor, StructProperty);
ActorProperties.ActorSlotMap.Add(StructProperty->GetFName(), FloatProp);
ScenesData.ActorPropertiesMap.Add(i, ActorProperties);
}
I’m leaving out the logic for getting StructProperty values, basically it is generated from property iterator for the actor.
When I debug this ActorProperties, ActorProperties.ActorSlotMap[0] and ActorProperties.ActorSlotMap[1], I’m seeing correct float values 0 and 5.
Log Output:
Adding float value 0.000000
Adding float value 5.000000
Now if I query all the entries in ScenesData.ActorPropertiesMap[i].ActorSlotMap all the FloatProp values are same
Log Output:
float value: 5.000000
float value: 5.000000
I’m an Unreal c++ noob, so maybe I’m not seeing an obvious issue here.What am I doing wrong here?
Nothing pops out to me. You seem to only be adding FMyFloatProperty. Could you comment out the line with the if statement “if(Slot.Value->GetDerivedStruct() ==…”? Just to make sure you’re not overwriting the value.
There’s only four ways I can think of this happening.
You’re overwriting the same index.
The value pointer is being overwritten.
The value itself is being overwritten.
Your global logging is being run twice (and you only have one value).
I think we can rule out #1 because you wouldn’t get two values. #2 seems dubious.
#3 is possible which is why I want you to try removing the if statement checking the type.
But do you think #4 is possible? Can add a LOG statement before you start logging the SceneData’s map to ensure it’s not just running twice? If it was running twice, it likely means your data was overwritten. To me, it looks like it’s run twice from different actors and you’re only storing the last invocation. But that’s just a guess.
So my advice is make sure the number of invocations are correct when setting it and when logging it.
edit: Oh, and add the scene number in your logging.
Thank you for the suggestions. I’ve tried logging the scene index as well, and it does log 0 and 1.
This is how I’m generating the property values:
Importing a JSON with list of scenes. Each scene has a list of Actors that has list of properties
For each actor I’m spawning an actor instance, setting properties from the json. For each scene, I’m overwriting the properties on the actor instance if it’s already spawned.
For each actor, the ActorProperties list is generated from the JSON as well, from the output logs everything looks correct
Then I’m adding the ActorProperties list to SceneData for each scene. This is where something weird is happening. I’m wondering if FMyProperty pointer is pointing to the actor instance’s property which is overwritten. If that’s the case, then why does the ActorProperties log different values?
ActorProperties.Transform seems to be stored correctly. I can’t store FMyProperty by value because I need to downcast to derived struct when retrieving the values. FloatProperty is just an example, there are other types of properties
This is not a personal project, that’s why I’m unable to share the entire code.
In Visual Studio, you can set a breakpoint when you add the first value. With the debugger paused at that breakpoint, add a DATA breakpoint to your Value in FloatProp->Value. I think there’s a checkbox to stop the debugger when the value changes.
That will let you rule out anything overwriting the Value itself.
Before that though, I would put a LOG statement above this line:
FSceneData SceneData = FSceneData();
If that line runs more than once, you have an invocation issues where it’s being called too often. All of the SceneData needs to be added in this one call because you’re creating the instance here.
You could also print the pointer value of FMyFloatProprty* FloatProp in your logging code. This is to ensure you have different pointers stored.
Aside from that, this looks like you’ll need to do some debugging. The code itself looks fine to me, but I don’t know what is calling it. That’s where I think the problem lies… again just a guess. Maybe someone will see something I’m missing.
I’d also add a LOG statement before your logging with SceneData.Num().
Are you 1000% sure this returns a different pointer? Yes, you logged a different value, but LOG the pointer address too. I have no idea how that value is stored in the property. If by some design, that pointer is meant to be temporary, then perhaps you were meant to copy it (or create a new instance and copy the data).
This is why it’s giving us the same pointer, because even though I want different property values, it’s the same actor.
I’m not sure how to fix this though.
How are the values different when you insert it though? Is GetStructPointerFromProperty() setting it?
I’m not familiar with that method (ContainerPtrToValuePtr), but I’ve been reading up on it. I think ContainerPtrToValuePtr returns the Class’ pointer to that property. To get the actual value pointer for your actor, you need to call GetObjectPropertyValue(ValuePtr);
But I still don’t understand how you’re only iterating over one property and expecting two values.
thanks! GetObjectPropertyValue only works on UObjects and not structs. So
my solution was to copy the value to a new pointer using malloc and then memcpy and preserve the values like that.
I was logging as I was adding the pointers to the list. Between each log, the properties on the actor gets overwritten, so it was giving me the latest value on the property.