Attach a static mesh to socket via C++

Relrin
Sat, 03 Sep 2016 19:50:52 +0000
Asset Creation

Hi everyone.

I’m trying to put a sword in the hand of monster instance via C++ code. So, we have this code, which compile successfully:

MeleeWeapon.h

#pragma once
#include "GameFramework/Actor.h"
#include "MeleeWeapon.generated.h"

class AMonster;

UCLASS()
class LEARNUE4CPPANDACTORS_API AMeleeWeapon : public AActor
{
    GENERATED_UCLASS_BODY()

    // The amount of damage attacks do
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = MeleeWeapon)
    float AttackDamage;

    // A list of things the melee weapon already hit this swing?
    // Ensures each thing sword passes thru only gets hit once.
    TArray<AActor*> ThingsHit;

    // Prevents damage from occurring on frames where the sword is not swinging.
    bool Swinging;

    // "Stop hitting yourself" - used to check if the actor holding
    // the weapon is hitting himself
    AMonster* WeaponHolder;

    // The sphere you collide with to pick item up
    UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Category = MeleeWeapon)
    UBoxComponent* ProxBox;

    UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Category = MeleeWeapon)
    UStaticMeshComponent* Mesh;

    UFUNCTION(BlueprintNativeEvent, Category = Collision)
    void Prox( AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult );

    void Swing();
    void Rest();
};

Monster.h

#pragma once
#include "GameFramework/Character.h"
#include "Monster.generated.h"

class AMeleeWeapon;

UCLASS()
class LEARNUE4CPPANDACTORS_API AMonster : public ACharacter
{
	GENERATED_UCLASS_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=MonsterProperties)
    float Speed;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=MonsterProperties)
    float HitPoints;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=MonsterProperties)
    int32 Experience;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=MonsterProperties)
    UClass* BPLoot;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=MonsterProperties)
    UClass* BPMeleeWeapon;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=MonsterProperties)
    float BaseAttackDamage;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=MonsterProperties)
    float AttackTimeout;

    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = MonsterProperties)
    float TimeSinceLastStrike;

    UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Category = Collision)
    USphereComponent* SightSphere;

    UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Category = Collision)
    USphereComponent* AttackRangeSphere;

    // The melee weapon instance (set if the character is using a melee weapon)
    AMeleeWeapon* MeleeWeapon;

	// Called every frame
	virtual void Tick(float DeltaSeconds) override;

    // Utility functions
    inline bool isInAttackRange(float d) {return d < AttackRangeSphere->GetScaledSphereRadius();}
    inline bool isInSightRange(float d) {return d < SightSphere->GetScaledSphereRadius();}

    virtual void PostInitializeComponents() override;
};

Monster.cpp

void AMonster::PostInitializeComponents()
{
    Super::PostInitializeComponents();

    // instantiate the melee weapon if a bp was selected
    if (BPMeleeWeapon)
    {
        MeleeWeapon = GetWorld()->SpawnActor<AMeleeWeapon>(BPMeleeWeapon, FVector(0), FRotator(0));

        if(MeleeWeapon)
        {
            MeleeWeapon->WeaponHolder = this;
            const USkeletalMeshSocket *socket = GetMesh()->GetSocketByName("RightHandSocket");
            socket->AttachActor(MeleeWeapon, GetMesh());  // <-- attempt to put a sword in the right hand
        }
        else
        {
            FString msg = GetName() + FString(" cannot instantiate meleeweapon ") + BPMeleeWeapon->GetName();
            GEngine->AddOnScreenDebugMessage(0, 5.f, FColor::Yellow, msg);
        }
    }
}

As a result after “play” mode Unreal Engine generates the following warning:

Warning AttachTo: '/Game/GameContent/UEDPIE_0_DefaultLevel.DefaultLevel:PersistentLevel.BP_Monster_7.CharacterMesh0' is not static  (in blueprint "BP_Monster"), cannot attach '/Game/GameContent/UEDPIE_0_DefaultLevel.DefaultLevel:PersistentLevel.BP_MeleeSword_C_28.Mesh' which is static to it. Aborting.

It leads to that I don’t see any weapon in the hands of monster. How can I fix this, without using blueprints? I saw solutions with blueprint nodes for this issue, but I want to connect all them together through C++ code.

11 posts - 1 participant