Skip to content

Latest commit

 

History

489 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

때려쳐 : 샷건 시뮬레이터

프로젝트 소개

  • 개발엔진: Unreal Engine 5(5.3.2)
  • 개발기간: 2023.11 ~ 2025.06
  • 게임설명 : 직장생활에 지친 직장인들에게 주변 사물을 때려 부수며 스트레스를 풀 수 있는 게임으로, 사실적인 사물표현과 사물파괴를 기반으로 쾌감과 즐거움을 제공하는 게임

담당 파트

메인 클라이언트 프로그래머

  • 플레이어 조작
  • 현실적인 사물 표현 및 사물간 상호작용

기술설명

구현 기술에 대한 설명이 필요한 주된 메커니즘들을 설명합니다




기반 시스템: 오브젝트 풀링

구현목표

  • 자주 사용하는 Actor를 미리 생성하여 게임을 최적화

구현방법

  • TArray를 이용하여 미리 생성후 활성화/비활성화를 통한 Actor 배치

코드

/// <summary>
/// 풀 초기화, 나이아가라 시스템 풀
/// </summary>
/// <param name="_PoolTargetClass_NsDisplay"></param>
/// <param name="_PoolSize_NsDisplay"></param>
void AObjectPoolSystem::InitializePool_NsDisplay(TSubclassOf<ANsDisplay> _PoolTargetClass_NsDisplay, int32 _PoolSize_NsDisplay)
{
    PoolTargetClass_NsDisplay = _PoolTargetClass_NsDisplay;
    PoolSize_NsDisplay = _PoolSize_NsDisplay;

    for (int32 i = 0; i < PoolSize_NsDisplay; ++i)
    {
        ANsDisplay* NewActor = GetWorld()->SpawnActor<ANsDisplay>(PoolTargetClass_NsDisplay);
        NewActor->SetActorHiddenInGame(true);
        ObjectPool_NsDisplay.Add(NewActor);
    }
}

/// <summary>
/// 풀 받아오기
/// </summary>
/// <returns>사용가능한 액터</returns>
ANsDisplay* AObjectPoolSystem::GetPooledObject_NsDisplay()
{
    for (ANsDisplay* nsDisplay : ObjectPool_NsDisplay)
    {
        if (nsDisplay->IsHidden())
        {
            nsDisplay->SetActorHiddenInGame(false);
            nsDisplay->SetActorTickEnabled(true);
            return nsDisplay;
        }
    }

    return GetAddtionalObject_NsDisplay();
}

/// <summary>
/// 사용가능한 풀이 없을 경우
/// </summary>
/// <returns>추가 액터</returns>
ANsDisplay* AObjectPoolSystem::GetAddtionalObject_NsDisplay()
{
		// 추가 생성
    ANsDisplay* addtionalNewNsDisplay =
			     GetWorld()->SpawnActor<ANsDisplay>(PoolTargetClass_NsDisplay);
			     
		// 비활성화 하여 제공
    addtionalNewNsDisplay->SetActorHiddenInGame(false);
    addtionalNewNsDisplay->SetActorTickEnabled(true);
    return addtionalNewNsDisplay;
}

/// <summary>
/// 액터 사용완료 후, 풀로 반환
/// </summary>
/// <param name="Ns_Display"></param>
void AObjectPoolSystem::ReturnPooledObject_NsDisplay(ANsDisplay* Ns_Display)
{
    Ns_Display->SetActorHiddenInGame(true);
}

구현결과

image

게임 시작 시, 미리 풀이 형성

Image

액터 요청 시 레벨에 표시 ➡️ 일정시간 이후 회수

기반 시스템: 점수증가 feat. Lerp

구현목표

  • 점수 증가의 표현을 시각적으로 표현

구현방법

  • Lerp함수를 이용하여 점수 증가를 시각적으로 표현
  • 최대/최소값을 기반으로 작은 값은 최솟값으로, 큰 값은 최댓값으로 제한

코드

/// <summary>
/// 점수 획득, 보간 트리거 
/// </summary>
/// <param name="price">획득점수</param>
void AProjectD_DefaultGameMode::GetScore(int32 price)
{
	// 새로운 보간의 시작 (시작 : 현재점수, 목표 : 현재점수 + price)
	ScoreInterpolStartVal = CurScore;
	InterpolTargetScore += price;

	// 보간값 초기화
	ElapsedScoreInterpolTime = 0;
	// 보간 소요시간 기본 설정
	ScoreInterpolDuration = FMath::Abs(ScoreInterpolStartVal - InterpolTargetScore)
															* SCORE_INTERPOL_DURATION_RATE
	// 보간 소요시간 최댓값 필터
	ScoreInterpolDuration = 
						FMath::Min(ScoreInterpolDuration, SOCRE_INTERPOL_MAX_DURATION);
	// 보간 소요시간 최솟값 필터						
	ScoreInterpolDuration = 
						FMath::Max(ScoreInterpolDuration, SCORE_INTERPOL_MIN_DURATION);

	CountSlowStack();
}

/// <summary>
/// Tick함수에서 실행
/// CurScore이 InterpolTargetScore보다 작을때만 실행(GetScore 실행시 Trigger)
/// </summary>
/// <param name="dt">DeltaTime</param>
void AProjectD_DefaultGameMode::InterpolateScore(float dt)
{
	if (CurScore >= InterpolTargetScore) { 
		CurScore = InterpolTargetScore;
		return; 
	}
	ElapsedScoreInterpolTime += dt;

	// 고정된 A to B의 Lerp
	CurScore = FMath::Lerp(ScoreInterpolStartVal, 
												InterpolTargetScore, 
												ElapsedScoreInterpolTime / ScoreInterpolDuration);
}

구현결과

Image Image

기반 시스템 : 벡터의 내적을 이용하여 액터를 던지는 각도 계산

구현목표 - 액터를 던지는 각도에 따라 Directinal Mag의 크기 조절 구현

구현방법

  • 플레이어의 Forward Vector와 카메라 Forward Vector의 내적을 이용하여 던지는 각도 계산
  • 각도에 따라 Directional Mag 감소 여부 확인

코드

image

플레이어의 Forward Vector와 카메라 Forward Vector의 내적을 이용하여 던지는 각도 계산

image image

각도에 따라 Directional Mag 감소 여부 확정

구현결과

Image

파편 분산 정도(Directional Magnitude) 정상적용

Image

파편 분산 정도(Directional Magnitude) 감소




Chaos Physics Engine : Fracture System

구현목표 - Static Mesh와 다르게 부숴지는 액터를 카오스 물리엔진으로 표현

구현방법

  • 프렉쳐 시스템을 이용하여 Geometry Collection 생성
  • Convex 콜리전을 세밀하게 조정
image

총 23조각으로 Fracture 적용, Geometry Collection의 엉성한 Convex 콜리젼

image

구현결과

  • 머그컵 데미지 임계점 : 3,000
Image

좌 데미지: 2000, 우 데미지: 5000

Chaos Physics Engine : Geometry Collecion - Set Actor Location 의 한계

구현목표 - Set Actor Location 이 안 되기 때문에, 물건을 집어 던지는 행위에 제한 발생 ➡️ 던질 수 있도록 구현

구현방법

  • 액터 이동 필요 시 Static Mesh 모델 사용
  • 던져서 충돌 시 Geometry Collection과 Master Field를 생성하여 파괴

코드

image

Master Field 생성 (추후 오브젝트 풀링 적용)

image

Geometry Collection 생성

구현결과

Image

던져지는 순간 Static Mesh 사용 ➡️ 부딪히는 순간부터 Geometry Collection 사용

Chaos Physics Engine : Field System - Bomb Field

구현목표 - Fracture System 뿐만 아니라 Static Mesh에도 영향을 줄 수 있도록 구현

구현방법

  • Static Mesh 액터와 Geometry Collection액터에 Field System에 대한 Overlap Event 추가
  • 피직스 바디 깨우기(수정)
  • Geomoetry Collection과의 콜리젼 발생(수정)

코드
image

구현결과

Image



Procedural Mesh: Procedural Mesh

구현목표

  • Static Mesh와 실시간으로 변형되어 찌그러짐을 표현

구현방법

  • 기본 Static Mesh로 부터 Procedural Mesh 생성
  • player Tag를 가진 액터와의 충돌에서 계산된 충격량에 따라 찌그러짐구현

코드
image

충돌 부분의 인근 정점 수집 → 정점 위치 변형
image

변경된 정점에 따라 Procedural Mesh와 Convex Mesh 업데이트

구현결과
Image

실시간으로 변형되는 Procedural Mesh

image

변형된 컨벡스 메시

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages