일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 29 | 30 | 31 |
- 전자공학부
- 게임개발
- 반도체소자교육
- 전자회로
- pn junction
- SoC설계
- 베르
- SK하이닉스
- 반도체기초교육
- 반도체공정교육
- 자습
- 자습목적포스팅
- 다이오드
- Rectifier
- 개인스터디
- 물리전자
- UnrealEngine4
- UE4
- 언리얼엔진4
- 회로개발
- 베르의게임개발유튜브
- 하이포2기
- 자습포스팅
- 전자공학
- ASIC설계
- diode
- 반도체물성
- 참고
- 반도체교육
- 디지털회로설계
- Today
- Total
호경
[캡스톤디자인] VR게임 제작하기 - 무기 배치, 잡기 본문
※본 글은 전자공학부 캡스톤 디자인 작품인 "VR 체험형 소프트웨어 제작"주제로 진행한느 내용을 정리하기 위한 글로, 개발 과정에 전반적인 흐름과 코드를 포스팅 하기 위해 작성 됐다. 혹여, VR 관련된 프로젝트를 하는 분들이 계시거나 UE4를 잘 아는 분이 계시면 해당 포스트에서 틀린 곳이나 수정해야 할 부분이 있으면 말씀해주시면 감사하겠습니다!
그리고 해당 프로젝트는 C++과 블루프린트의 혼용으로 진행할 예정입니다!
1. 프로젝트 세팅에서 집기 버튼 활성화
프로젝트 세탕 -> 입력 -> 액션 맵핑
이 과정을 통해 Grip 버튼을 활성화 시킨다.
이번에 내 프로젝트에서는 Oculus RIiftS를 사용할 예정이므로 Oculus Touch L, R 그립에 GrabLeft, GrabRight 액션을 맵핑을 해주었다.
2. 잡는 동작 만들기
1) AVRPawn 함수에 Overlap 되게 설정해주기
언리얼엔진에서는 집기 동작을 만들 때 Overlapping이라는 함수를 이용해서 만든다.
우선 AVRPawn 함수에 Overlap 함수를 넣어줄 수 있는 Mesh에 Collision을 Set 해준다.
//Overlap이 돼야함
LeftSword->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Overlap);
RightSword->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Overlap);
2) 입력을 받기 위해 SetupPlayerInputComponent 함수에 입력 코드 넣어주기
이동은 BindAxis로 묶어주고, 버튼을 누르는 입력은 BindAction으로 입력 Mapping을 해준다.
IE_Pressed를 통해서 눌렀을 경우, GrabRight와 GrabLeft가 작동하게 만들어준다.
void AVRPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
PlayerInputComponent->BindAction("GrabRight", IE_Pressed, this, &AVRPawn::GrabRightPressed);
PlayerInputComponent->BindAction("GrabLeft", IE_Pressed, this, &AVRPawn::GrabLeftPressed);
}
3) 잡는 것에 대한 기능 구현하기 위해 헤더파일에 선언하고, 소스파일에 구현하기
a) VRPawn.h
//다음 레벨로 이동하기 위한 방법
bool Right_has_sword;
bool Left_has_sword;
//왼손 오른손 칼잡기
void GrabRightPressed();
void GrabLeftPressed();
b) VRPawn.cpp
void AVRPawn::GrabRightPressed()
{
//Collecti (Nodachi_white)
FName RightWeaponSocket = TEXT("Sword Socket");
TArray<AActor*> outoverlap;
RightSword->GetOverlappingActors(outoverlap);
//East_Sword
FName RightEastSocket = TEXT("RightSword East");
TArray<AActor*> outoverlap_East_Right;
RightSword->GetOverlappingActors(outoverlap_East_Right);
//Kitsune_Sword
FName RightKitsuneSocket = TEXT("RightSword Kitsune");
TArray<AActor*> outoverlap_Kitsune_Right;
RightSword->GetOverlappingActors(outoverlap_Kitsune_Right);
if (outoverlap.Num() > 0)
{
ACollecti* trycast = dynamic_cast<ACollecti*>(outoverlap[0]);
Right_has_sword = true;
if (trycast)
{
trycast->GetStaticMeshComponent()->SetSimulatePhysics(false);
trycast->AttachToComponent(RightHand, FAttachmentTransformRules::SnapToTargetIncludingScale, RightWeaponSocket);
if (Right_has_sword == true)
{
UE_LOG(LogTemp, Display, TEXT("Right Sword"));
if (Left_has_sword == true && Right_has_sword == true)
{
UE_LOG(LogTemp, Display, TEXT("Both has sword"));
this->OutputText->SetText("Wepon Selected!");
}
}
}
}
if (outoverlap_Kitsune_Right.Num() > 0)
{
AKorean_Scabbard* trycast_Korean_Right = dynamic_cast<AKorean_Scabbard*>(outoverlap_Kitsune_Right[0]);
Right_has_sword = true;
if (trycast_Korean_Right)
{
trycast_Korean_Right->GetStaticMeshComponent()->SetSimulatePhysics(false);
trycast_Korean_Right->AttachToComponent(RightHand, FAttachmentTransformRules::SnapToTargetIncludingScale, RightKitsuneSocket);
if (Right_has_sword == true)
{
UE_LOG(LogTemp, Display, TEXT("Right Sword Kitsune"));
if (Left_has_sword == true && Right_has_sword == true)
{
UE_LOG(LogTemp, Display, TEXT("Both has sword"));
this->OutputText->SetText("Wepon Selected!");
}
}
}
}
if (outoverlap_East_Right.Num() > 0)
{
AEast_Sword_1* trycast_East_Right = dynamic_cast<AEast_Sword_1*>(outoverlap_East_Right[0]);
Right_has_sword = true;
if (trycast_East_Right)
{
trycast_East_Right->GetStaticMeshComponent()->SetSimulatePhysics(false);
trycast_East_Right->AttachToComponent(RightHand, FAttachmentTransformRules::SnapToTargetIncludingScale, RightEastSocket);
if (Right_has_sword == true)
{
UE_LOG(LogTemp, Display, TEXT("Right Sword East"));
if (Left_has_sword == true && Right_has_sword == true)
{
UE_LOG(LogTemp, Display, TEXT("Both has sword"));
this->OutputText->SetText("Wepon Selected!");
}
}
}
}
}
void AVRPawn::GrabLeftPressed()
{
//Nodachi_Black Sword
FName LeftWeaponSocket = TEXT("LeftSword Socket");
TArray<AActor*> outoverlap_Left;
LeftSword->GetOverlappingActors(outoverlap_Left);
//Kitsune_Sword
FName LeftKitsuneSocket = TEXT("LeftSword Kitsune");
TArray<AActor*> outoverlap_Kitsune_Left;
LeftSword->GetOverlappingActors(outoverlap_Kitsune_Left);
//East_Sword
FName LeftEastSocket = TEXT("LeftSword East");
TArray<AActor*> outoverlap_East_Left;
LeftSword->GetOverlappingActors(outoverlap_East_Left);
if (outoverlap_Left.Num() > 0)
{
ANodachi_Black* trycast_Left = dynamic_cast<ANodachi_Black*>(outoverlap_Left[0]);
Left_has_sword = true;
if (trycast_Left)
{
trycast_Left->GetStaticMeshComponent()->SetSimulatePhysics(false);
trycast_Left->AttachToComponent(LeftHand, FAttachmentTransformRules::SnapToTargetIncludingScale, LeftWeaponSocket);
if (Left_has_sword == true)
{
UE_LOG(LogTemp, Display, TEXT("Left Sword Nodachi"));
if (Left_has_sword == true && Right_has_sword == true)
{
UE_LOG(LogTemp, Display, TEXT("Both has sword"));
this->OutputText->SetText("Wepon Selected!");
}
}
}
}
if (outoverlap_Kitsune_Left.Num() > 0)
{
AKorean_Sword1* trycast_Korean_Left = dynamic_cast<AKorean_Sword1*>(outoverlap_Kitsune_Left[0]);
Left_has_sword = true;
if (trycast_Korean_Left)
{
trycast_Korean_Left->GetStaticMeshComponent()->SetSimulatePhysics(false);
trycast_Korean_Left->AttachToComponent(LeftHand, FAttachmentTransformRules::SnapToTargetIncludingScale, LeftKitsuneSocket);
if (Left_has_sword == true)
{
UE_LOG(LogTemp, Display, TEXT("Left Sword Kitsune"));
if (Left_has_sword == true && Right_has_sword == true)
{
UE_LOG(LogTemp, Display, TEXT("Both has sword"));
this->OutputText->SetText("Wepon Selected!");
}
}
}
}
if (outoverlap_East_Left.Num() > 0)
{
AEast_Sword_1* trycast_East_Left = dynamic_cast<AEast_Sword_1*>(outoverlap_East_Left[0]);
Left_has_sword = true;
if (trycast_East_Left)
{
trycast_East_Left->GetStaticMeshComponent()->SetSimulatePhysics(false);
trycast_East_Left->AttachToComponent(LeftHand, FAttachmentTransformRules::SnapToTargetIncludingScale, LeftEastSocket);
if (Left_has_sword == true)
{
UE_LOG(LogTemp, Display, TEXT("Left Sword East"));
if (Left_has_sword == true && Right_has_sword == true)
{
UE_LOG(LogTemp, Display, TEXT("Both has sword"));
this->OutputText->SetText("Wepon Selected!");
}
}
}
}
}
원하는 칼을 고를 수 있게 코드를 짠 것이다. 스켈레톤에 소켓을 구성하고 거기에 칼을 넣는 방식으로 코드를 구현했다.
4) 칼에 Collsion 입히기
#include "Korean_Sword1.h"
#include "Components/BoxComponent.h"
AKorean_Sword1::AKorean_Sword1()
{
//Find object and Get Overloap to Object
static ConstructorHelpers::FObjectFinder<UStaticMesh> loadedObj(TEXT("/Game/Kitsune/Mesh/SM_Kitsune_Katana_Sword1.SM_Kitsune_Katana_Sword1"));
this->GetStaticMeshComponent()->SetStaticMesh(loadedObj.Object);
this->GetStaticMeshComponent()->SetWorldScale3D(FVector(1.0f, 1.0f, 1.0f));
static ConstructorHelpers::FObjectFinder<UMaterial> loadedMat(TEXT("Material'/Game/Kitsune/Materials/M_Kitsune_Katana.M_Kitsune_Katana'"));
this->GetStaticMeshComponent()->SetMaterial(0, loadedMat.Object);
this->GetStaticMeshComponent()->SetSimulatePhysics(true);
this->SetMobility(EComponentMobility::Movable);
this->GetStaticMeshComponent()->SetGenerateOverlapEvents(true);
//Making Collsion Box
SwordHitBox = CreateDefaultSubobject<UBoxComponent>(TEXT("Collsion Box"));
}
이렇게 해야지 칼을 잡을 수 있다.
3. VRPawn blueprint, VRGameMode 설정
1) 게임 모드 설정을 위해 VRGameMode BP를 만들고 Player Start 기본 Pawn을 VRPawn으로 한다.
2) 이후, 레벨에 액터들을 배치해주고 실행을 확인한다.
4. 실행 결과
5. 다음 개발 계획
1) 검에 Collision Box 붙이기
2) 날아오는 구체를 튕길 수 있는 검 만들기
'캡스톤 졸업작품 > 언리얼 엔진 4' 카테고리의 다른 글
[캡스톤 디자인] VR게임 제작하기 - VR Pawn 만들기 (0) | 2023.01.06 |
---|---|
Unreal Engine 4 : (4) C++에서 구현한 함수를 블루 프린트로 구현하기 (0) | 2022.03.03 |
Unreal Engine 4 : (3) C++ 함수 선언 및 구현해보기 (0) | 2022.03.03 |
Unreal Engine 4 : (2) 변수, 접근지정자, 프로퍼티, 생성자 (0) | 2022.03.02 |
Unreal Engine 4 : (1) 기본 개념 (0) | 2022.03.01 |