Spawning a character with C++

I want to spawn a character in a manner that I get a pointer of my character class after the spawning event happened. APlayerCharacter::StaticClass() won’t do it

Actors can be spawned from the UWorld (SpawnActor / Deferred) Deferred if you need to do some setup before finishing spawning. Spawning gives you a pointer to an instance of the class, not the class itself (which APlayerCharacter::StaticClass() already is)

APlayerCharacter* YourCharacter = World->SpawnActorDeferred<APlayerCharacter>(APlayerCharacter::StaticClass(), YourTransform, YourOwner, YourInstigator, ESpawnActorCollisionHandlingMethod::AlwaysSpawn);
if (IsValid(YourCharacter )) {
  // Do some setup
  // ....
  YourCharacter ->FinishSpawning(YourTransform);
}
1 Like

Alright. But is YourOwner a APlayerController Instance? I see the function requires an object of AActor type, and I am not really sure how to instantiate APlayerController in the way so I get AActor object. Either way, I just put nullptr for instigator and owner, but when I compile the project I get this ‘EXCEPTION_ACCESS_VIOLATION reading address 0x0000000000000208’. Should I make some casts or sth? I don’t really understand what to start from, UE makes trivial things way too hard to grasp (tho It might be just me being silly)

You get this if you use a pointer which is nullptr, which is invalid. You should do an IsValid() check on UObjects or test the pointer against nullptr. Check the log to see what variable gave the access violation so you can fix that. The world is retrievable, so is the owner, it depends on where you are trying to spawn from how to get it. Usually you can just GetWorld for world and if the thing you try to spawn from is not an actor you can do something like GetOwner (components) GetOwningPlayer (widgets) etc

You wrote about APlayerCharacter earlier. PlayerControllers are not usually managed like this. Either way, a character or a controller are both AActors so you can use the example I gave to spawn them.

1 Like
	FActorSpawnParameters sp;
	sp.bNoFail = true;
	sp.Name = "MyNewActor";		
	FTransform t = FTransform::Identity; // Transform spawn point
	 APlayerCharacter* character = GetWorld()->SpawnActor<APlayerCharacter>( APlayerCharacter::StaticClass(), sp);

If you want to spawn a blueprint derived from a c++ class then pass in a TSubclassOf in place of the class

so in header define

UPROPERTY(BlueprintReadWrite, EditAnywhere)
TSubclassOf<APlayerCharacter> passedActor;

and in cpp

// previous spawn contditions
 APlayerCharacter* character = GetWorld()->SpawnActor<APlayerCharacter>( passedActor, sp);

Well, I left some of spawnActor functions in GameMode constructor when the under the hood stuff is not initialized, that’s why I was getting access violation error. Kind of lame on my side. Thank you for answers, guys. Helped me clarify some things

You’re better off spawning actors after begin play. You need the world reference that needs to be initialized and running. You can’t spawn actors in the CDO.

The only exception is child actor components.

2 Likes

Just to add some info to that about spawning components:

You mean components can be spawned in the Constructor :slight_smile: which is not done with UWorld::SpawnActor but with:

CreateDefaultSubobject<USpringArmComponent>(TEXT("SomeSpringArm "));

Which works just like that but you might want to set up attachment etc.

1 Like