KLingo Project Documentation 1.0.0
Unreal Engine 5.6 C++ Project Documentation
로딩중...
검색중...
일치하는것 없음
UOrbitalBehaviorComponent.cpp
이 파일의 문서화 페이지로 가기
1// Copyright (c) 2025 Doppleddiggong. All rights reserved. Unauthorized copying, modification, or distribution of this file, via any medium is strictly prohibited. Proprietary and confidential.
2
8#include "GameFramework/Actor.h"
9
11UOrbitalBehaviorComponent::UOrbitalBehaviorComponent()
12{
13 PrimaryComponentTick.bCanEverTick = true;
14}
15
17void UOrbitalBehaviorComponent::BeginPlay()
18{
19 Super::BeginPlay();
20
21 if (AActor* Owner = GetOwner())
22 {
23 AnchorLoc = Owner->GetActorLocation();
24 }
25}
26
28void UOrbitalBehaviorComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
29{
30 Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
31 Tick_TargetFloat(DeltaTime);
32}
33
35void UOrbitalBehaviorComponent::Tick_TargetFloat(float DeltaTime)
36{
37 AActor* Owner = GetOwner();
38 if (!Owner || !IsValid(TargetActor) || DeltaTime <= 0.f)
39 return;
40
41 // 1) 타겟 중심(높이 오프셋 포함)
42 const FVector TargetCenter = TargetActor->GetActorLocation() + FVector(0.f, 0.f, HeightOffset);
43
44 // 2) 앵커 보간(타겟이 바뀌거나 움직여도 부드럽게 따라감)
45 AnchorLoc = FMath::VInterpTo(AnchorLoc, TargetCenter, DeltaTime, AnchorLerpSpeed);
46
47 // 3) 시간 누적(상하 바운스 / 공전 각도)
48 TimeAcc += DeltaTime;
49
50 // IdleYawSpeedDegPerSec를 공전 각속도로 사용
51 AngleDeg = FMath::Fmod(AngleDeg + IdleYawSpeedDegPerSec * DeltaTime, 360.f);
52 const float Rad = FMath::DegreesToRadians(AngleDeg);
53
54 // 4) 궤도 오프셋(SinCos 1회 호출)
55 float s = 0.f, c = 0.f;
56 FMath::SinCos(&s, &c, Rad);
57
58 // 상승/하강 바운스
59 const float Bob = FMath::Sin(TimeAcc * (2.f * PI) * FMath::Max(0.f, BobSpeed)) * BobAmplitude;
60
61 const FVector Offset(c * OrbitRadius, s * OrbitRadius, Bob);
62 const FVector NewLoc = AnchorLoc + Offset;
63
64 // 5) 위치 적용(충돌 고려가 필요하면 true로 변경)
65 Owner->SetActorLocation(NewLoc);
66
67 // 6) 플레이어를 바라보게(수평 Yaw만 적용, 근접 발산 방지)
68 if (IsValid(PlayerActor))
69 {
70 const FVector ToPlayer = PlayerActor->GetActorLocation() - NewLoc;
71 if (!ToPlayer.IsNearlyZero(1.f))
72 {
73 const float DesiredYaw = ToPlayer.Rotation().Yaw;
74 Owner->SetActorRotation(FRotator(0.f, DesiredYaw, 0.f));
75 }
76 }
77 else
78 {
79 // PlayerActor가 없으면 천천히 자체 회전(원한다면 주석 해제)
80 const FRotator AddYaw(0.f, IdleYawSpeedDegPerSec * DeltaTime, 0.f);
81 Owner->AddActorWorldRotation(AddYaw);
82 }
83}
84
86void UOrbitalBehaviorComponent::SetTargetActor(AActor* NewTarget, bool bSnapAnchor, bool bPreserveOrbitPhase)
87{
88 // 동일 대상이면 무시
89 if (TargetActor == NewTarget)
90 return;
91
92 AActor* Owner = GetOwner();
93 const FVector OwnerLoc = (Owner ? Owner->GetActorLocation() : FVector::ZeroVector);
94
95 TargetActor = NewTarget;
96
97 // 새 타겟이 없으면 앵커/각도는 그대로 유지
98 if (!IsValid(TargetActor))
99 return;
100
101 // 새 중심(높이 오프셋 반영)
102 const FVector NewCenter = TargetActor->GetActorLocation() + FVector(0.f, 0.f, HeightOffset);
103
104 // 즉시 스냅(보간 없이 전환)
105 if (bSnapAnchor)
106 {
107 AnchorLoc = NewCenter;
108 }
109
110 // 위상 유지: 현재 월드 위치가 궤도상 같은 지점이 되도록 각도를 재설정
111 if (bPreserveOrbitPhase && Owner)
112 {
113 const FVector Rel = OwnerLoc - NewCenter; // 새 중심 기준
114 if (!Rel.IsNearlyZero())
115 {
116 AngleDeg = FMath::RadiansToDegrees(FMath::Atan2(Rel.Y, Rel.X)); // [-180,180]
117 // AngleDeg를 0~360로 정규화하고 싶으면:
118 if (AngleDeg < 0.f) AngleDeg += 360.f;
119 }
120 }
121
122 // TimeAcc는 유지(바운스 위상 지속). 필요 시 리셋:
123 // TimeAcc = 0.f;
124}
UOrbitalBehaviorComponent 클래스를 선언합니다.