or I need to do in namespace myNameSpaces
?
Hi Alexa, sometimes it can make sense to step back again and rethink before getting deeper and deeper into trouble and ending up in a unecessarily growing complexity.
Just some thoughts here about your blueprint, from which you start. Before converting things 1:1 to C++, it could be worth to check, if the Blueprint code has potential for simplification.
From what I understand, you actually have an array of items you iterate through in order to spawn them at some location?/transform?, picked randomly from an array of available transforms you have stored in some Item Group.
Some points to potentially simplify the blueprint before going on to C++
- Why do you call a separate function within the GameMode to get a random item from that array? At least it looks like this function does no more than this. Apart from the fact, that a Blueprint Function Library could be a better place to put such functions in, the Array already has a function to get a random element.
- Next, you get some random array element and then use a loop to do a random again in case the element is already in a list of used locations to avoid, that it is set as spawn location again. Means, the nearer you come to the end of the list, the more iterations will be needed.
Have a look at this simplified blueprint version. I reduced your Items to a string array, also replaced the spawn by simple print string.
If things are transforms, naming them as such is useful, so I did not call it Location. This can avoid later trouble. Could even mean for your code, if you really need Locations only, make the arrays also Location type, saving memory and processing time.
Before starting the iteration, make a copy of the available transforms to choose from.
Simply get a random element from this and then reduce the array of choices by simply removing that element. No loop needed at all and guaranteed unique random spawn transforms.
The item array of course must not contain more elements than available spawn transforms.
In my case, it will return 0 bacause random does not find any entry in the empty array. Something that can be checked.
In your case, this will run into an endless loop - will create problems at runtime.
Just include "Algo/RandomShuffle.h"
.
I don’t understand why you got so fixated on this opertator ==
for FTransform
.
If you really need index of given FTransform
then TArray
already have function for customize equality operation.
// lambda for comparing transforms
auto IsEqual = [TransformToCompare](FTransform const& ArrayElem) -> bool {
static constexpr double Tolerance = 0.00001; // or whatever tolerance you want
return ArrayElem.Equals(TransformToCompare, Tolerance);
};
// finding index, INDEX_NONE if not exists
auto Index = MyArray.IndexOfByPredicate(IsEqual);
if (Index != INDEX_NONE) {
// founded
}
this idea is perfect, but I have 5 containers of static meshes in the ItemGroup class, and everytime it spawns with these 5 containers and returning the world space transforms of all containers, and later the static meshes is attached to the containers from an array of items and assign the fixed location from the array of locations to this ItemGroup Class, and the location assigned to it must not be re-used for another spawn of ItemGroup Class, just randomize the range by removing it array.num() -1 as the last index
from the random range, but the problem is the operator ==
needs to be overloaded.
OverLoad == FTransform but i don’t know how to do it, i also don’t know if unreal support namespaces or any other method to overload it will solve my issue
I tried and the header can’t be opened , can’t find this header is missing
Why not change UsedLocations to an array of indexes
TArray<int32> UsedLocations;
First this would take an index
void RandomLocation(TArray<FTransform> Available, FTransform& Location, int32& index)
{
index = FMath::RandRange(1, Available.Num() - 1);
Location = Available[index];
}
Then you can use it like this
FTransform Location;
int32 index;
while (true)
{
RandomLocation(Available, Location, index);
if(UsedLocations.Find(index) == -1)
{
UsedLocations.Add(index);
break;
}
}
and then how to convert index to FTransform to set SpawnLocation = index;
i did something like and it gives me duplicate locations
while (true)
{
RandomLocations(Available, Location, indexes);
if (UsedLocationss.Find(indexes) == -1)
{
SpawnLocation = Location;
UsedLocationss.Add(indexes);
break;
}
}
Can you show the modified RandomLocations ? Also try the same thing in blueprint and see if it’s still working as before.
I meant the RandomLocations function in C++ sorry
void AMyGamemode::RandomLocations(TArray<FTransform> Available, FTransform& Location, int32& index)
{
index = FMath::RandRange(1, Available.Num() - 1);
Location = Available[index];
}
I doubt it’s this but remove the 1 from this
index = FMath::RandRange(1, Available.Num() - 1);
Should be
index = FMath::RandRange(0, Available.Num() - 1);
Try moving this before the for loop, this way you only run that function once.
Available.Empty(); <------ Add this just in case
ItemGroupRef->GetAllTransforms(Available); //Here <-----
for (auto SpawnArrayElements : ItemsIDArr)
{
SpawnType = SpawnArrayElements.Type;
SpawnID = SpawnArrayElements.ID;
//Sequence 1
//Not here <-----------
do
Can you also print all locations to the log so we can confirm that there are unique locations in there ?
TArray<FTransform> Available;
for(const FTransform& value : Available)
{
UE_LOG(LogTemp, Warning, TEXT("Location: %s"), *value.GetTranslation().ToString());
}
I have this infinite loop in the UE_LOG , map not found, this is why I am always printing on the screen
I see one duplicate. You can print if you can, I think you added the log in the loop, try doing outside of the loop, with the previous change where we moved GetAllTransforms outside the loop too.
Available.Empty(); < ------Add this just in case
ItemGroupRef->GetAllTransforms(Available); //Here <-----
TArray<FTransform> Available;
for(const FTransform& value : Available)
{
UE_LOG(LogTemp, Warning, TEXT("Location: %s"), *value.GetTranslation().ToString());
}
for (auto SpawnArrayElements : ItemsIDArr)
{
SpawnType = SpawnArrayElements.Type;
SpawnID = SpawnArrayElements.ID;
//Sequence 1
//Not here <-----------
do
...retc
Can you try my previous post, there’s a chance your Available array has duplicate items and that would explain the issue.