남이 쓴 상호작용 기능 구현 코드이다.

void AHamsterDemoCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
{
	...
	PlayerInputComponent->BindAction("Interaction", IE_Pressed, this, &AHamsterDemoCharacter::OnInteract);
	...
}


void AHamsterDemoCharacter::OnInteract()
{

}


// 업데이트 문
void AHamsterDemoCharacter::Tick(float DeltaSeconds)
{
	Super::Tick(DeltaSeconds);

	FHitResult hitResult;
	if (TraceOn(hitResult))
	{
		auto interactableObj = TraceInteractableObject(hitResult); // 감지한 물체가 상호 작용 가능한 물체인 지 체크
		if (interactableObj != nullptr)
		{
			bool isSuccessInteract = interactableObj->Interact(); // 물체에게 상호 작용 시도
			if (isSuccessInteract)
			{
				// 상호 작용 성공 시 캐릭터가 할 행동 
			}
		}
	}
}


AInteractableObject* AHamsterDemoCharacter::TraceInteractableObject(struct FHitResult& inHit)
{
	auto actor = inHit.GetActor();
	if (actor == nullptr)
		return nullptr;

	return Cast<AInteractableObject>(actor);
}


bool AHamsterDemoCharacter::TraceOn(struct FHitResult& OutHit)
{
	auto startPos = GetSpawnFVector();
	auto forwardVector = GetGunRightFVector();
	float TraceOffset = 500.0f;

	FVector endPos = ((forwardVector * TraceOffset) + startPos);

	FCollisionQueryParams CollisionParams;

	return GetWorld()->LineTraceSingleByChannel(OutHit, startPos, endPos, ECollisionChannel::ECC_WorldStatic, CollisionParams);
}

상호 작용 가능한 물체/인물에 다가가면 E키를 누르라는 UI가 보이고,

E키를 눌러 상호작용 시 대화, 탑승 등의 추가 이벤트로 넘어가게 된다.

 

키보드에서 E키를 눌렀을 때 OnInteract() 가 발동됨

 

Tick 함수에서 매 틱마다 (프레임마다, 즉 1초에 60회정도) 판정하는 내용은 다음과 같다.

 

TraceOn(HitResult)에 값이 있는지?

TraceOn 에서는

LineTraceSingleByChannel (RayCast 기능) 을 사용해서, WorldStatic 인 콜리전만 찾음 (WorldStatic은 static mesh에만 적용되는 속성이므로, static mesh를 찾는다는 뜻)

TraceOn은 ray를 맞은 애인 OutHit을 리턴

 

TraceOn(HitResult)가 nullptr가 아니면 if 문 진입 (ray 맞은 애가 있다면)

TraceInteractableObj 에서 Ray를 맞은 애가 액터인지 & 상호작용 가능한지 (interactable인지) 확인하고 리턴

 

interactableObj가 nullptr가 아니면 if문 진입 (상호작용 가능하다면)

interactableObj에 Interact() (상호작용 시도)

 

 

if(isSucessInteract) 전까지는 모두 interact 여부 판단을 위한 코드임

그 이후로는 상호작용에 성공했을 시 취할 행동의 코드를 기술하면 된다.

 

OnInteract() 에서 (E키가 눌렸을 때)

조건에 맞지 않으면 무시하고

조건에 맞으면 진행한다.

 

+) InteractableObj 또는 isSuccessInteract 를 (혹은 둘 다를) 지역변수가 아닌 멤버 변수로 선언해서

OnInteract()에서 가져다가 판정할 수 있게 해도 좋을 것 같음.

 

'E 누르기' UI는 Interact()에서 띄우게 해도 된다

단, 이미 UI가 떠 있으면 띄우지 않게, 다른 사람이 이미 대화 중이라면 띄우지 않게, 퀘스트를 이미 클리어했다면 띄우지 않게 하기 등 예외처리가 필요하다.

 

Interact() 에서 E누르기가 가능해서 E를 누른 이후의 처리는 OnInteract() 에서 진행한다 (대화창 등)

 

 


 

11줄을 조정하면 구체의 크기가 바뀌고, 31줄을 조정하면 총알이 남아있는 시간이 바뀔 줄 알았는데...

의외로 그렇게 간단히 바뀌지는 않는 것 같다 (확실하지 않음)

 

bShouldBounce를 false로 하면 공이 맞은 곳에 그대로 붙어 버린다. 찍찍이공처럼!

 

AddImpulse를 통해 뭔가 뭔가 할 수 있을 것 같다.

 

총알이 닿았을 때 이펙트가 터지는 건 어떻게 해야 할 지 아직 잘 모르겠다...

https://docs.unrealengine.com/4.27/ko/Basics/Actors/DecalActor/

https://velog.io/@kjinwoo12/%EC%96%B8%EB%A6%AC%EC%96%BC-%EC%97%94%EC%A7%84-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-FPS-%EA%B2%8C%EC%9E%84-%EA%B0%9C%EB%B0%9C-%EC%9D%BC%EC%A7%805-%EC%B4%9D%EC%95%8C-%EC%9E%90%EA%B5%ADBullet-holes-%EB%8D%B0%EC%B9%BCDecal

 

아이디어: 데칼 사용? remote procedure call 사용?

'[햄] 작업일기' 카테고리의 다른 글

230530  (0) 2023.05.31
230528  (0) 2023.05.28
230527  (0) 2023.05.27
230516  (0) 2023.05.16
230508  (0) 2023.05.08

+ Recent posts