Can't set all 3 vector parameters to 100 (very weird)

Ok this has been driving me crazy!

I’m new to c++ but this really can’t be normal. I’m trying to create a vector and ran into an issue when adding 3x100 as the vector values…

FVector add_vector;
add_vector.X = float(100);
add_vector.Y = float(100);
add_vector.Z = float(100);

// or 

FVector add_vector = FVector(100.0f, 100.0f, 100.0f);

// none of them work! But if I change one 100 it does work!

// works: 

add_vector.X = float(100);
add_vector.Y = float(100);
add_vector.Z = float(101);

// works as well:

add_vector.X = float(200);
add_vector.Y = float(200);
add_vector.Z = float(200);

// and so on... 3 x 100 in a vector just doesn't work and creates an empty vector... I tried any variation of adding a hundred, 100.0, 100.000, 100.0f and so on...

Please tell me it’s a bug and I’m not losing my mind :d, would greatly appreciate your help

That was strange enough that I had to check.

FVector add_vector = FVector(100.0f, 100.0f, 100.0f);

Works fine for me.

Any chance the problem is where you are checking to see if it has been set?

This works for me.
Can you provide a little more code?

// Btw this is sufficient

add_vector.X = 100.f;

// or

add_vector.X = 100;

I’m trying to guess down below:

void AFoo::AddToVector(FVector add_vector)
{
  // Do you have a class variable called add_vector? if so you need to do
  this->add_vector.X...

 // Instead you are interacting with the argument add_vector

  // Like this
  this->add_vector += add_vector;
}

// Or are you looking at add_vector in debug mode after it has been released
// example

...
if (true)
{
    FVector add_vector;
    add_vector.X = float(100);
    add_vector.Y = float(100);
    add_vector.Z = float(100);
}
bool bHere_Add_Vector_Will_Be_Invalid = true;
...

I did some further checking and

FVector add_vector = FVector(100.0f, 100.0f, 100.0f);

does indeed work however, when inside a bool check it does not:

		float float_x = StartX;
		float float_y = StartY;
		float float_z = 100.0f;
		FVector new_vector = FVector(float_x, float_y, float_z);
		
		bool Contains = BlockArray.Contains(new_vector);
		
		if (!Contains){
			Newtiles = true;

			FVector add_vector = FVector(100.0f, 100.0f, 100.0f);

			StartArray.Add(add_vector);
		}

The bool check seems to work correctly though, since Newtiles is passed as true, it’s inside this if statement 3x100 does not work but any other combination does :slight_smile:

It must be something with the .Contains

float float_x = StartX;
float float_y = StartY;
float float_z = 100.0f;
FVector new_vector = FVector(float_x, float_y, float_z);

// just checking with a new TArray to see if it's a problem with a constant TArray, it's not though	
TArray<FVector> BlockArrayTwo = BlockArray;

// BlockArrayTwo.Add(new_vector);
// if i uncomment the above, and change the if(!Contained) check to true, it fires correctly and 3x100 vector is passed

bool Contained = BlockArrayTwo.Contains(new_vector);

// changed Contains to Contained, since I though it might be an illegal variable name
if (!Contained ){
	Newtiles = true;
	FVector add_vector = FVector(100.0f, 100.0f, 100.0f);
	StartArray.Add(add_vector);
}

Still nothing. Someting about the BlockArrayTwo.Contains(new_vector) seems to interact badly? Since if I do:

bool Contained = false;
if (!Contained ){
	Newtiles = true;
	FVector add_vector = FVector(100.0f, 100.0f, 100.0f);
	StartArray.Add(add_vector);
}

It does work… And I think I’m using .Contains right, since adding the vector to the array and checking gives a proper true bool. and still doesn’t explain why Contains is properly checked as false (since Newtiles is set correctly).

This still works for me. StartArray populates correctly (FVector add_vector is expected to be invalid after if’s end bracket } ).

It’s possible that you have a memory leak.

I would not check Start Location with .Contains

Here’s how I would do it:

bool AFoo::CheckListForValidStart(const FVector &Location, const TArray<FVector> &LocList) const
{
	for (auto Cmp : LocList)
	{
		if (FVector::Dist(Cmp, Location) < 2.0f)
			return false;
	}

	return true;
}

bool AFoo::IsValidStart(const FVector &Location)
{
	if (!CheckListForValidStart(Location, StartArray))
		return false;

	if (!CheckListForValidStart(Location, BlockArray))
		return false;

	return true;
}

void AFoo::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	float StartX = FMath::RandRange(-100, 100);
	float StartY = FMath::RandRange(-100, 100);

	float float_x = StartX;
	float float_y = StartY;
	float float_z = 100.0f;
	FVector new_vector = FVector(float_x, float_y, float_z);

	if (IsValidStart(new_vector))
	{
		StartArray.Add(new_vector);
	}
}

Are you doing a tile based game? guessing based on bool Newtiles

If that is the case I would change things to this:

Foo.h

static const float TileSize = 10.0f;

struct FTile
{
   // Single tile properties goes here
   // Example
   // ETileType TileType (Grass, Dirt, Sand)
   // int32 TileX
   // int32 TileY
};


UCLASS()
class AFoo : public AGameMode // GameMode would be a good place to add this code
{
  ...
public:
    virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;

    // I'm using this to add random start locations, for testing purpose
    virtual void Tick(float DeltaTime) override;

FVector GetTileLocation(int32 TileX, int32 TileY);

private:
  TArray<FTile *> StartArray;
  TArray<FTile *> BlockArray;

  FTile **Tiles;
  int32 TileWidth;
  int32 TileHeight;
  ...
};

Foo.cpp

AFoo::AFoo()
{
   Tiles = nullptr;
}

void AFoo::BeginPlay()
{
	Super::BeginPlay();

	TileWidth = 10;
	TileHeight = 10;
	Tiles = new FTile *[TileWidth];
	for (int32 X = 0; X < TileWidth; X++)
		Tiles[X] = new FTile[TileHeight];
}

void AFoo::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
	Super::EndPlay(EndPlayReason);

	if (Tiles)
	{
		for (int32 X = 0; X < TileWidth; X++)
			delete[] Tiles[X];
		delete[] Tiles;
		Tiles = nullptr;
	}
}

void AFoo::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	int StartTileX = FMath::RandRange(0, TileWidth-1);
	int StartTileY = FMath::RandRange(0, TileHeight-1);

	FTile *Tile = &Tiles[StartTileX][StartTileY];

	if (!BlockArray.Contains(Tile))
	{
		StartArray.AddUnique(Tile);
	}
}

FVector AFoo::GetTileLocation(int32 TileX, int32 TileY)
{
	FVector Loc;
	Loc.X = TileSize * TileX;
	Loc.Y = TileSize * TileY;
	Loc.Z = 100.f;
	return Loc;
}

That fixed it! Moving the boolcheck to a new function and switching .Contains to your suggested:

for (auto Cmp : LocList)
     {
         if (FVector::Dist(Cmp, Location) < 2.0f)
             return false;
     }
 
     return true;

got it working. So as you said, perhaps a memory leak due to bad code?

Anyways, thanks a lot for your extra suggestions (yeah it’s a tile based game), it got me thinking about changing some stuff and hopefully cleaning things up. Such a weird issue and would never have figured out the problem without this help.

Cheers!

Sorry, meant to say memory corruption

Here is a example how a memory corruption occurs:

{
FVector *TestVector = new FVector(0);
FVector *WatchTestVector = TestVector;

// Ok
TestVector->X = 20;

// BAD
TestVector += FMath::RandRange(50, 100);

// Now the TestVector points to an unwanted memory location

// Writing to unkown memory location, can cause crash
TestVector->X = 50;

// VERY BAD, deleting unkown memory
delete TestVector;

// Original TestVector was NOT deleted
}

Glad you got it working :), happy to help.