-
무기 생성Game Programming/언리얼 2023. 10. 17. 14:44
무기 생성을 위해 Mesh, Flash Light, Point Light를 Weapon.cpp에서 구현했다.
Weapon.h
private: UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Light, meta = (AllowPrivateAccess = "true")); class UPointLightComponent* PointLight; private: void CreateMesh(); protected: void CreateLightFromBP(const FString& socketName); public: void TurnLight(bool bLight); void ToggleLight(); const class USkeletalMeshSocket* GetBarrelSocket(); FTransform GetSocketTransform();
Weapon.cpp
AWeapon::AWeapon() { PointLight = CreateDefaultSubobject<UPointLightComponent>(TEXT("WeaponsFlashlight")); PointLight->Mobility = EComponentMobility::Movable; PointLight->SetRelativeRotation(FRotator(0.0f, 0.0f, 0.0f)); PointLight->SetVisibility(false); PointLight->UpdateColorAndBrightness(); PointLight->AttenuationRadius = 200.f; PointLight->SetRelativeLocation(FVector(50.f, 0.f, 0.f)); PointLight->SetupAttachment(GetRootComponent()); }
케릭터 클래스에서 사용한 코드를 Weapon클래스로 가져왔다.
void AWeapon::CreateMesh() { USkeletalMesh* GunMesh = Cast<USkeletalMesh>(StaticLoadObject(USkeletalMesh::StaticClass(), NULL, TEXT("/Game/MyProject/Weapons/Meshs/SK_HeavyMachineGun.SK_HeavyMachineGun"))); ItemMesh->SetSkeletalMesh(GunMesh); SetRootComponent(ItemMesh); }
StaticLoadObject 함수를 사용해서 아이템 메시를 GunMesh로 변경했다.
void AWeapon::CreateLightFromBP(const FString& socketName) { UObject* LightObject = Cast<UObject>(StaticLoadObject(UObject::StaticClass(), NULL, TEXT("/Game/Voyager/Blueprints/BP_FlashLightWeapon.BP_FlashLightWeapon"))); UBlueprint* GeneratedLightBP = Cast<UBlueprint>(LightObject); if (!GeneratedLightBP) return; UClass* LightClass = GeneratedLightBP->StaticClass(); if (LightClass == NULL) return; UWorld* World = GetWorld(); FActorSpawnParameters SpawnParams; SpawnParams.Owner = this; SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; AActor* actor = World->SpawnActor<AActor>(GeneratedLightBP->GeneratedClass, GetActorLocation(), GetActorRotation(), SpawnParams); actor->AttachToComponent(ItemMesh, FAttachmentTransformRules::SnapToTargetNotIncludingScale, *socketName); }
actor->AttachToComponent(ItemMesh, FAttachmentTransformRules::SnapToTargetNotIncludingScale, *socketName);
AttachtoComponent 부분이 다른데, MyCharacter.cpp에서 GetMesh()를 사용했다면, ItemMesh를 사용했다.
FlashLightSocket을 추가로 만들어, HandLight를 부착했다.
FTransform AWeapon::GetSocketTransform() { const USkeletalMeshSocket* MeshSocket = ItemMesh->GetSocketByName("BarrelSocket"); return MeshSocket->GetSocketTransform(ItemMesh); }
FTransform을 Weapon으로부터 가져와야하기 때문에, BarrelSocket을 가져와 Transform을 읽어오는 함수를 따로 만들었다.
MyCharacter.cpp
UObject* WeaponObject = Cast<UObject>(StaticLoadObject(UObject::StaticClass(), NULL, TEXT("/Game/MyProject/Weapons/BaseWeapon/BaseWeapon.BaseWeapon"))); UBlueprint* GeneratedBP = Cast<UBlueprint>(WeaponObject); if (!GeneratedBP) return; UClass* WeaponClass = GeneratedBP->StaticClass(); if (WeaponClass == NULL) return; UWorld* World = GetWorld(); FActorSpawnParameters SpawnParams; SpawnParams.Owner = this; SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; AWeapon* DefaultWeapon = World->SpawnActor<AWeapon>(GeneratedBP->GeneratedClass, GetActorLocation(), GetActorRotation(), SpawnParams); if (DefaultWeapon == NULL) return; const USkeletalMeshSocket* HandSokcet = GetMesh()->GetSocketByName( FName("hand_rSocket")); if (!HandSokcet == NULL) return; HandSokcet->AttachActor(DefaultWeapon, GetMesh()); EquippedWeapon = DefaultWeapon;
블루 프린트 에셋에서 Weapon을 생성하여 hand_rSocket에 붙이는 코드. EquippedWeapon으로 생성한 무기를 저장하고 있는다.
if (EquippedWeapon) { const USkeletalMeshSocket* BarrelSocket = EquippedWeapon->GetBarrelSocket(); if (BarrelSocket) { FTransform SocketTransform = EquippedWeapon->GetSocketTransform(); FVector3d vecScale(1.f, 1.f, 1.f); SocketTransform.SetScale3D(vecScale);
Weapon으로부터 Transform을 읽어 MuzzleFlash와 Bullet 파티클을 만드는데 행렬 크기의 영향을 받지 않도록 스케일을 단위 스케일로 만들었다.
추가)
Spawn Weapon when using blueprint if (DefaultWeaponClass) { // Spawn the Weapon AWeapon* DefaultWeapon = GetWorld()->SpawnActor<AWeapon>(DefaultWeaponClass); // Get the Hand Socket const USkeletalMeshSocket* HandSokcet = GetMesh()->GetSocketByName( FName("hand_rSocket")); if (HandSokcet) { // Attach the Weapon to the hand socket RightHandSocket HandSokcet->AttachActor(DefaultWeapon, GetMesh()); } EquippedWeapon = DefaultWeapon; }
평소 TSubclassOf타입에 대해 궁금했는데,
유데미 강좌에서는 TSubclassOf 타입의 DefaultWeaponClass 변수를 사용하여 무기를 손에 붙였다.
TSubclassOf 타입이란 객체의 블루프린트 타입이라 이해하면 될 것 같다.
'Game Programming > 언리얼' 카테고리의 다른 글
무기 버리기 (1) 2023.10.17 아이템 Enum값 추가 (0) 2023.10.17 클래스 배열 PickupWdigetBP 바인딩 (1) 2023.10.17 Bind item name (1) 2023.10.16 Create Door (1) 2023.10.15