すしあつめユーティリティの使用方法

1. https://play.google.com/apps/internaltest/4698858477410894375 ページをブラウザで開きます。

2. 「ACCEPT INVITE」ボタンを押します。

3. 「download it on Google Play」リンクを押してPlayストアを起動します。

4. 「更新」ボタンを押してアプリを更新します。

5.「プレイ」ボタンをタップします。

6. ユーティリティアプリが起動したら、下部の「アップロード」ボタンを押します。

7. しばらく後、作業完了を確認した後、スクリーンショットを撮って開発チームに返信します。


게임잼 행사 결과물

모든 작품에 프로그래머로 참여!

[2021년 11월] 청소의 정석

[2022년 2월] 봄날의 프로포즈

[2022년 5월] 편식소녀 : 먹지마 채소

[2022년 8월] Kit Rush (키트 러시)

[2022년 11월] 소방차를 기다리는 비버가 산불을 끄는 게임

[2023년 8월] 프로클리너 (Frocleaner)




언리얼 엔진을 배우며…

유니티만 10년 정도 쓰다가 언리얼 엔진 5.1을 한번 써 보니 꽤 재미있다.

막힐 때는 답답하지만… 두 엔진이 각각 같은 개념을 다르게 포장해둔 것을 비교해보는 게 재밌다.

그리고 게임에서 쓰이는 기본 기능들이 다 만들어져 있는 것도 좋다.

유니티를 만든 회사와 언리얼을 만든 회사가 각각 자기 자리를 잘 잡은 것으로 느껴진다.

유니티는 오랫동안 써 와서 이제 좀 질린 감이 있고, 별로 신나게 떠들만한 구석은 없다고 여기고 있었는데, 언리얼을 다루다보니 유니티와 아무래도 1:1 비교가 되는 부분이 많이 보여서 같이 이야기해보려고 한다.

그냥 맘대로 끄적인 글이니까, 진지하게 두 개의 엔진 중 하나를 택하기 위해 이 글을 보고 있다면 다른 진지한 글을 찾아보는 것이 낫다는 것을 우선 밝힌다. 비교를 잘 해둔 글이 넘쳐난다.

유니티는 그래도 풀타임, 파트타임으로 10년 넘게 썼고, 언리얼은 이제 몇 주 다뤄봤을 뿐이므로 틀린 내용도 많을 것이다. (그런 게 있으면 알려주면 좋겠지만… 이 글을 누가 볼 것이며, 댓글도 다 막아뒀다는…)

그리고 두 엔진 중 하나를 선택하고 있는 사람이라면 다른 사람의 경험을 먼저 참고할 것이 아니라, 스스로의 경험/느낌의 비중을 가장 높이는 것이 맞기 때문에… 뭔가 두 개를 며칠 혹은 몇 주 가지고 놀아보고 다른 사람들의 의견에 대해서 참고 삼아 보는 수준으로 읽었으면 좋겠다.

언리얼 엔진은 일단 원활하게 에디터를 구동하기 위한 컴퓨터 사양 자체가 격(?)이 다르다. 2020년형 아이맥, 2021년에 구입한 고사양 라이젠 데스크탑 두 개를 주력으로 쓰고 있는 터라 언리얼 에디터 구동에 무리는 없으나, 유니티만 쓰던 사람이라 언리얼이 엄청나게 무겁게 느껴지는 것은 사실이다. 그러나 이 ‘무겁다’라는 표현만으로는 너무 애매하니 조금 나눠서 설명해보고자 한다.

새 컴퓨터 상태에서 첫 개발 환경을 구축하는 것: 구축하는 절차는 비슷비슷, 걸리는 시간은 언리얼 엔진이 훨씬 많이 걸린다. 두 엔진 모두 각각 Unity Hub, Epic Games Launcher란 프로그램 설치를 시작으로 개발 환경을 구축하게 되는데, 편의성만큼은 둘 다 매우 좋다. 회원 가입과 몇 번의 클릭으로 순식간에 설치가 완료된다.

절차는 비슷한데, 차이가 나는 부분은 첫 실행 시 걸리는 시간이다. 언리얼 엔진이 월등하게 더 오래 걸린다. 언리얼 엔진이 기본 내장된 셰이더 코드가 훨씬 많고, 이를 미리 컴파일해야 실행되도록 만들어둬서 그런 것으로 보인다. 초심자 대상 유니티 실습 강사도 여러 회 맡아 본 경험으로, 개발 환경 구축에 걸리는 시간이 중요할 때도 있긴 하지만, 대부분의 사용 목적에는 일회성 셋업 시간의 차이가 아무리 큰들, 큰 판단 기준은 아닐 것이다. 다만 언리얼 엔진이 인상적으로 더 시간이 걸리기 때문에 언급한다.

두 엔진 모두 에디터 실행이 딱 되면 가장 먼저 ‘새 프로젝트’ 생성을 할 차례이다. (유니티를 써서 쉬워지는 것은 ‘새 프로젝트’ 생성이지 ‘게임’ 완성이 아니라는 농담반 진담반 댓글도 떠오른다…)

새 프로젝트 생성 단계에 있어서도 두 엔진은 확실한 차이를 보여준다.

1인칭, 3인칭, 탑다운, 차량 조종 게임 등 인기있는 게임 개발을 위한 기초 셋업이 완료된 프로젝트 템플릿을 고르는 것과 ‘텅 빈’ 프로젝트 템플릿을 동등하게 두고 고르라고 하는 언리얼 에디터와는 달리 유니티 에디터는 ‘텅 빈’ 프로젝트 생성을 기본으로 추구한다는 점이다. 물론 유니티도 몇 번 클릭하면 프로젝트 템플릿을 고를 수도 있긴하다. 다만 이 ‘기본값’의 힘을 무시할 수는 없을 터… 우리 엔진은 이것도 할 수 있고, 저것도 할 수 있고, 다 할 수 있어요!!! 라고 외치는 듯한 언리얼과는 달리 유니티는 굉장히 소박하게 시작하는 것을 권하는 듯하다.

프로젝트 생성이 끝난 후 나오는 첫 에디터 화면은 내 기준으로 확연한 차이는 느끼지 못했다. 그래도 보이는 차이점 중에 가장 큰 것이 있다면, 느낌상 언리얼 에디터는 ‘내가 정해준 대로 써’ 느낌이라면 유니티 에디터는 ‘일단 이게 기본값인데 맘에 안들면 바꿔서 써’ 느낌이다. 언리얼 에디터의 여명기에 대해서는 내가 겪어본 바 없지만, 오랜 기간 규모 있는 게임 회사의 전유물이었던 것으로 안다. 그러다보니 ‘언리얼 개발자’라는 커리어 키워드가 생겨났을 것이고, 이는 모든 ‘언리얼 개발자’가 최대한 유사한 개발 환경을 공유해서 얻는 이득이 컸음을 짐작할 수 있다. 그래서 언리얼 엔진을 사용해 개발하는 사람이나, 언리얼 엔진 자체를 개발한 개발자나 양쪽 모두 툴의 커스터마이징 필요성은 크게 보지 않았으리라…

기본 조작 방식이나 에디터의 UI 레이아웃을 비교하는 것은 서로 다른 두 게임의 그것을 비교하는 것과 똑같은 느낌이라 과감하게 생략한다.

블루프린트 이야기를 빼 놓을 순 없을 것이다. 이는 언리얼 엔진에 기본 내장되고 ‘권장되는’ 비주얼 스크립팅 시스템이다. 코드를 텍스트 형태로 주르르륵 써 내려가는 대부분의 프로그래밍 언어와는 완전히 다르게 각 필요에 맞는 노드를 배치하고, 노드를 선으로 연결해서 프로그램 로직을 개발하는 것이다. 파워포인트 슬라이드에 그림 그리듯이 만들게 되므로 진입 장벽은 월등하게 낮아지는 장점이 있다.

그나저나 너티독 같은 곳에서도 엔진 공개해주면 좋겠다. 책은 써 놓고 엔진 공개는 왜 안하는가!!!


blog.plusalpha.top 대개장

예전에 만든 사이트가 PHP 6.1 버전이라 보안상 문제가 있다고 한다. 그래서 업그레이드를 해 볼까 했는데 뭔 Bitnami 이미지는 업그레이드가 불가하다고 해서 새로 만들었다. 하하하~



UE5 스터디 기록

UE5 정복

UE5 정복

UE5 배운 내용들 메모로 남기자.

1일차 (2023년 3월 21일 20:00 ~ 22:00)

  1. 새 프로젝트 만들기 – 이름: StartMac, Empty 템플릿, C++
  2. 콘텐츠 생성: 레벨, 이름: GameMap
  3. GameMap 열기
  4. C++ 버전의 게임 모드 베이스 만들기 – MyGameModeBase 클래스 타입은 정하지 않은 상태로 두기
  5. 월드 세팅 창 열고 게임모드 오버라이드를 MyGameModeBase로 지정
  6. MyGameModeBase.h 코드 편집 – 코드 중 STARTMAC_API 부분은 각자의 프로젝트명에 맞게 변경해야 함
    UCLASS()
     class STARTMAC_API AMyGameModeBase : public AGameModeBase
     {
         GENERATED_BODY()
     
     public:
         AMyGameModeBase();
     
     };
    
  7. MyGameModeBase.cpp 코드 편집
    AMyGameModeBase::AMyGameModeBase()
    {
        // set default pawn class to our Blueprinted character
        static ConstructorHelpers::FClassFinder<APawn> PlayerPawnBaseBPClass(TEXT("/Game/BP_ThirdPersonCharacter"));
        if (PlayerPawnBaseBPClass.Class != NULL)
        {
            DefaultPawnClass = PlayerPawnBaseBPClass.Class;
        }
    }
    
  8. 에디터 실행하면 시 BP_ThirdPersonCharacter 찾을 수 없다는 경고창 나온다. 정상.
  9. 블루프린트 클래스 추가 – 종류: 캐릭터, 이름: BP_ThirdPersonCharacter
  10. C++ 클래스 추가 – 종류: 캐릭터, 이름: MyGameCharacter
  11. BP_ThirdPersonCharacter 애셋 열고 상단 메뉴 파일블루프린트 부모변경MyGameCharacter
  12. UnrealEngine\Templates\TemplateResources\High\Characters\Content\Mannequins\Meshes\SKM_Quinn.uasset 파일을 내 프로젝트 콘텐츠 폴더로 복사
  13. BP_ThirdPersonCharacter 애셋의 최상위 컴포넌트 선택하고 디테일 패널에서 Skeletal Mesh AssetSKM_Quinn으로 지정
  14. MyGameCharacter.h 코드 편집 – GENERATED_BODY() 아래에 다음 코드 삽입
    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = MyInput, meta = (AllowPrivateAccess = "true"))
    class UInputMappingContext* DefaultMappingContext;
    
    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = MyInput, meta = (AllowPrivateAccess = "true"))
    class UInputAction* JumpAction;
    
    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = MyInput, meta = (AllowPrivateAccess = "true"))
    class UInputAction* MoveAction;
    
    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = MyInput, meta = (AllowPrivateAccess = "true"))
    class UInputAction* LookAction;
    
  15. MyGameCharacter.h 코드 편집 – protected: 아래에 다음 코드 삽입
    void Move(const FInputActionValue& Value);
    void Look(const FInputActionValue& Value);
    
  16. 빌드 해 보면 여러 가지 빌드 오류들이 날 것
  17. StartMac.Build.cs 파일 열어 PublicDependencyModuleNames 변수에 EnhancedInput 항목 추가
  18. MyGameCharacter.cpp 코드 편집 – 헤더 파일 맨 뒤에 추가
    #include "EnhancedInputComponent.h"
    #include "EnhancedInputSubsystems.h"
    
  19. MyGameCharacter.h 코드 편집 – #include "MyGameCharacter.generated.h" 줄 위에 추가
    #include "InputActionValue.h"
    
  20. 빌드 정상적으로 완료되는지 확인
  21. MyGameCharacter.cpp 코드 편집. 캐릭터 조작 입력 바인딩의 실질적인 구현.
    void AMyGameCharacter::BeginPlay()
    {
        Super::BeginPlay();
    
        if (const APlayerController* PlayerController = Cast<APlayerController>(Controller))
        {
            if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
            {
                Subsystem->AddMappingContext(DefaultMappingContext, 0);
            }
        }
    }
    
    void AMyGameCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
    {
        Super::SetupPlayerInputComponent(PlayerInputComponent);
    
        if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
        {
            EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Triggered, this, &ACharacter::Jump);
            EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping);
    
            EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AMyGameCharacter::Move);
            EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &AMyGameCharacter::Look);
        }
    }
    
    void AMyGameCharacter::Move(const FInputActionValue& Value)
    {
        const FVector2D MovementVector = Value.Get<FVector2D>();
    
        if (Controller != nullptr)
        {
            const FRotator Rotation = Controller->GetControlRotation();
            const FRotator YawRotation(0, Rotation.Yaw, 0);
    
            const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
            const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
    
            AddMovementInput(ForwardDirection, MovementVector.Y);
            AddMovementInput(RightDirection, MovementVector.X);
        }
    }
    
    void AMyGameCharacter::Look(const FInputActionValue& Value)
    {
        const FVector2D LookAxisVector = Value.Get<FVector2D>();
    
        if (Controller != nullptr)
        {
            AddControllerYawInput(LookAxisVector.X);
            AddControllerPitchInput(LookAxisVector.Y);
        }
    }
    
  22. 콘텐츠 생성: 입력입력 매핑 컨텍스트 1개, 이름: IMC_Default
  23. 콘텐츠 생성: 입력입력 액션 3개, 이름 IA_Jump, IA_Move, IA_Look
  24. 편집프로젝트 세팅...프로젝트맵 & 모드에 들어가서 에디터 시작 맵, 게임 기본 맵GameMap으로 변경
  25. 카메라를 제대로 작동하도록 해 보자.
  26. MyGameCharacter.h 파일에 프로퍼티 추가
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = MyCamera, meta = (AllowPrivateAccess = "true"))
    class USpringArmComponent* CameraBoom;
    
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = MyCamera, meta = (AllowPrivateAccess = "true"))
    class UCameraComponent* FollowCamera;
    
  27. MyGameCharacter.cpp 파일 생성자에 코드 삽입
    // controller 회전 시에 캐릭터도 회전하게 하지 않는다. 카메라만 회전하면 된다.
    bUseControllerRotationPitch = false;
    bUseControllerRotationYaw = false;
    bUseControllerRotationRoll = false;
    
    GetCharacterMovement()->bOrientRotationToMovement = true;
    GetCharacterMovement()->RotationRate = FRotator(0.0f, 500.0f, 0.0f);
    
    GetCharacterMovement()->JumpZVelocity = 700.f;
    GetCharacterMovement()->AirControl = 0.35f;
    GetCharacterMovement()->MaxWalkSpeed = 500.f;
    GetCharacterMovement()->MinAnalogWalkSpeed = 20.f;
    GetCharacterMovement()->BrakingDecelerationWalking = 2000.f;
    
    CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
    CameraBoom->SetupAttachment(RootComponent);
    CameraBoom->TargetArmLength = 400.0f;
    CameraBoom->bUsePawnControlRotation = true;
    
    FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
    FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName);
    FollowCamera->bUsePawnControlRotation = false;
    
  28. 카메라 제어도 이제 된다.


Copyright © 2024. All Rights Reserved. PAGS by Flytonic.