전체 글 (99)

  • 2024.03.04
  • 2024.03.04
  • 2023.10.18
  • 2023.10.17
  • 2023.01.02
  • 2022.10.21
  • 2022.10.03
  • 2022.07.28
  • 2022.06.09
  • 2022.05.24
  • 2022.05.22
  • 2022.05.12
  • 03
    04

    Verse 코드로 선택한 바닥 매쉬를 등록해

    순차적으로 사라지게 하는 디바이스를 만들어보자.

    https://dev.epicgames.com/documentation/ko-kr/uefn/synchronized-disappearing-platforms-using-verse-in-unreal-editor-for-fortnite

     

    동기화된 사라지는 플랫폼

    Verse를 사용하여 차례대로 나타나면서 사라지는 징검다리 플랫폼을 하나의 장치로 구현합니다.

    dev.epicgames.com

     

    우선 등록할 바닥 매쉬를 생성해주어야 하는데, 위 예제에서는 색상 변경 바닥 디바이스? 

    미리 구현되어 있는 바닥을 이용해서 사라지는 플랫폼을 구현하는데,

     

    좀 더 커스텀할 수 있게 BP나 디바이스를 만드는 게 더 좋아 보여서 BP로 만들려고 한다.

     언리얼 엔진보다 한정적인 모습을 볼 수 있다. 건물 사물, 건물 스테틱 메시가 있는데,

    건물 사물을 "독립적인" 사물로 정적 매쉬라는 용어 자체가 고정되어 조작 불가란 의미가 있기 때문에

    건물 사물이 좀 더 바닥으로 쓰기 맞아 보인다. 이걸로 생성해 준다.

     

    아무 메쉬나 스태틱 메시 컴포넌트에 등록한다. 

     

    전 글에서 Verse 스크립트 생성을 써서 스킵하겠다.

    Verse로 디바이스를 선택해 아래와 같이 작성한다. 

    using { /Fortnite.com/Devices }
    using { /Verse.org/Native }
    using { /Verse.org/Simulation }
    using { /UnrealEngine.com/Temporary/Diagnostics }
    
    log_platform_series := class(log_channel){}
    
    Test_Verse01 := class<concrete>(creative_device):
        Logger : log = log{Channel := log_platform_series}
    
        @editable
        HeadStart : float = 2.45
     
        @editable
        AppearDelay : float = 0.98
     
        @editable
        DisappearDelay : float = 1.11
     
        @editable
        Platforms : []creative_prop = array{}
    
        OnBegin<override>()<suspends> : void =
    
            loop:
                sync:
                    ShowAllPlatforms() # 이 동시 실행 루틴은 즉시 시작되며 block 표현식과 동시에 실행됩니다.
                    block: # block 표현식은 ShowAllPlatforms()와 동시에 바로 시작됩니다. 이 코드 블록 내의 모든 표현식은 순차적으로 실행됩니다.
                        Sleep(HeadStart) # HeadStart초 동안 기다린 후에 HideAllPlatforms()이 실행됩니다.
                        HideAllPlatforms() # HeadStart초 후에 이 동시 실행 루틴이 실행됩니다.
    
        ShowAllPlatforms()<suspends> : void =
            for (PlatformNumber -> Platform : Platforms):
                Logger.Print("Platform{PlatformNumber} is now shown.") 
                Platform.Show()
                Sleep(AppearDelay)
    
        HideAllPlatforms()<suspends> : void =
            for (PlatformNumber -> Platform : Platforms):
                Logger.Print("Platform{PlatformNumber} is now hidden.") 
                Platform.Hide()
                Sleep(DisappearDelay)

     

    Sync는  Verse 언어에서 사용되는 키워드 중 하나로, 동시 실행 루틴을 시작하는 데 사용된다.

    유니티 코루틴 생각하면 될 듯. 

    Block 키워드는 아래로 무조건 순차적으로 진행되는 코드를 그룹화하여, 순서 보장을 한다.

    그래서, 모든 블랙폼을 보여주면서 동시에 숨김을 하는

    작업 사이에 Sleep을 주어 순차적으로 사라지는 바닥이 구현된다.

     

     

    위에서 만든 바닥들이 Creative_prob에 해당된다. @editable으로 디테일 창에 노출시켰으니, 등록해 주자

    + 여담이지만 UPROPERTY(EditAnywhere)와 같은 매크로와 블루프린트에 노드를 사용 못한다는 게 아쉽다.

     

     

    순차적으로 사라졌다 생기는 플랫폼들을 확인할 수 있다.

     

    'STUDY > UEFN' 카테고리의 다른 글

    UEFN - 프로젝트 생성 및 로그 남기기  (0) 2024.03.04
    COMMENT
     
    03
    04

    https://dev.epicgames.com/community/fortnite/getting-started/uefn

     

    UEFN - Getting Started | Epic Developer Community

    The Epic Developer Community offers UEFN learning materials for new users getting started.

    dev.epicgames.com

    포트나이트에서 모드를 개발하기 위한 UFFN (Unreal Editor for Fortnite)와 포트나이트가 필요하다.

     

    언리얼 엔진을 해보신 분이라면 친숙할 것이다. 기본 맵을 선택 해서 켜준다. 

     

    Alt + P 혹은 세션 시작 버튼을 누르면 클라이언트 포트나이트가 켜지고, 에디터와 세션을 맺는다.

    한 2분~3분 정도 기다려 줘야 한다.

     

    에디터에서 봤던 맵이 포트나이트 게임에서 실행되는 것을 볼 수 있다.

    언리얼에서 포트나이트를 위해 이런걸 제공한다니 정말 놀랍다

     

     

    로그를 확인하기 위해서는 섬 설정 -> 일지에서 확인해 볼 수 있다.

    영문으로는 로그인데, 일지는 좀..

    해외 유튜버들은 TAB으로 간단히 눌러서 로그 보던데.. 그 방법은 나중에 찾아봐야겠다.


     

    Verse는 언리얼에서 개발한 새로운 언어이다. 사실 내가 이걸 해보는 이유도

    포트나이트라는 게임을 하나의 새로운 플랫폼으로 만들게 된 것도 있고

    Verse가 얼마나 C++을 대체 가능할 만큼?

    또 입문자들이 쉽게 구현할 수 있게 잘 되어 있을까라는 의구심으로 진행 중이다.   

     

     

    상단 Verse 탭에서 Verse 익스플로러를 선택해 주고 프로젝트에서 새 Verse 파일을 추가한다.

    그러면 VS Code가 설치가 되거나 켜지게 될 것이다. 아마 익스텐션도 자동으로 설치가 되는 듯

     

    파일이 추가되면 콘텐츠 브라우저에도 추가되어서 해당 에셋을 레벨에 드래그해서 배치한다.

     

    using { /Fortnite.com/Devices }
    using { /Verse.org/Simulation }
    using { /UnrealEngine.com/Temporary/Diagnostics }
    
    
    Test_Verse01 := class(creative_device):
    
        OnBegin<override>()<suspends>:void=
            var StringType : string = "dd"
            var intType : int = 1
            var floatType : float = 1.0
            var boolType : logic = true
            
            if(boolType?):
                Print("str {StringType}, int {intType}, float {floatType}")
            else:
                Print("boolType Wrong")
    
            set boolType = false;
            Print("Make bool Type false\n\n")
    
            if(boolType?):
                Print("str {StringType}, int {intType}, float {floatType}")
            else:
                Print("boolType Wrong")

    디버깅 테스트를 위해 위처럼 대충 출력하는 코드를 입력해 주자.

    여기서 코드를 수정하거나 추가했을 때, 바로 변경사항 푸시를 하지 말고 빌드를 하자.

     

    변경 사항 푸시가 있고, Verse 변경 사항 푸시가 있는데, 변경사항 푸시는 한참 걸리니

    코드만 수정되었을 때는 코드만 푸시하는 걸 권장한다.

     

    아까 로그창에 정상적으로 출력되는 걸 확인할 수 있다.

    'STUDY > UEFN' 카테고리의 다른 글

    UEFN - 사라지는 바닥  (0) 2024.03.04
    COMMENT
     
    10
    18

    Chunk

    Chunk는 독립적으로 배포가 가능하고 다운로드를 가능하게 하는 에셋 묶음이다. 

     

     

    Chunk0은 기본 프로젝트 콘텐츠, 무조건적으로 프로젝트당 하나 있게 되고    

    언리얼 에디터에서 DataAsset 타입으로 PrimaryAssetLabel 파일을 추가해서

    Chunk1..2..3..?? 해당 디렉터리에 있는 파일을 다운로드 가능하게 묶는 것이 청크 세팅이다. 

     

    PakFile

    Unreal Automation Tool로 패키징 시 청크가 세팅된 대로 CDN을 위한 Pak 파일을 생성하는 과정이 이뤄진다.

    .Zip 파일 압축파일처럼 여러 개의 리소스를 압축해 놓은 것이다. 내부 구조는 아래 링크에서 굉장히 잘 설명해 준다.

    https://zhuanlan.zhihu.com/p/54531649

     

    UE4 Pak 文件格式

    UE4 打包过程中,会调用 UnrealPak 将 Cook 后的文件资源打包成一整个 Pak 文件,这个 Pak 中的内容可以分为三大块,按写入顺序分别为: 文件内容区 + 文件索引信息区 + Pak文件信息区文件内容区: 依

    zhuanlan.zhihu.com

     

    Pak 내부에는 리소스 내용 구간, 파일 인덱스 내용 구간, pak 파일 정보 내용 구간 3가지 구간으로 나뉜다.

    (구간이라고 말하는 것은 순차적으로 직렬 저장되기 때문)

     

    리소스 내용 구간

    Pak 파일의 시작 부분에 위치하고 각 파일의 FPakEntry와 실제 파일 내용을 차례로 저장한다.

    FPakEntry는 한 pak안에 수많은 리소스 중 한 개의 리소스이다. 리소스 크기와 pak 파일 안에 어디 있는지 알기 위한 offset이 있다

     

    파일 인덱스 내용 구간

    CDN을 받을 때 올바른 경로에 넣어주는 것 (마운트)을 하려면, Pak 파일 안에 수많은 리소스에 대한 경로..?

    모든 리소스 파일들은 Files에 저장되는데 각자마다 인덱스가 있다. 인덱스는 FPakDirectory 경로와 매핑돼있다. 또

    각 리소스 파일 이름과 인덱스 번호도 매핑된다. 

    엔진소스에서 UnrealPak.exe의 작동 방식을 확인 가능하다. 다 직렬화해서 저장하는 모습..

     

    pak 파일 정보 내용

    파일 마지막에 해당 내용이 있다. pak 파일의 마지막 위치( 45 바이트 로 고정)에 기록된다고 한다.

    IndexOffset ( Pak 파일 인덱스 정보 영역의 시작 위치 ),

    IndexSize ( 8바이트, Pak 파일 인덱스 정보 영역의 크기 ) ,

    IndexHash ( 20바이트, 파일 인덱스 정보의 SHA1 값 )

     


    UnrealPak.exe

    엔진경로\Engine\Binaries\Win64\UnrealPak.exe

     

    해당 경로에서 Pak파일을 생성하고 조회하고 압축해제 해주는 실행파일을 찾을 수 있다.

    명령어는 아래와 같이 확인해 볼 수 있다.

     

    UnrealPak <PakFilename> -Test
    UnrealPak <PakFilename> -List [-ExcludeDeleted]
    UnrealPak <PakFilename> <GameUProjectName> <GameFolderName> -ExportDependencies=<OutputFileBase> -NoAssetRegistryCache -ForceDependsGathering
    UnrealPak <PakFilename> -Extract <ExtractDir> [-Filter=<filename>]
    UnrealPak <PakFilename> -Create=<ResponseFile> [Options]

     

    일반적으로 위 명령어 대로 하면 되지만 Pak에 암호화가 걸려있을 때는 -CryptoKeys 명령어를 붙여줘야 한다. 그리고

    프로젝트에서 암호화 설정 시 자동으로 생성된 Crypto.Json의 파일 경로를 입력해줘야 한다. 

     

    배치 파일 조회 예시

    ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    :: Choi Jiwon 
    :: Pak 파일 정보 조회
    ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    @echo off
    
    SET EnginePath="{엔진경로}"
    SET PakPath="%~dp0{Pak 파일 경로}"
    SET CryptoFilePath="%~dp0Crypto.json"
    
    %EnginePath%\Engine\Binaries\Win64\UnrealPak.exe %PakPath% -Info -CryptoKeys=%CryptoFilePath%

     

    배치 파일 압축해제 예시

    ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    :: Choi Jiwon 
    :: Pak 파일 압축 해제
    ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    @echo off
    
    SET EnginePath="{엔진경로}"
    SET PakPath="%~dp0{팩 파일 경로}"
    SET CryptoFilePath="%~dp0Crypto.json"
    
    @echo "Extract Folder Created"
    
    if exist %PakPath%_extracted (
        rmdir /s /q %PakPath%_extract
    )
    
    %EnginePath%\Engine\Binaries\Win64\UnrealPak.exe %PakPath% -Extract %PakPath%_extracted -CryptoKeys=%CryptoFilePath%
    COMMENT
     
    10
    17

    언리얼 에디터에서 패키징하면 로그에서 실행되는 것을 볼 수 있듯

    UAT는 Unreal Automation Tool으로 빌드/패키징을 실행하는 배치파일이다.

     

    BuildCookRun 명령어로 에디터를 켜지 않고도 패키징 과정을 할 수 있는데,

    젠킨스, 자동화 툴을 통해 패키징을 할 수 있는 것이다. 

     

    엔진경로\Engine\Build\BatchFiles 경로에서 RunUAT 파일을 찾을 수 있다.

    Mac/Linux는. sh, Window는. bat 파일을 제공한다.

     

    RunUAT.bat -list

     

    명령어 리스트를 확인해보자

    자동화 패키징 시 필요한 것은 BuildCookRun 명령어이다.


    // Window(64비트) 프로젝트 빌드 예시 (DebugGame)
    
    RunUAT.bat BuildCookRun -project="<ProjectPath>.uproject" -platform=Win64
    -clientconfig=DebugGame -build -cook -stage -archive -archivedirectory="C:\Output" 
    
    // RAM Window(64비트) 프로젝트 빌드 예시 (Shipping)
    RunUAT.bat BuildCookRun -project="<ProjectPath>.uproject" -platform=Win64 -clientconfig=Shipping 
    -build -cook -stage -archive -archivedirectory="D:\Output" -nodebuginfo

     

    위 Shipping 예시에서 -nodebuginfo를 명령어 줄에 추가하는 이유는

    .pdb 디버그 파일을 포함하지 않기 위함이다. 

    필요한 명령이 필요하면 더 추가하면 된다. RunUAT.bat BuildCookRun -help로 더 자세히 볼 수 있음

    더보기

    Parameters:
        -project=Path                           Project path (required), i.e: -project=QAGame,
                                                -project=Samples\BlackJack\BlackJack.uproject,
                                                -project=D:\Projects\MyProject.uproject
        -destsample                             Destination Sample name
        -foreigndest                            Foreign Destination
        -targetplatform=PlatformName            target platform for building, cooking and deployment (also -Platform)
        -servertargetplatform=PlatformName      target platform for building, cooking and deployment of the dedicated
                                                server (also -ServerPlatform)
        -foreign                                Generate a foreign uproject from blankproject and use that
        -foreigncode                            Generate a foreign code uproject from platformergame and use that
        -CrashReporter                          true if we should build crash reporter
        -cook,                                  -cookonthefly Determines if the build is going to use cooked data
        -skipcook                               use a cooked build, but we assume the cooked data is up to date and where
                                                it belongs, implies -cook
        -skipcookonthefly                       in a cookonthefly build, used solely to pass information to the package
                                                step
        -clean                                  wipe intermediate folders before building
        -unattended                             assumes no operator is present, always terminates without waiting for
                                                something.
        -pak                                    generate a pak file
        -iostore                                generate I/O store container file(s)
        -cook4iostore                           generate I/O store container file(s)
        -zenstore                               save cooked output data to the Zen storage server
        -nozenautolaunch                        URL to a running Zen server
        -makebinaryconfig                       generate optimized config data during staging to improve loadtimes
        -signpak=keys                           sign the generated pak file with the specified key, i.e.
                                                -signpak=C:\Encryption.keys. Also implies -signedpak.
        -prepak                                 attempt to avoid cooking and instead pull pak files from the network,
                                                implies pak and skipcook
        -signed                                 the game should expect to use a signed pak file.
        -PakAlignForMemoryMapping               The game will be set up for memory mapping bulk data.
        -rehydrateassets                        Should virtualized assets be rehydrated?
        -skippak                                use a pak file, but assume it is already built, implies pak
        -skipiostore                            override the -iostore commandline option to not run it
        -stage                                  put this build in a stage directory
        -skipstage                              uses a stage directory, but assumes everything is already there, implies
                                                -stage
        -manifests                              generate streaming install manifests when cooking data
        -createchunkinstall                     generate streaming install data from manifest when cooking data, requires
                                                -stage & -manifests
        -skipencryption                         skips encrypting pak files even if crypto keys are provided
        -archive                                put this build in an archive directory
        -build                                  True if build step should be executed
        -noxge                                  True if XGE should NOT be used for building
        -CookPartialgc                          while cooking clean up packages as we are done with them rather then
                                                cleaning everything up when we run out of space
        -CookInEditor                           Did we cook in the editor instead of in UAT
        -IgnoreCookErrors                       Ignores cook errors and continues with packaging etc
        -nodebuginfo                            do not copy debug files to the stage
        -separatedebuginfo                      output debug info to a separate directory
        -MapFile                                generates a *.map file
        -nocleanstage                           skip cleaning the stage directory
        -run                                    run the game after it is built (including server, if -server)
        -cookonthefly                           run the client with cooked data provided by cook on the fly server
        -Cookontheflystreaming                  run the client in streaming cook on the fly mode (don't cache files locally
                                                instead force reget from server each file load)
        -fileserver                             run the client with cooked data provided by UnrealFileServer
        -dedicatedserver                        build, cook and run both a client and a server (also -server)
        -client                                 build, cook and run a client and a server, uses client target configuration
        -noclient                               do not run the client, just run the server
        -logwindow                              create a log window for the client
        -package                                package the project for the target platform
        -skippackage                            Skips packaging the project for the target platform
        -neverpackage                           Skips preparing data that would be used during packaging, in earlier
                                                stages. Different from skippackage which is used to optimize later stages
                                                like archive, which still was packaged at some point
        -distribution                           package for distribution the project
        -PackageEncryptionKeyFile               Path to file containing encryption key to use in packaging
        -prereqs                                stage prerequisites along with the project
        -applocaldir                            location of prerequisites for applocal deployment
        -Prebuilt                               this is a prebuilt cooked and packaged build
        -AdditionalPackageOptions               extra options to pass to the platform's packager
        -deploy                                 deploy the project for the target platform
        -getfile                                download file from target after successful run
        -IgnoreLightMapErrors                   Whether Light Map errors should be treated as critical
        -trace                                  The list of trace channels to enable
        -tracehost                              The host address of the trace recorder
        -tracefile                              The file where the trace will be recorded
        -sessionlabel                           A label to pass to analytics
        -stagingdirectory=Path                  Directory to copy the builds to, i.e. -stagingdirectory=C:\Stage
        -optionalfilestagingdirectory=Path      Directory to copy the optional files to, i.e.
                                                -optionalfilestagingdirectory=C:\StageOptional
        -optionalfileinputdirectory=Path        Directory to read the optional files from, i.e.
                                                -optionalfileinputdirectory=C:\StageOptional
        -CookerSupportFilesSubdirectory=subdir  Subdirectory under staging to copy CookerSupportFiles (as set in Build.cs
                                                files). -CookerSupportFilesSubdirectory=SDK
        -unrealexe=ExecutableName               Name of the Unreal Editor executable, i.e. -unrealexe=UnrealEditor.exe
        -archivedirectory=Path                  Directory to archive the builds to, i.e. -archivedirectory=C:\Archive
        -archivemetadata                        Archive extra metadata files in addition to the build (e.g.
                                                build.properties)
        -createappbundle                        When archiving for Mac, set this to true to package it in a .app bundle
                                                instead of normal loose files
        -iterativecooking                       Uses the iterative cooking, command line: -iterativecooking or -iterate
        -CookMapsOnly                           Cook only maps this only affects usage of -cookall the flag
        -CookAll                                Cook all the things in the content directory for this project
        -SkipCookingEditorContent               Skips content under /Engine/Editor when cooking
        -FastCook                               Uses fast cook path if supported by target
        -cmdline                                command line to put into the stage in UECommandLine.txt
        -bundlename                             string to use as the bundle name when deploying to mobile device
        -map                                    map to run the game with
        -AdditionalServerMapParams              Additional server map params, i.e ?param=value
        -device                                 Devices to run the game on
        -serverdevice                           Device to run the server on
        -skipserver                             Skip starting the server
        -numclients=n                           Start extra clients, n should be 2 or more
        -addcmdline                             Additional command line arguments for the program
        -servercmdline                          Additional command line arguments for the program
        -clientcmdline                          Override command line arguments to pass to the client
        -nullrhi                                add -nullrhi to the client commandlines
        -fakeclient                             adds ?fake to the server URL
        -editortest                             rather than running a client, run the editor instead
        -RunAutomationTests                     when running -editortest or a client, run all automation tests, not
                                                compatible with -server
        -Crash=index                            when running -editortest or a client, adds commands like debug crash, debug
                                                rendercrash, etc based on index
        -deviceuser                             Linux username for unattended key genereation
        -devicepass                             Linux password
        -RunTimeoutSeconds                      timeout to wait after we lunch the game
        -SpecifiedArchitecture                  Determine a specific Minimum OS
        -UbtArgs                                extra options to pass to ubt
        -MapsToRebuildLightMaps                 List of maps that need light maps rebuilding
        -MapsToRebuildHLODMaps                  List of maps that need HLOD rebuilding
        -ForceMonolithic                        Toggle to combined the result into one executable
        -ForceDebugInfo                         Forces debug info even in development builds
        -ForceNonUnity                          Toggle to disable the unity build system
        -ForceUnity                             Toggle to force enable the unity build system
        -Licensee                               If set, this build is being compiled by a licensee
        -NoSign                                 Skips signing of code/content files.

    예를 들어 패키징 시에 Pak 파일을 포함시키려면 

    RunUAT.bat BuildCookRun -project="<ProjectPath>.uproject" -platform=Win64 -clientconfig=Shipping 
    -build -cook -stage -pak -archive -archivedirectory="D:\Output" -nodebuginfo

    위처럼 명령어를 계속 추가하면 된다. 

     

    또한 아래처럼 배치파일로 원하는 패키징을 얻을 수 있다.

    @echo off
    
    REM The location of the UAT batch file.
    set UAT="<EngineDirectory>\Engine\Build\BatchFiles\RunUAT.bat"
    REM The location of your Unreal project.
    set PROJECT="<ProjectPath>.uproject"
    REM The location where the builds are going to be stored.
    set OUTPUT="D:\Output"
    
    REM Build both Shipping and DebugGame
    call %UAT% BuildCookRun -project=%PROJECT% -platform=Win64 -clientconfig=Shipping -build -cook -stage -archive -archivedirectory="%OUTPUT%\Shipping" -nodebuginfo
    call %UAT% BuildCookRun -project=%PROJECT% -platform=Win64 -clientconfig=DebugGame -build -cook -stage -archive -archivedirectory="%OUTPUT%\DebugGame"

     

     

    https://greenforestgames.eu/article/Building-Unreal-projects-with-UAT-1605886728

    COMMENT
     
    01
    02

    https://www.unrealengine.com/en-US/blog/download-our-new-blender-addons

     

    Download our new Blender addons

    We’ve released two new, free addons that greatly streamline the workflow between Blender and Unreal Engine. 

    www.unrealengine.com

     

    2020년 7월 30일 Blender Addon이 추가되었다.

    이를 이용하면 리깅과 익스포트가 용이해진다고 한다.

     다운로드하기 위해서는 언리얼 엔진 홈페이지에서 깃허브 계정을 연동해야 한다.

    이와 같은 화면이 뜨면 언리얼 레포지에 접근할 수 있게 된다. 

    아래 링크도 접속이 안된다면 위와 같은 절차를 밟아야 한다. 

    https://github.com/EpicGames/BlenderTools/releases?q=Send+to+Unreal&expanded=true

    위 링크가 Send2ue 블렌더 에드온이다. 

     

     

    다운로드하였다면 Blender Add-ons에서 해당 에드온을 추가한다.

    Blender 2.8부터 지원하는 것으로 알고 있다. 파이썬 지원하는 버전이면 가능하다

     

    언리얼에서는 플러그인 2개를 활성화해주어야 한다.

     

    그리고 프로젝트 세팅에서 파이썬 원격 실행 Enable Remote Excution를 켜준다.

    블렌더에서 수정해서 보내면 엔진으로 명령하도록 하게 한다. 

     

    새로 생긴 Pipeline 탭에서 세팅(Export > Setting Dialog) 적용할 프로젝트의 경로를 설정해 준다.

     

    블렌더 수정 후 Ctrl + U를 누르거나 Pipeline 탭에서 Export send to UE를 선택하면 

    수정된 블렌더가 즉각적으로 Uasset으로 변환되고 프로젝트에 적용이 된다. 

     

    예시 

     

    애니메이션도 포함된다고 하니 리깅 할 때도 유용한 워크플로우가 형성될 것 같다.

    결과 영상

    https://youtu.be/YBnwVDvqjNo

     

    COMMENT
     
    10
    21

    vs19로 언리얼 자동완성 기능을 위해서 Visual Assist X를 사용했었는데

     

    Visual Studio 2022가 64버젼으로 나오면서 

    Visual Assist X도 21년도에 새로 나왔다.

     

    요즘엔 Rider로 개발을 해서 Visual studio와 멀어졌지만,

    아직도 VS의 투박한 매력을 잊지 못하고 산다. 

     

    얼마나 빨라지고 편해졌을지 기대가 되면서

    설치를 해보겠다. (주말에)

    https://www.wholetomato.com/downloads

     

     

    'ETC' 카테고리의 다른 글

    개인정보처리방침  (0) 2021.05.12
    COMMENT
     
    10
    03

    https://github.com/jiwonchoidd/Jiwon_opengl

    1. 서론

    다이렉트X는 윈도우 플랫폼에 종속적이고 COM기반으로 제작되었다.

    기본적으로 윈도우에는 해당 SDK가 내장되어 쉽게 환경 구성을 할 수 있다.

    OpenGL 자체는 실제 구현된 라이브러리가 아니라 API 스펙 그 자체여서

    그래픽카드와 상호작용하는 기능만 있고, 그게 어떤 플랫폼의 그래픽 카드

    인지는 모르는 API이다. 그래서 남들이 만든 라이브러리를 사용해서 

    그래픽카드와 연결한다.

    GLFW, SDL, Freeglut 등 있지만 나는 많이 사용하는 GLFW를 사용함.

     

    2. 설치한 라이브러리

    GLFW 3.3.8 version installed  // https://www.glfw.org/

    ㄴ 앞서 말했다싶이 디바이스 연결용

    GLEW 2.1.0 version installed // https://glew.sourceforge.net/

    ㄴ윈도우가 구버전 opengl 지원해서 높은 버전을 위해 사용함

    GLM

    ㄴ이건 수학 라이브러리, 필요하면 받자

     

    3. 환경 설정 및 화면 띄우기

    콘솔용 메인함수 int main을 쓰든 윈도우용 winmain을 쓰든

    환경 설정을 완료하기 위해 일단 창을 띄워보자.

     

    프로젝트 include lib 폴더에 각각 파일을 넣어주었다.

    비주얼 스튜디오를 켜고 넣은 include와 lib 연결을 해준다.

     

    추가 포함 디렉터리에 헤더 폴더 연결
    라이브러리 폴더 연결

     

    속성에 라이브러리 이름을 기입해서 연결할 수 있지만, 

    나는 라이브러리와 인크루드를 관리하는 헤더 하나를 만들었다.

     

    //DD_Std.h
    
    #pragma once
    #pragma comment	(lib, "glew32.lib")
    #pragma comment	(lib, "glfw3.lib")
    #pragma comment	(lib, "opengl32.lib")
    #include "glew.h"
    #include "glfw3.h"

     

    위 헤더를 메인 함수에 연결시켜서 잘 연결되었는지 확인해보자.

    아래는 메인함수이다. 위 std 헤더를 연결해주었다. 

     

    #include "DD_MainCore.h"
    #include "DD_Std.h"
    int main()
    {
        GLFWwindow* window; 
    
        if (false == glfwInit())
            return -1;
    
        window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
        if (nullptr == window)
        {
            glfwTerminate(); 
            return -1;
        }
    
    
        glfwMakeContextCurrent(window); 
        glewInit(); 
        glClearColor(0.5, 0.75, 1, 1);
    
    
        while (!glfwWindowShouldClose(window))
        {
            glClear(GL_COLOR_BUFFER_BIT); 
            glfwSwapBuffers(window); 
            glfwPollEvents(); 
        }
    
        glfwTerminate();
        return 0;
    }

     

    논외지만 다렉보다 굉장히 간단해서 놀랐다. 

    빌드를 해서 본다면 아래와 같은 화면이 나올 것이다.

     

     

    동적 라이브러리 dll 파일이 없다고 나온다면 아까 glew에서 받은 dll 파일을

    실행파일 위치에 같이 넣어주면 해결이 된다. 

    아래 경로에 있다.

    이 위치에 있다.

     

     

    이렇게 해서 opengl 환경설정을 마치고 창까지 띄워보았다.

    추가적으로 엔진 라이브러리 프로젝트와  이를 사용하려는 프로젝트를 구분하였다.

     

    엔진 및 사용 프로젝트 구분

    기존 프로젝트를 출력을 Lib로 하고 새로운 프로젝트에서

    그 라이브러리를 사용하면 된다. 빌드후처리로 바로 작업 폴더에

    옮기게 자동화하는 걸 추천한다.

    #include "DD_MainCore.h"
    
    void Framebuffer_size_callback(GLFWwindow* window, int width, int height);
    void processInput(GLFWwindow* window);
    
    void DD_MainCore::Start()
    {
        // glfw: 초기화 및 설정
        // ------------------------------
        glfwInit();
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    
    #ifdef __APPLE__
        glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    #endif
    
        // glfw 윈도우 생성
        // --------------------
        pWindow = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
        if (pWindow == NULL)
        {
            glfwTerminate();
            return;
        }
        glfwMakeContextCurrent(pWindow);
        glfwSetFramebufferSizeCallback(pWindow, Framebuffer_size_callback);
    
        // glew 초기화
        glewInit();
    }
    void DD_MainCore::Frame()
    {
        // render loop
        // -----------
        while (!glfwWindowShouldClose(pWindow))
        {
            // input
            // -----
            processInput(pWindow);
    
            // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
            // -------------------------------------------------------------------------------
            glfwSwapBuffers(pWindow);
            glfwPollEvents();
        }
    }
    
    void DD_MainCore::Release()
    {
        glfwTerminate();
        glfwDestroyWindow(pWindow);
        pWindow = nullptr;
    }
    void Framebuffer_size_callback(GLFWwindow* window, int width, int height)
    {
        glViewport(0, 0, width, height);
    }
    void processInput(GLFWwindow* window)
    {
        if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS)
            glfwSetWindowShouldClose(window, true);
    }

     

    Sample에서는 이런식으로 우리가 만든 라이브러리를 사용하면 된다.

    #pragma once
    #pragma comment	(lib, "ddEngine.lib")
    #include "DD_MainCore.h"
    int main()
    {
    	DD_MainCore* gEngine = new DD_MainCore();
    
    	gEngine->Start();
    
    	gEngine->Frame();
    
    	gEngine->Release();
    
    	delete gEngine;
    	gEngine = nullptr;
    
    	return -1;
    }

     

    이런식으로 나누면 나중에 작업할때 편할 것이다.

    COMMENT
     
    07
    28

    Effective C++ 책을 보고 정리한 글입니다.


    클래스가 비어있다고 해도 클래스 안에 직접 선언을 안 해도 

    자동으로 컴파일러가 생성하는 함수는 생성자, 복사 생성자, 복사 대입 연산자, 소멸자 등 이 있다.

    모두 public의 접근제어자를 가지며 inline함수이다.

     

    자동으로 만들어지는 클래스의 함수들

    class Test{}; // 이렇게 빈 클래스를 만들면
    // 아래 함수가 자동으로 생성됨
    class Test{
    public:
    	Test(){}; //기본 생성자
        Test(const Test& rhs){}; //복사 생성자
        ~Test(){};//소멸자
        
        Test& operator=(const Test& rhs){};//복사 대입 연산자
    };

     

    컴파일러가 자동으로 만들어주는 함수가 필요가 없다면

    사용을 못하게 막아둘 필요가 있다. 

    하지만 위에서 말했듯이 public 접근제어를 갖는다.

    private으로 선언한다해도 friend 함수가 호출할 수 있다는 문제점이 있다.

    friend : private 멤버 변수를 접근 가능하게 하는 키워드

     

    멤버 함수를 private으로 선언하고 정의하지 않는 방법을 사용하면 된다.

    c++ iostream 라이브러리에서도 복사 방지책으로 사용한다고 한다.

     

    class UncopyUtil{
    protected: //상속된 것만 접근 가능
    	UncopyUtil(){};
    	~UncopyUtil(){};
    
    private:
    	UncopyUtil(const UncopyUtil& rhs); //복사생성, 복사대입 방지
    	UncopyUtil& operator=(const UncopyUtil& rhs);
    };

     

    class Test : private UncopyUtil {
    ...
    };

     

    복사를 외부에서 시도할때 컴파일러는 자동으로 생성하려 하는데 접근이 불가능하므로

    기능을 허용치않는 효과를 얻을 수 있다. 

    이와 같이 상속을 통해 여러 클래스를 막을 수도 있지만 비슷한 기본 클래스를 만들어두는 것도 

    좋을 것 같다. 다중 상속 문제가 생길 수도 있기 때문이다.

    COMMENT
     
    06
    09

    언리얼 팀 프로젝트를 진행하면서, 

    분업화를 위해서 각자 플러그인, 모듈을 만들어서

    작업을 진행했다. 

     

    1. 플러그인 제작

    동적 라이브러리인 dll과 같다. 

    모듈 제작을 위해서는 모듈 폴더와 빌드 설정 파일(Build.cs) 파일이 있어야함

    모듈의 정의를 해주는 파일은 모듈이름으로 된 .cpp파일이다.

     

    언리얼은 개발은 c++로 하고 프로젝트 빌드 관리는 c#으로 하는 것 같다.

     

     

    2. 프로젝트에 c++ CDO 객체 적재 실패

    언리얼 프로젝트에서 저장을 해주는 클래스를 게임 인스턴스에서 

    미리 생성해두고 사용하려니까 계속해서 CDO 참조가 안되는 문제가 있었다. 

     

    연결하고 껐다키면 이렇게 해당 플러그인 클래스가 싹 다 빠져있음

     

    플러그인 안에 있는 C++에서 제작한 클래스를 미리 적재를 못한다는 느낌이 들어서

    언리얼 포럼에서 찾아보니까 다른 모듈보다 먼저 로딩하도록 하는 플래그를 기입하니 해결 되었다.

    LoadingPhase를 "Default"에서 "PreDefault"로 바꿔주었다.

     

    https://forums.unrealengine.com/t/failed-to-load-c-class-plugin-after-editor-restart/484156

     

    Failed to load c++ class (plugin) after editor restart

    Hey guys, I implemented a plugin that contains an abstract c++ parent class (InventorySlotUI) and a BP widget that inherits from it (SimpleInventorySlotUI) in the content folder. Another BP widget (InventoryUI) is using this and the first time I put everyt

    forums.unrealengine.com

     

    COMMENT
     
    05
    24

    언리얼은 무조건 UObject에서 파생된다.

    언리얼엔진에서 관리되는 가비지 컬렉션 쓸라면 UObject를 상속 받아야함

     

    1. CDO

    UClass() 매크로를 구성하면 언리얼 클래스가 된다.

    컴파일 단계에서 언리얼 오브젝트마다 UClass가 생성된다면,

    실행 초기의 런타임 과정에서는 언리얼 오브젝트 마다 클래스 정보와 함께

    언리얼 오브젝트의 인스턴스가 생성된다. <- 이 인스턴스는 언리얼 기본 세팅을 지정하는데 사용함.

    클래스 기본 객체 (Class Default Object) CDO라고 함.

     

    CDO로 복사해서 실제로 런타임에서는 복사본으로 작동한다. 

    CDO를 만듬으로서 오브젝트를 생성할때마다 매번 초기화 안하고 기본 인스턴스를 미리

    만들어놔 복제하는 방식으로 인스턴싱같은 기술? 인가보다.

     

    언리얼 오브젝트의 로딩은 

    모듈 로딩->모듈에 속한 모든 UObject의 클래스 정보 등록 -> 각 클래스 정보의 CDO 객체 생성

    -> 언리얼 오브젝트의 생성자를 호출해 CDO 완성

     

    2. UHT? GENERATE_BODY?

    언리얼 헤더 툴(UHT)에서 Generated.h 생성함, 헤더 맨 마지막에 와야만 함.

    GENERATED_BODY() 매크로는 복사생성자,

    기본 UE 타입 시스템에 자동으로 생성된 기능을 포함하도록 확장된 매크로 GENERATED_BODY 

    PRIVATE로 생성자를 외부에서 사용 못하게, 언리얼 메카니즘에서 벗어나지 않게끔한다.

     

    https://dlemrcnd.tistory.com/96?category=517587 

     

    UE5 - C++와 블루프린트 연동 UPROPERTY(), UFUNCTION()

    UPROPERTY() UPROPERTY()는 변수에 붙는 리플렉션 매크로다. 매크로에 인자값을 넣어서 용도에 맞게 사용이 가능, 인자 값 순서는 상관이 없지만, 규칙이 존재함 1. 변수 공개 & 수정 권한 VisibleDefaultsOnly

    dlemrcnd.tistory.com

     

    이전 포스팅에서 UCLASS, UFUNCTION, UPROPERTY의 매크로에 대해서 다뤘는데,

    이런 매크로는 상속관계를 맺는다. 그래서 기본적으로 AACTOR를 상속받은 액터 클래스는

    블루프린트 가능하게 되어진다.

    액터는 거의 모든 UCLASS 매크로 가 붙어져있어서

    액터는 기본적으로 블루프린트 매크로를 굳이 안붙여도 됨.

     

    3. New가 아닌 언리얼 생성, 팩토리 함수

    블루프린트 드롭다운 메뉴에서 받아올수있는것,

    new 대신 특별한 팩토리 함수를 호출하도록 요구함

    AActor는 SpawnActor<>

    UObject 인스턴스화는 ConstructObject<> 또는 NewObject<>를 사용한다.

    언리얼 5로 넘어가면서 ConstructObject를 배제했다 블루프린트에는 아직 사용가능

     불편하게 NewObject에는 호출마다 GetRransientPackage()를 전달해야하는 첫번째 매개변수가 있음

    ObjectType* object = NewObject<ObjectType>(ObjectType*)GetTransientPackage(), ObjectType::StaticClass());
    
    ObjectType* obejct = ConstructObject<ObjectType>(UClassReference) 오브젝트 인스턴스화가능

     

    StaticClass()를 사용하면 CDO, 오브젝트 베이스 UClass* 를 얻을 수 있다. 

    GetTranientPackage() 단순 휘발성 패키지 얻어옴,  ConstructObejct와 다르게 좀 더 많은 파라미터 제공

    팩토리 디자인 패턴를 사용함.

     

    4. 언리얼 스마트 포인터

    native c++ 가 아닌 언리얼 스마트 포인터는

    직접 언리얼 가비지 컬렉션에 속하지 않아도 메모리 프로그래밍할때 사용한다.

    TSharedPtr, TWeakPtr, TAutoPtr

    언리얼 버젼으로 포팅한것이다.  

     

    5. FClassFinder, FObjectFinder 구분해서 사용 

    둘다 Constructor Helper로 생성자에서만 사용가능하다. CDO 제작에서만 사용됨

    FObjectFinder는 CDO 객체를 찾는다.

    반면에 FClassFinder는 UClass객체를 찾는다.

    객체 초기화할때 프로젝트에 포함된 다른 클래스나 오브젝트 리소스 가져와야 할때

    c++ 코드에서 CDO가 아닌 실제 클래스 가져올때 사용한다. 

    static ConstructorHelpers::FClassFinder<APawn> BPClass(TEXT("/Game/Blueprints/Bp_Class"));
    if (BPClass.Succeeded() && BPClass.Class != NULL)
    {
        // 가져온 BPClass.Class를 통한 작업
    }

     

    6. FSoftClassReference, TSubClassOf<c++classname>

    FStringClassReference 이름에서 해당이름으로 바뀜

    스트링으로 참조하겠다는 뜻.

    블루프린트에서 MetaClass 태그로 만든것을 해당 c++클래서에서 파생된 블루프린트로만 제한함,

    이 방법도 있지만

    TSubClassOf<c++classname> // 클래스 레퍼런스를 받는것, CDO 객체를 받아올 수 있음</c++classname>

    UClass 이름을 지정해서 객체 받아옴

     

    7. ETC

    GEngine 엔진 포인터 외부변수

    GEngine->AddOnScreenDebugMessage(-1, 10, FColor::Red, TEXT(""))
    
    //블루프린트 Print string과 같은 내용

     

    FTimerHandle Timer;
    
    GetWorldTimerManager().SetTimer(Timer, this, ..., 10);
    
    //시간 타이머

     

    //매쉬 컴포넌트 생성, 생성자에서만 호출가능
    
    Mesh = CreateDefaultSubobject<UStaticMeshComponent>("이름");

    생성자에서만 할당가능함

    auto MeshAsset = ConstructorHelpers::FObjectFinder<UStaticMesh>(TEXT("에셋경로"));
    
    if(MeshAsset.Object!=nullptr)//유효 검사
    
    //ConstructHelper로 에셋으로 매쉬를 가져옴

    경로 가져오는건 에셋 오른쪽 마우스 경로 복사가 있음.

     

    부모자식 하이라키

    //오브젝트 계층설정

    BoxOne->AttachTo(Root);
    
    BoxTwo->AttachTo(ChildSceneComponent);
    
    ChildSceneComponent->SetRelativeTransform(FTransform(FRotator(0,0,0), FVector(0,0,0), FVector(0.1f)));

     

    Tick, TickComponent

    액터 틱과 컴포넌트 틱의 차이

    PrimaryComponentTick.bCanEverTick = true; 매 틱마다 발생

     

    BlueprintSpwanableComponent 추가하면 클래스 추가가능

    UCLASS(ClassGroup =(custom), meta =(BlueprintSpawnableComponent))

    유클래스 매크로는 상속이된다.

     

    열거형 변수 UENUM() 매크로

     

    COMMENT
     
    05
    22

    언리얼 5가 정식 출시되면서 

    Control rig와 Fullbody IK가 정식 탑재 되었다. 

    기존에는 플러그인에서 추가를 해야 사용이 가능했지만, 이제는 바로 사용이 가능하다.

     

    이전에 개인 프로젝트에서 Control rig와 Fullbody IK를 활용해

    어떤 지형이든 바닥에 닿게 하는 기능을 제작했는데, 굉장히 유용했다. 

     

    팀프로젝트를 진행하면서 캐릭터 커스터마이징을 구현할 기회가 생겨서 

    현업 분들은 어떻게 구현했을지 모르지만.. 이를 이용하면

    뼈를 조절하기 편할 것 같아서 사용해보았다.

     

    1. 컨트롤 릭 생성

     

     

    원하는 캐릭터의 본 계층을 불러온다. 

     

    2. 컨트롤 생성

     

    뼈를 조정할 새 컨트롤를 생성하고, 원하는 뼈 위치에 컨트롤을 가져다 놓는다,

     

     

    가장 가까운 본에서 Offset 트랜스폼 설정하면 알아서 근처 뼈 위치에

    놓아진다. 컨트롤 쉐이프는 디테일에서 수정 가능.

     

    3. Fullbody IK 설정, 및 SetTransform Bone

     

    풀바디 IK를 생성해, 원하는 본에다가 컨트롤 트랜스폼을 넣어주면, 

    컨트롤 행렬이 본에 입혀진다. 

    이 외, 원하는 뼈 설정이나, 제외할 뼈, 등등 많은 설정을 쉽게 할 수 있는게 Fullbody IK이다.

    상속된 뼈들을 유연하게 조절할 수 있는 플러그인이다.

    하지만, 캐릭터 커스터마이징에서의 조절은 단일 뼈를 조절하는게 맞기 때문에,

    그냥 뼈에 Set Transform를 하는게 더 적절해 보여서 Fullbody IK의 사용을 배제했다.

     

    4. 결과

    COMMENT
     
    05
    12

    소수는 자기자신만으로만 나눌 수 있는 값이다.

    그래서 2부터 자기자신 숫자 전까지만 반복문으로 돌아서

    나뉘어질 경우에 소수가 아님을 판별하는 로직으로 하니, 

    효율성이 실패함. 에라토스테네스의 체를 사용하면 쉽게 해결 가능.

     

    n까지의 소수를 알고 싶을때, n*1/2이하의 수의배수만 지우면 됨.

     

    2부터 시작해서 특정 수의 배수에 해당하는 수를 모두 지운다.

     -> 2를 제외한 2의 배수 지우고 ...3를 제외한 3의배수 지우고..반복..

     

    코드

    vector<bool> arr(n+1);
    arr[1] = true;
    for(int i = 2; i <= sqrt(n); i++){
        if(arr[i]) continue;
        for(int j = i + i; j <= n; j += i)
            arr[j] = true;
    }
    
    // 소수 출력
    for(int i = 2; i <= n; i++)
    	if(!arr[i]) cout<< i << endl;

     

    시간 복잡도

    제곱근까지만 약수의 여부를 검증하면 O(N^1/2)로 가능

     

    'STUDY > Algorithm' 카테고리의 다른 글

    정렬 알고리즘 (삽입, 선택, 버블, 병합)  (0) 2021.12.16
    COMMENT