Weapon changes... I need help

Hi all,

I was trying to implement a weapon changing system (Between primary and secondary weapon).

Here is my .h code

UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Weapon")
		TSubclassOf<AWeaponRange> PrimaryWeapon;
	AWeaponRange* PrimaryWeaponInstance;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Weapon")
		TSubclassOf<AWeaponRange> SecondaryWeapon;
	AWeaponRange* SecondaryWeaponInstance;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Weapon")
		AWeaponRange* CurrentWeapon;

and here is my c++ constructor code:
CurrentWeapon = Cast<AWeaponRange>(PrimaryWeapon);

and here is the weapon changing code:

void ACharacter::ChangeWeapon()
{
	if (CurrentWeapon == PrimaryWeaponInstance)
	{
		CurrentWeapon->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, WeaponPrimarySocketName);
		//CurrentWeapon = nullptr;
		CurrentWeapon = Cast<AWeaponRange>(SecondaryWeapon);
		CurrentWeapon->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, WeaponCurrentSocketName);
	} 
	else
	{
		CurrentWeapon->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, WeaponSecondarySocketName);
		//CurrentWeapon = nullptr;
		CurrentWeapon = Cast<AWeaponRange>(PrimaryWeapon);
		CurrentWeapon->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, WeaponCurrentSocketName);
	}
}

The thing is my CurrentWeapon is an empty object inside the game but My primary weapon is an actor. I can shoot and all withh primary (For some reason).
How can I Set my CurrentWeapon to my primaryWeapon?

Thankk you in advance :slight_smile:

There may be other things happening but where is PrimaryWeaponInstance assigned?
Is it initially null?
Assigned in the constructor?

If CurrentWeapon is assigned the results of the Cast<>(PrimaryWeapon) and the instance is null or something entirely different then the code would be limited to the else clause.

Also, in ChangeWeapon do you need the first AttachToComponent calls in the if { . . . } and else { . . . }?
Could those be eliminated:

if (. . .)
{
CurrentWeapon = Cast(SecondaryWeapon);
CurrentWeapon->AttachToComponent( . . . )
}
else
{
CurrentWeapon = Cast<>(PrimaryWeapon);
CurrentWeapon->AttachToComponent(. . .);
}

This in your constructor is wrong
CurrentWeapon = Cast<AWeaponRange>(PrimaryWeapon);

PrimaryWeapon is a TSubClass which means it’s a path to some blueprint class that you would spawn first.

You should in your Begin play spawn the weapon using
TSubclassOf<AWeaponRange> PrimaryWeapon;

then assign the spawned weapon to CurretWeapon.

First of all thank you for replaying,
Yes the instances are assigned in the constructor. But I will delete them. They are for testing only.

The thing is, CurrentWeapon is null even though I have cast it to the Primary weapon in the constructor.

Why would I not need the attach? The player should change the weapon model too and put it in its correct position

Thank you very much for replaying.

The primary weapon has EditDefaultOnly and it has been assigned and spawned.
But maybe this is correct. I tried to cast it then spawn it. I will check with the code order. (I’m at work now :sweat_smile:)

Thank you again for replaying.
I will get back to you when I check it

You will do very, very little work inside a Constructor (mostly making sure that mandatory subcomponents of actors are existing, although there may be other things occasionally), and most of your initialization work should occur in BeginPlay. There may possibly be other situations where you might occasionally have need for something that occurs pre BeginPlay but post constructor… but… all in all… very rarely do you need to do much in constructor.

You might have a good look through Actor Lifecycle | Unreal Engine Documentation

1 Like

The below line doesn’t work. You’re essentially trying to convert a class to an object.

CurrentWeapon = Cast<AWeaponRange>(SecondaryWeapon);

You instead want an AWeaponRange object, which you have already defined as PrimaryWeaponInstance and SecondaryWeaponInstance.
The above line of code should look something like this instead:

CurrentWeapon = SecondaryWeaponInstance;

But you still need to instantiate those Weapon instances, which you haven’t shown in your code so I’m going to assume you haven’t yet. Here is an example:

void ACharacter::BeginPlay()
{
    FTransform Transform;

    // Spawn primary weapon.
    PrimaryWeaponInstance = GetWorld()->SpawnActorDeferred<AWeaponRange>(
			PrimaryWeapon, Transform, this);
    UGameplayStatics::FinishSpawningActor(PrimaryWeaponInstance, Transform);

    // Spawn secondary weapon.
    SecondaryWeaponInstance = GetWorld()->SpawnActorDeferred<AWeaponRange>(
			SecondaryWeapon, Transform, this);
    UGameplayStatics::FinishSpawningActor(SecondaryWeaponInstance, Transform);
}

Sorry for using Deferred Actor spawning, that’s all I had on hand since that’s what I primarily use. You can use GetWorld->SpawnActor but I’ve forgotten the syntax for it.

Thank you very much :slight_smile:

Thank you for sharing such a detailed answer :slight_smile:

Thank you all.
My issue has been resolved.

But how do I set this thread as “SOLVED”?