Download

[C++ Blueprint function] How to pass a class/blueprint to a function and spawn it's instance?

I have a character C++ class and I have a blueprint-exposed function in it called Fire() that is supposed to take some parameters, including a Class/Blueprint of the projectile that I want to shoot, spawn that projectile, give it some velocity and return a pointer to this newly spawned instance.

However when i try to do it, the compiler complains that it expects a pointer type for when I am trying to pass in a ABaseProjectile class to it. What I essentially want is to have some kind menu similar to “Spawn Actor From Class” BP node, where I could select either a C++ class that I have or a BP class (or pass it from some other node), and then have the function spawn an instance of that class in the world. All the material I was able to find so far seems to hard-code the Projectile into C++, which isn’t something you typically want.

Here is code I have atm:

ThirdPersonCharacter.h



//constructor, etc.
protected:
        /* ... */
        UFUNCTION(BlueprintCallable, Category=Gameplay)
        ABaseProjectile* Fire(ABaseProjectile Projectile, const FVector Muzzle, bool Hitscan, const FVector OverrideVelocity);

public:
	/* ... */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Projectile)
	TSubclassOf<class ABaseProjectile> ProjectileClass;

ThirdPersonCharacter.cpp



ABaseProjectile* AThirdPersonCharacter::Fire(ABaseProjectile Projectile, const FVector Muzzle, bool Hitscan = false, const FVector OverrideVelocity = FVector()){	
	FVector Velocity, CameraLoc;
	FRotator CameraRot, MuzzleRot;
	GetActorEyesViewPoint(CameraLoc, CameraRot);
	if (OverrideVelocity == FVector::ZeroVector && Hitscan == false) { //if custom velocity vector was not passed and projectile isn't hitscan
		MuzzleRot = CameraRot;
		MuzzleRot.Pitch += 10.0f;
		Velocity = MuzzleRot.Vector(); //Set velocity to align with camera
	}
	else {
		Velocity = OverrideVelocity;
	}
	UWorld* const World = GetWorld();
	if (World) { //if witcher 3 not out yet
		FActorSpawnParameters SpawnParams;
		SpawnParams.Owner = this;
		SpawnParams.Instigator = Instigator;
		//I am not sure if this is required. The logic here is that by dynamically retrieving Projectile class, we get the pointer to proper subclass is necessary (e.g. if I have separate projectile for different weapons)
		ABaseProjectile* const SpawnedProjectile = World->SpawnActor<ABaseProjectile>(Projectile.GetClass(), Muzzle, MuzzleRot, SpawnParams);
		if (SpawnedProjectile != nullptr) {
			SpawnedProjectile->InitVelocity(Velocity);
			return SpawnedProjectile;
		}
		return nullptr;
	}
	else {
		return nullptr;
	}
}


Any suggestions for how I might achieve this?

UPDATE:
Ok I sort of got this thing moving with the following:


ABaseProjectile* AThirdPersonCharacter::Fire(**TSubclassOf<ABaseProjectile> Projectile**, const FVector Muzzle, bool Hitscan = false, const FVector OverrideVelocity = FVector()){

Ít’s not ideal though since I can only refer to C++ classes this way. I still appreciate any input, guys!

You should also be able to reference BP-Classes as long as these classes are derived from ABaseProjectile, since those BPs are of course also a Subclass of ABaseProjectile.
I’m using that in my project as well and it works fine for me.

Thanks, didn’t know that!

Hey I have encountered another issue with the above approach. When I try to actually spawn the instance of projectile using this line:


ABaseProjectile* const SpawnedProjectile = World->SpawnActor<ABaseProjectile>(Projectile->GetClass(), Muzzle, MuzzleRot, SpawnParams);

The pointer SpawnedProjectile is null and it doesn’t actually place anything. Any idea why this is happening?