Unreal 4 C++ and Blueprint lessons

Screenshot of bluieprint & C++ code
A blueprint + C++ call sample – click for full size.

I’m working on an educational project called “Testing Grounds”. The goal here is to learn how UE4 creates a relationship between its components through Blueprint and C++. This is following guidance from this online course.

While the course does establish the parameters and provides example code to students, I’ve written the code myself, breaking down each call to properly understand its purpose.

// Main method that populates obstacles on the tile when it's created. Called from blueprint
void ATile::PlaceActors(TSubclassOf<AActor> Placeable, int MinPlaced, int MaxPlaced, float Radius)
{
	TArray<FVector> pointCollection;


	if (Placeable == nullptr)
	{
		UE_LOG(LogTemp, Warning, TEXT("Placeable class was null"))
			return;
	}
	int counter = FMath::RandRange(MinPlaced, MaxPlaced);
	for (size_t i = 0; i < counter; i++)
	{
		FVector* EmptyPoint = get_empty_point(Radius);
		if (EmptyPoint == nullptr) {
			UE_LOG(LogTemp, Warning, TEXT("Could not find valid place point"))
				return;
		}
		place_actor(Placeable, *EmptyPoint);
	}
}

void ATile::place_actor(TSubclassOf<AActor> Placeable, FVector PlacePoint)
{
	AActor* PlacedActor = GetWorld()->SpawnActor<AActor>(Placeable);
	PlacedActor->SetActorRelativeLocation(PlacePoint);
	PlacedActor->AttachToActor(this, FAttachmentTransformRules(EAttachmentRule::KeepRelative, false));
}

FVector* ATile::get_empty_point(float Radius) const
{
	FVector min = FVector(0, -2000, 0);
	FVector max = FVector(4000, 2000, 0);
	FBox* Box = new FBox(min, max);
	FVector* referenceToCandidate = nullptr;
	int AttemptCounter = 20;
	do
	{
		FVector candidatePoint = FMath::RandPointInBox(*Box);

		if (!cast_sphere(candidatePoint, Radius))
		{
			*referenceToCandidate = candidatePoint;
			break;
		}
		AttemptCounter--;
	} while (AttemptCounter > 0);

	return referenceToCandidate;
}

// Returns true if there's an obstacle within the radius.
bool ATile::cast_sphere(FVector Location, float Radius) const
{
	FHitResult hitResult;
	auto result = GetWorld()->SweepSingleByChannel(hitResult, Location, Location, FQuat::Identity, ECollisionChannel::ECC_GameTraceChannel2, FCollisionShape::MakeSphere(Radius));
	FColor Color;
	Color = result ? FColor::Red : FColor::Green;
	DrawDebugSphere(GetWorld(), Location, Radius, 36, Color, true);
	return result;
}

Quick side note on the code above: I still need to do an optimization pass throughout. Production code would be using an item pool, declaring variables outside of the loop and so forth.

In general, the relationship may seem tenuous diving into the code at first, but the binding that exists between them becomes clear when you see that a concept applies to both: inheritance.

Unreal-flavored C++ relies heavily on inheritance for extensibility. The idea is that the base functionality provided by base classes is not replaced but built on top of, bolted onto if you will, without fundamentally changing the type of object being manipulated.

Unreal is rife with this relationship, where a blueprint based on a base class is brought in by making a call to retrieve a component type (essentially a pointer) and then casting the value you get from de-referencing that pointer (a C++ concept at that) to the derived class. Essentially, you’re not changing the value of the reference — you’re reshaping a predefined pointer to capture more (always more) information than the original reference.

Testing Grounds is really the type of project that isn’t meant to be show-cased but learned from.

Unreal, as an engine, provides a lot of ready-built functionality that Unity relies on 3rd-party packages, or on a developer’s own programming skill, to provide.