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.