Attach weapon using C++

Im trying to follow the solution posted here for attached an item to my character:

but im getting an error trying to instantiate the class and call the functions. Not sure why its not working.
The error is “no default constuctor exists”
Here is how im trying to call:
void ALaserTagCharacter::BeginPlay() { AMyWeapon wep; wep.AttachWeaponToPawn(GetWorld()->GetFirstPlayerController()->GetPawn(), TEXT("HeroTPP")); }

You must use Unreal’s Actor Factories to spawn instances of classes derived from Actor, e.g.

FActorSpawnParameters spawnParams;
spawnParams.Owner = this;    
AMyWeapon* wep = GetWorld()->SpawnActor<AMyWeapon>(AMyWeapon::StaticClass(), spawnParams);

I’ll test that out when I get home, but I was thinking I would need the class of the rifle mesh as the SpawnActor param:
static ConstructorHelpers::FObjectFinder SpecifiedSpawnObject(TEXT(“Blueprint’/Game/ThingToSpawn.ThingToSpawn’”));
WhatToSpawn = (UClass*)SpecifiedSpawnObject.Object->GeneratedClass;

I was thinking WhatToSpawn would be the param to pass into SpawnActor, otherwise how will it know which mesh to spawn?

By the way, I have no idea how you guys are posting your code like that. There is no documentation for “Answerhub”. Im using the code block, but it looks like crap.

With this code:

[CODE]
void ALaserTagCharacter::BeginPlay()
{
	FActorSpawnParameters spawnParams;
	spawnParams.Owner = this;

	AMyWeapon* wep = GetWorld()->SpawnActor<AMyWeapon>(AMyWeapon::StaticClass(), spawnParams);
	if (wep)
	{
		wep->AttachWeaponToPawn(GetWorld()->GetFirstPlayerController()->GetPawn(), TEXT("HeroTPP"));
	}
}
[/CODE]

I’m able to see the MyWeapon class show up in the scene outliner when I run the game, but there is no weapon mesh. I think I may be using the AttachWeaponToPawn method incorrectly, or I misunderstood its intended purpose.

Ok, so if your weapon is properly spawned and its mesh created properly, but it is not attached correctly to the pawn, it should still be spawned in the world - it just won’t follow you around. I assume this is not the case as you would probably see it floating there in space.

Now, the problem is most probably with the SkeletalMeshComponent on the weapon class. Please note that you MUST have some basic root object on the weapon class to which you can attach the WeaponMesh, e.g. my weapon class constructor looks like this:

APWNWeapon::APWNWeapon(const class FPostConstructInitializeProperties& PCIP)
	: Super(PCIP)
{		
	// We must tick
	PrimaryActorTick.bCanEverTick = true;
	
	// Dummy root component
	RootComponentDummy = PCIP.CreateDefaultSubobject<USkeletalMeshComponent>(this, TEXT("RootComponentDummy"));
	RootComponent = RootComponentDummy;

	// Weapon Comp
	Weapon = PCIP.CreateDefaultSubobject<USkeletalMeshComponent>(this, TEXT("Weapon"));
    Weapon ->AttachParent = RootComponentDummy;	

}

Please note that “Weapon” is my SkeletalMeshComponent for the weapon mesh.

There are now a number of things you can check:

  • Make sure that you are attaching the weapon mesh to the weapon class properly
  • Make sure that the mesh isn’t tiny or massive
  • Make sure that the weapon class and mesh are not hidden

How would you instantiate that weapon class and how would you assign that object to the weapon mesh?

Apologies - regarding the Root component: This is only required if you want to programmatically create a relative offset for your mesh. In your case you could simply set RootComponent = Weapon after creating the subobject, and ignore the RootComponentDummy part of my comment.

You are already creating an instance of the weapon class with:

AMyWeapon* wep = GetWorld()->SpawnActor<AMyWeapon>(AMyWeapon::StaticClass(), spawnParams);

My last two comments refer to how you create a SkeletalMeshComponent on your weapon class to display the mesh.

The skeletal mesh can be set as follows (please note that I do it outside of the constructor):

// Find the Mesh
USkeletalMesh* WeaponSkelMesh = Cast<USkeletalMesh>(StaticLoadObject(USkeletalMesh::StaticClass(), NULL, TEXT("pathToYourMeshInContentBrowser")));

// Set mesh
Weapon->SetSkeletalMesh(WeaponSkelMesh);

As for the AnswerHub code block, it only works nicely when posting an answer, not in comments, but in any case there’s a little icon that looks like this:

101
100

You use this to post code.

Im still not getting any mesh, in the scene. Here is the code:

http://pastebin.com/EgJ0JMRu

You can remove the dummy root component, i.e. replace your constructor with:

        AMyWeapon::AMyWeapon(const class FPostConstructInitializeProperties& PCIP)
            : Super(PCIP)
        {
            // We must tick
            PrimaryActorTick.bCanEverTick = true;
       
            // Weapon Comp
            Weapon = PCIP.CreateDefaultSubobject<USkeletalMeshComponent>(this, TEXT("Weapon"));
            RootComponent = Weapon;
        }

If you are not getting any errors, the only other things I can think of:

  • Make sure that the mesh isn’t tiny or massive - this could cause you not to see it.
  • Make sure that the weapon class and mesh are not hidden

Also, as you are doing proper checks for null pointers, you should also check whether all of the code is executed, e.g. in AttachWeaponToPawn(), if ArmMesh is null, it won’t execute the attach code, but will exit gracefully (i.e. not raise an error).

Ok Im trying to trouble shoot segments of this code, I found that Im not getting the correct name from my mesh.
In the code im checking for the name of a USkeletalMeshComponent:

if (playerMesh->GetName() == ComponentName)

The GetName() should be returning “HeroTPP”, but instead it is returning “CharacterMesh0”. So I change the code to check for “CharacterMesh0” and then the MyWeapon class sucessfully attached to the Character.

The weapon mesh spawns pointing straight down, relative to the character, Im not sure how to get it pointed in the correct direction.

EDIT I was able to do a local rotate in the editor of the weapon socket, now its pointing in the correct direction.

How can I check for the real name instead, which is “HeroTPP”?
I tried to use GetReadableName() name and that gave me something closer; it returned “MyCharacter_C_12.CharacterMesh0 HeroTPP”.