Armour and level swap

As the title says what’s the best way to keep equipped the armour your wearing when you switch/ reopen levelz

The best way to persist data across levels is by storing it in your GameInstance. You can have your Pawn query the game instance on BeginPlay.

For example, if you keep your data on the equipped armor in a custom struct called FEquippedArmour you can do something like this:

//within your MyGameInstance.h

UCLASS(Blueprintable, BlueprintType)
class MYGAME_API MyGameInstance : public UGameInstance {
    GENERATED_BODY()

    public:

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Character State")
    FEquippedArmour EquippedArmour;

};

//within your MyPawn.h

UCLASS(Blueprintable, BlueprintType)
class MYGAME_API AMyPawn : public APawn {
    GENERATED_BODY()

    // Called when the game starts or when spawned
    virtual void BeginPlay() override;

    UFUNCTION(BlueprintCallable, , Category = "State|Equipment")
    void ApplyEquippedArmour();

    UFUNCTION(BlueprintCallable, , Category = "State|Equipment")
    void StoreEquippedArmour();

};


//within MyPawn.cpp

void AMyPawn::BeginPlay()
{
    ApplyEquippedArmour();

}

void AMyPawn::ApplyEquippedArmour()
{
    UMyGameInstance* GameInstance = UGameplayStatics::GetGameInstance(GetWorld());
    if (GameInstance)
    {
        FEquippedArmour& Armour = GameInstance.EquippedArmour;
        ApplyHelmet(Armour.Helmet);
        ApplyBreastplate(Armour.Breastplate);
        ApplyShield(Armour.Shield);
        ...
    }

}

void AMyPawn::StoreEquippedArmour()
{
    UMyGameInstance* GameInstance = UGameplayStatics::GetGameInstance(GetWorld());
    if (GameInstance)
    {
        GameInstance.EquippedArmour = FEquippedArmour(GetHelmet(), GetBreastplate(), GetShield()...);

    }

}

Would that still work if the weapon was a socketed static mesh and the armour is a non socketed skeletal mesh?

Or could i possibly see it as a blueprint function, alot of that list is very confusing

It doesn’t matter how you are storing the armour data, I just provided that detail as a generic example since I have no idea how you are storing or controlling your Armour; the important part is that you store the data in the GameInstance.
When your Pawn is built, it can then retrieve that data from the GameInstance to make its armour. Before you exit your level, you’ll want to update the data within GameInstance with the current Pawn armour data.

GameInstance persists between levels, your Pawn and GameMode do not.

Create a new BP Object based on the GameInstance class (or, if you already havea custom GameInstance use that).

Open the BP editor for your custom GameInstance.

Add variables that correspond to the data you want to persist between levels; however you are storing your armour information create those.

Within Edit->ProjectSettings change the GameInstance class to your new custom GameInstance.

Within your Pawn, in the construction script, GetGameInstance pass the return value to CastToClass using your new GameInstance BP. You can then access the armour data from the returned value of that, if the cast is successful. You can assign those values to your armour data within your pawn.

When you are exiting the level, you will want to call a method in your Pawn that gets the GameInstance again and sets the current value of your armour in your pawn to the armour value(s) in the GameInstance.

If this is confusing, I’ll set up a mock-up in BP and post screengrabs when I get a chance. Might be a couple hours though.

lol iv been tryin to find some info on this for a week mate with no luck so another few hours for an answer is easy :stuck_out_tongue:

Tell me a bit more about how you have the armour set up currently. Is this stored in your pawn, or character? Is it in your player controller? What types of data are you storing? Do you just need access to the mesh being used for visual data, or do you need the name of the armor or any stats to go with it?
How is the current armour being applied to the pawn, do you have an armoury with all available armour in the game, or are things stored individually?

This is how my setup is for my characters armour, its just a single mesh for the full armour in my inventory widget

the setup for my weapons are abit different

i had to use this method for the weapons so i could use their collision capsules for damage

the iron sword is an empty static mesh attached to my characters hand socket
the chest is a skeletal mesh set up as you see above but its not socketed

Is PlayerRef a Pawn, a Character, your PlayerController?

The ArmourActive? boolean, how is that assigned? Does that only exist within your widget?

The ItemData members of your Inventory array, are they structs?

Where is the Inventory currently stored? Is it part of you widget?

What does the SetArmour method look like?

Is this structure based on a template, or tutorial, or is this your custom creation?

its a ref to my game character

that boolean is only in the widget

yep its an array from a struct

the struct was based on a tutorial vid i got from youtube

Long story short, you’re going to want to move the Inventory variable, and your ArmourActive and WeaponActive booleans into your custom GameInstance; then have your widget/character use those values. You can do it in exactly the same way, just pull the values from the GameInstance rather than from the Character reference.

I’d suggest moving the SetArmour and SetWeapon methods into your MyCharacter class, rather than in the widget. Then just have the button clicks call those methods. This will keep everything a bit cleaner, and avoid having to do unnecessary casts.

Then in your MyCharacter class, either in the Construction Script, or after BeginPlay, call SetArmour and SetWeapon.

In the OnClicked even for Button_106, you can get rid of the GetPlayerCharacter and CastTomy_Character nodes.
Have the False exec line from the Branch go directly into SpawnActorFromSwordBP; then use your PlayerRef value as the Target for the Mesh going into InParent on AttachActorToComponent.

You’re also going to have to replace AttachActorToComponent as that method is deprecated. AttachToComponent is the valid replacement.

so in my inventory widget whe giving the buttons functions just cast it to the gameinstance instead of my character

First move the SetArmour method into your MyCharacter blueprint, and have all the functionality there. You can remove the Cast entirely when that is done.

Then create two new methods, one for equipping armour and one for equipping a weapon; and move the functionality you have in your button click events into them.

In your widget, keep the same PlayerRef, but have your button clicks call your new EquipArmour and EquipWeapon methods.

I’ll give you pics in a bit.

so Instead of using the buttons on the widget since im moving them to my character bp should i just use a custom event instead like “equip armour” or something?

OK i moved all the weapon and armour settings and variables to my character bp and everything is all working as before, what do i need to do now to keep wearing the stuff when i switch or reopen levels?