총(StaticMesh)의 부모 컴포넌트 생성
UCLASS(config=Game)
class ASeSAC_NetworkCharacter : public ACharacter
{
GENERATED_BODY()
// 총을 자식으로 붙일 컴포넌트
UPROPERTY(VisibleAnywhere)
class USceneComponent* GunComp;
ASeSAC_NetworkCharacter::ASeSAC_NetworkCharacter()
{
GunComp = CreateDefaultSubobject<USceneComponent>(TEXT("GunComp"));
GunComp->SetupAttachment(GetMesh(), TEXT("GunPosition"));
}
Socket 생성해서 SetupAttachment에서 해당 Socket의 이름이 존재하면 그 소켓에 Attach
총 잡기 (TakePistol)
public:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input)
UInputAction* TakePistolAction;
// 필요 속성 : 총 소유 여부
bool bHasPistol = false;
// 소유중인 총
UPROPERTY()
AActor* OwnedPistol = nullptr;
// 총 검색 범위
UPROPERTY(EditAnywhere, Category = "Gun")
float DistanceToGun = 200;
// 월드에 배치된 총들
UPROPERTY()
TArray<AActor*> PistolActors;
void TakePistol(const FInputActionValue& Value);
// 총을 컴포넌트에 붙이기
void AttachPistol(AActor* InPistol);
void ASeSAC_NetworkCharacter::BeginPlay()
{
Super::BeginPlay();
// 총 검색
TArray<AActor*> allactors;
UGameplayStatics::GetAllActorsOfClass(GetWorld(), AActor::StaticClass(), allactors);
for (const auto& actor : allactors)
{
if (actor->GetName().Contains("BP_Pistol"))
PistolActors.Add(actor);
}
}
게임이 시작될 때, 월드에 존재하는 모든 Pistol을 받아와 저장
void ASeSAC_NetworkCharacter::TakePistol(const FInputActionValue& Value)
{
// 총을 소유하지 않았다면 일정 범위 안에 있는 총을 잡는다.
// 필요 속성 : 총을 소유하고 있는지, 소유중인 총, 총을 잡을 수 있는 범위
// 1. 총을 잡고 있지 않다면
if (bHasPistol == true) return;
// 2. 월드에 있는 총을 모두 찾는다.
for (const auto& pistol : PistolActors)
{
// 3. 총의 주인이 있다면 그 총은 검사하지 않는다.
// 총이 없어질 수 있는 경우가 있다면 NULL체크 필요
if (pistol->GetOwner() != nullptr) continue;
// 4. 총과의 거리를 구한다.
float distance = FVector::Dist(GetActorLocation(), pistol->GetActorLocation());
// 5. 총이 범위 안에 있다면
if (distance <= DistanceToGun)
{
// 6. 소유중인 총으로 등록한다.
OwnedPistol = pistol;
// 7. 총의 소유자를 자신으로 등록한다.
pistol->SetOwner(this);
// 8. 총 소유 상태를 변경한다.
bHasPistol = true;
// 9. 해당 총을 붙인다.
AttachPistol(pistol);
break;
}
} // for pistol
}
void ASeSAC_NetworkCharacter::AttachPistol(AActor* InPistol)
{
auto mesh = InPistol->GetComponentByClass<UStaticMeshComponent>();
mesh->SetSimulatePhysics(false);
mesh->AttachToComponent(GunComp, FAttachmentTransformRules::SnapToTargetNotIncludingScale);
}
총 버리기 (Release Pistol)
public:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input)
UInputAction* ReleasePistolAction;
// 총 놓기 입력 처리 함수
void ReleasePistol(const FInputActionValue& Value);
// 총을 컴포넌트에 붙이기
void DetachPistol(AActor* InPistol);
// 총 쏘기 입력 액션
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input)
UInputAction* FireAction;
// 총 쏘기 처리 함수
void Fire(const FInputActionValue& Value);
// 피격 파티클
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Gun)
class UParticleSystem* GunEffect;
void ASeSAC_NetworkCharacter::ReleasePistol(const FInputActionValue& Value)
{
// 총을 잡지 않았을 때는 처리하지 않는다.
if (bHasPistol == false) return;
// 총 소유시
if (OwnedPistol)
{
DetachPistol(OwnedPistol);
// 미소유로 설정
bHasPistol = false;
OwnedPistol->SetOwner(nullptr);
OwnedPistol = nullptr;
}
}
void ASeSAC_NetworkCharacter::DetachPistol(AActor* InPistol)
{
auto mesh = InPistol->GetComponentByClass<UStaticMeshComponent>();
mesh->SetSimulatePhysics(true);
mesh->DetachFromComponent(FDetachmentTransformRules::KeepRelativeTransform);
}
총 쏘기 (Fire)
public:
// 총 쏘기 입력 액션
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input)
UInputAction* FireAction;
// 총 쏘기 처리 함수
void Fire(const FInputActionValue& Value);
// 피격 파티클
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Gun)
class UParticleSystem* GunEffect;
void ASeSAC_NetworkCharacter::Fire(const FInputActionValue& Value)
{
// 총을 들고 있지 않을때는 처리하지 않는다.
if (!bHasPistol) return;
// 총쏘기 애니메이션 재생
auto anim = Cast<UCNetPlayerAnimInstance>(GetMesh()->GetAnimInstance());
anim->PlayFireAnimation();
// 총쏘기
FHitResult hitInfo;
FVector startPos = FollowCamera->GetComponentLocation();
FVector endPos = startPos + FollowCamera->GetForwardVector() * 10000;
FCollisionQueryParams params;
params.AddIgnoredActor(this);
bool bHit = GetWorld()->LineTraceSingleByChannel(hitInfo, startPos, endPos, ECC_Visibility, params);
if (bHit)
{
// 맞는 부위에 파티클 표시
UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), GunEffect, hitInfo.Location);
}
}
UCLASS()
class SESAC_NETWORK_API UCNetPlayerAnimInstance : public UAnimInstance
{
GENERATED_BODY()
public:
// 총쏘기에 사용할 몽타주
UPROPERTY(EditDefaultsOnly, Category = "Anim")
class UAnimMontage* FireMontage;
// 총쏘기 애니메이션 재생
void PlayFireAnimation();
}
void UCNetPlayerAnimInstance::PlayFireAnimation()
{
if (bHasPistol and FireMontage)
Montage_Play(FireMontage);
}
캐릭터의 위아래 회전 특정 수치에 고정
public:
// 회전값 기억할 변수
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "MyAnimSettings")
float PitchAngle;
void UCNetPlayerAnimInstance::NativeUpdateAnimation(float DeltaSeconds)
{
Super::NativeUpdateAnimation(DeltaSeconds);
if (player)
{
// 회전값 적용
PitchAngle = -player->GetBaseAimRotation().GetNormalized().Pitch;
PitchAngle = FMath::Clamp(PitchAngle, -60, 60);
}
}
MainUI
UCLASS(config=Game)
class ASeSAC_NetworkCharacter : public ACharacter
{
GENERATED_BODY()
public:
// 사용할 위젯 클래스
UPROPERTY(EditDefaultsOnly, Category = "UI")
TSubclassOf<class UCMainUI> MainUIWidget;
// MainUIWidget으로 부터 만들어진 인스턴스
UPROPERTY()
class UCMainUI* MainUI;
// UI초기화 함수
void InitUIWidget();
}
void ASeSAC_NetworkCharacter::InitUIWidget()
{
if (MainUIWidget)
{
MainUI = Cast<UCMainUI>(CreateWidget(GetWorld(), MainUIWidget));
MainUI->AddToViewport();
MainUI->ShowCrossHair(false);
}
}
void ASeSAC_NetworkCharacter::DetachPistol(AActor* InPistol)
{
auto mesh = InPistol->GetComponentByClass<UStaticMeshComponent>();
mesh->SetSimulatePhysics(true);
mesh->DetachFromComponent(FDetachmentTransformRules::KeepRelativeTransform);
MainUI->ShowCrossHair(false);
}
void ASeSAC_NetworkCharacter::AttachPistol(AActor* InPistol)
{
auto mesh = InPistol->GetComponentByClass<UStaticMeshComponent>();
mesh->SetSimulatePhysics(false);
mesh->AttachToComponent(GunComp, FAttachmentTransformRules::SnapToTargetNotIncludingScale);
MainUI->ShowCrossHair(true);
}
기본적으로 CrossHair는 꺼둔 상태에서 총을 들면 보여주고, 총을 버리게되면 다시 꺼두는 방식으로 설정
'Development > Unreal Lab' 카테고리의 다른 글
[SeSAC, Unreal Network] 2025. 04. 07 (0) | 2025.04.07 |
---|---|
[SeSAC, Unreal Network] 2025. 04. 04 (0) | 2025.04.04 |
[SeSAC, Unreal Network] 2025. 04. 02 (0) | 2025.04.02 |
[SeSAC, Unreal] 2025. 03. 18 (0) | 2025.03.18 |
[Unreal Graphics] 효과,이펙트 (Effect) (0) | 2025.03.06 |