Im not being able to compile it. Getting the error:
error : Inappropriate '’ on variable of type ‘float’, cannot have an exposed pointer to this type.*
Is this specific to unreal?
TArray<float*> AHISM_Test::GetAllInstancesAddresses(UHierarchicalInstancedStaticMeshComponent* HISM_L, int32 InstanceIndex, int32 CustomDataIndex) {
// Get the addresses of all the elements
TArray<float*> Addresses;
for (int32 i = 0; i < HISM_L->GetInstanceCount();++i) {
float* Address = &HISM_L->PerInstanceSMCustomData[i * HISM_L->NumCustomDataFloats + CustomDataIndex];
Addresses.Add(Address);
}
// Return the address
return Addresses;
}
Shouldnt this return the addresses of the instances?
Though the following works, changing the float by pointer, thats not what i need. I need to get the pointers to all the units. So to work with them later:
void AHISM_Test::ChangeCustomValueByPointer(UHierarchicalInstancedStaticMeshComponent* HISM_L, int32 InstanceIndex, int32 CustomDataIndex) {
// Get the address of the element
float* Address = &HISM_L->PerInstanceSMCustomData[InstanceIndex * HISM_L->NumCustomDataFloats + CustomDataIndex];
// Return the address
*Address = 50;
}
Looking at the source of the function PerInstanceSMCustomData you can see it returns a TArray of floats.
A pointer is for when you need to reserve a specific amount of memory blocks for an instance of an object or array length.
There is no need you you to be using & before your HISM_L. The reference is useless if you are not planning on modifying it in-place.
You are not even passing it by reference in the function, so the variable is a local copy.
Try
TArray<float> AHISM_Test::GetAllInstancesAddresses(UHierarchicalInstancedStaticMeshComponent* HISM_L, int32 InstanceIndex, int32 CustomDataIndex) {
// Get the addresses of all the elements
TArray<float> Addresses;
for (int32 i = 0; i < HISM_L->GetInstanceCount(); ++i) {
float Address = HISM_L->PerInstanceSMCustomData[i * HISM_L->NumCustomDataFloats + CustomDataIndex];
Addresses.Add(Address);
}
// Return the address
return Addresses;
}
Or you could retrieve the address allocated for the whole TArray via
Though this is not working either. No operator “=” matches.
I dont understand why we can get pointers to the float address. But we cant return them from a function…
If this works^ . Then why cant we return an array of pointers to our floats from a function?
I need to store them in an array or map, so i can access them in different places.
If this is not possible what are my options to work with these values in a bunch of different functions?
There isn’t a variable in blueprints that could represent the float* that is why it’s not working. You could on the other hand just modify the data via passing in a reference and do the modifications in pure c++.
Explain maybe why you need the pointers to the specific data in your blueprints and there is another way to get around the problem?
I need to get all the instances of HISM components of different actors into 1 array, and control them that way. In my context controlling one HISM of each actor is causing issues. So the only solution is to have an array of all of them.
void AHISM_Test::GetAllInstancesAddresses(UHierarchicalInstancedStaticMeshComponent* HISM_L, int32 InstanceIndex, int32 CustomDataIndex, TArray<float*>& InstancesPtrs) {
// Get the addresses of all the elements
for (int32 i = 0; i < HISM_L->GetInstanceCount(); ++i) {
float* Address = &HISM_L->PerInstanceSMCustomData[i * HISM_L->NumCustomDataFloats + CustomDataIndex];
InstancesPtrs.Add(Address);
}
// Return the address
}
That works to change the float right there. But not later. So im not being able to store the pointers anywhere.
Also you are using a reference to HISM_L, which means the function must pass a reference to the component, and that makes it drop in performance.
The only way to fix this is to get the addresses of all the instances and their floats stored in an array so to skip that.
And then change them on a tick directly in the addresses with just 1 loop.
Else, accessing each different HISM will cause a huge drop in performance. i tested this many times.
HISM is great. But only if you have 1 HISM type. The moment you need more HISM components, you will see its drop performance a lot by trying to animate in different hisms.
This will not be an issue if we get an array of pointers and change them directly in their address.
Which is something im capable of if necessary in assembly. But im trying to avoid that.
The base address of the PerInstanceSMCustomData TArray is not guaranteed to be consistent, storing pointers to them is probably not the best idea.
That’s a pointer to the HISM component, the float* is being set to the address of the TArray at that index. That should write/read directly into the TArray itself - it should be permanent.
I don’t think you could get it much faster than what I’ve put for setting the data - Visual Studio will optimize each of your references to those floats into a direct memory store/load - the ‘myArrayAtCorrectPosition’ variable will be optimized out.
Regarding the amount of HIMCs - maybe you could set the data on one set each tick rather than the lot at once?
private:
TArray<float*> cachedTArrayAddresses;
and pass in the the hismcomp storing it’s
float* f = &HISM_L[j]->PerInstanceSMCustomData[i];
to cachedTArrayAddresses
Then you can mass update it via a function where you just pass in the new float and then itterate over cachedTArrayAddresses setting a value in the loop.
No you cannot expose it to blueprints. Delete UPROPERTY(EditAnywhere, BlueprintReadWrite)
it might compile with just UPROPERTY() but definitely not EditAnywhere or BlueprintReadWrite
Edit: no any type of uproperty exposes it to blueprints so it might get GC only way to keep it save would probably be a static var in a library
It worked. Thanks so much.
At some point i was about to quit. But finally your tips got me there.
There’s only one detail i was missing and thought it was not working.
Even though we are updating the Instance float directly by pointer it still needs the
HISM->MarkRenderStateDirty().
Just in case someone comes here with the same question.
For example this one doesnt work. I dont know why.
I tried on a different project too, and debugged it and the address seems correct, but it doesnt update it, outside the beginplay.
It could be because like someone said the pointers to these floats are something temporary.
Or is there something im missing? Its just weird that it works on one place, but it doesnt work anywhere else.
I send you my project. It has a small sketch level with an actor that has HISM for test, its version 4.27.2 :
Seems the link is sending me to the homepage of https://wetransfer.com. Is it restricted to logged in users?
If you are modifying custom data then it may be only for the zero index.