일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 메카님
- Security
- stride
- animation
- Multiplay
- dirty cow
- photon fusion2
- Replication
- Unreal Engine
- 게임개발
- 유니티
- MLFQ
- ability task
- MAC
- 언리얼 엔진
- gas
- 언리얼엔진
- DP
- Delegate
- 게임 개발
- Rr
- CTF
- Race condition
- 유스케이스
- ret2libc
- DSP
- unity
- gameplay effect
- gameplay ability system
- 운영체제
- Today
- Total
Replicated
[ChronoSpace] Interaction 구현 본문
전에 만들었던 Key와 Altar는 Player가 OnInteract 델리게이트를 가지는데,
상호작용하는 오브젝트들이 충돌을 감지해서 해당 델리게이트를 구독하는 방식이다
그런데 인터렉션 인터페이스를 만들어두고 플레이어가 층돌 감지해서 인터렉션 인터페이스를 빼와서 그걸 작동시키는게 나을 것 같다
ICSInteractionInterface => 상호작용 오브젝트에 부착
UPlayerInteractionComponent => 플레이어에 부착
뭐가 됐든 상호작용 오브젝트도 감지용 트리거는 붙여놔야 함
ICSInteractionInterface
- BeginInteraction -> 상호작용 오브젝트 감지 시
- EndInteraction -> 상호작용 오브젝트 멀어질 시
- Interact -> 상호작용(F키 누름)
이렇게 만들어짐
플레이어는 컴포넌트 만들고 트리거 설정
그리고 실행 시 해당 컴포넌트의 ExecInteraction 사용
void UCSPlayerInteractionComponent::OnComponentBeginOverlapCallback(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepHitResult)
{
ICSInteractionInterface* Interaction = Cast<ICSInteractionInterface>(OtherActor);
if ( Interaction )
{
Interaction->BeginInteraction();
CurrentInteractionActor = OtherActor;
InteractionActors.Emplace(CurrentInteractionActor.GetFName(), CurrentInteractionActor);
}
}
여러 오브젝트가 동시에 들어올 수 있어서 캐싱해 둬야 함
void UCSPlayerInteractionComponent::OnComponentEndOverlapCallback(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
ICSInteractionInterface* Interaction = Cast<ICSInteractionInterface>(OtherActor);
if (Interaction)
{
Interaction->EndInteraction();
InteractionActors.Remove(OtherActor->GetFName());
ClearCachedActors();
if ( InteractionActors.Num() > 0 )
{
auto Actor = InteractionActors.CreateIterator();
CurrentInteractionActor = Actor.Value();
}
else
{
CurrentInteractionActor = nullptr;
}
}
}
트리거 나갈 때 캐시해둔 거 한 번 정리 (Destroy된 거 고려)하고, 남은 객체가 있으면 들고 와서 인터랙션 대상으로 삼음
* 굳이 이렇게 캐싱해서 관리하는 이유?
상호작용 오브젝트가 겹치는 상황이 올 수도 있으니까? 유저 경험적으로 유지해두는게 더 나음
Map인 이유는 Stack 쓰면 안되는게 트리거 범위가 다 다르니까 뭐가 먼저 빠져나갈 지 알 수 없음
void UCSPlayerInteractionComponent::ClearCachedActors()
{
for ( auto Actor = InteractionActors.CreateIterator(); Actor; ++Actor)
{
if ( !IsValid( Actor.Value() ) || Actor.Value()->IsPendingKillPending() ) {
InteractionActors.Remove(Actor.Key());
}
}
}
제거되지 않은 객체인지 확실하게 체크하고, 제거된 객체인 경우 맵에서 제거
void UCSPlayerInteractionComponent::ExecInteraction()
{
if ( CurrentInteractionActor )
{
ICSInteractionInterface* Interaction = Cast<ICSInteractionInterface>(CurrentInteractionActor);
Interaction->Interact();
}
}
인터렉션
사용법은
상호작용 오브젝트에 인터페이스 추가하고
이거 세 개 구현
Begin, End는 가까이 갔을 때, 멀어졌을 때 발동하는 함수
기본적으로는 위젯 가시화 관련, 다른 거 필요하면 구현해서 넣어도 될 듯
Interact는 F 누르면 발동되는 거 내용 구현
트리거도 만들어줘야 하는데 콜리전 프로필 저걸로 해줘야 함
이것만 해주면 나머진 PlayerInteractionComponent에서 알아서 처리함
일단 상호작용 표시는 다 뜨고
다른 오브젝트가 삭제되었을 때, 이전에 캐싱해뒀던 오브젝트로 인터렉션 대상이 잘 옮겨지는 걸 확인 가능하다
하나씩 사라지는 건 추가로 설정해뒀다
첫 구상 때는 발행 구독 패턴 형태였는데, 지금은 오히려 스트라티지 패턴에 인풋 이벤트를 엮은 형태가 되었다
'언리얼 엔진 > ChronoSpace' 카테고리의 다른 글
[ChronoSpace] Switch (0) | 2025.02.20 |
---|---|
[ChronoSpace] Patrol 배치, Clockwork Labyrinth 프로토타입 완성 (0) | 2025.02.17 |
[ChronoSpace] ** Attribute Replication ** (0) | 2025.02.17 |
[ChronoSpace] Behavior Tree + Ability & Effect + Camera Shake (0) | 2025.02.17 |
[ChronoSpace] NavMesh와 Behavior Tree를 이용한 AI NPC (Clockwork Labyrinth) (3) | 2025.02.16 |