UE5 Verse 언어 입문 — UEFN 스크립팅
Verse는 Epic Games가 UEFN(Unreal Editor for Fortnite)을 위해 개발한 함수형 + 객체지향 혼합 프로그래밍 언어입니다. 결정론적 동시성, 실패 가능(failable) 표현식, 강력한 타입 시스템이 특징이며, 향후 UE 엔진 전체로 확장될 예정입니다.
1. 기본 문법
섹션 제목: “1. 기본 문법”# 주석은 #으로 시작using { /Fortnite.com/Devices }using { /Verse.org/Simulation }
# 변수 선언var Count : int = 0 # 가변 변수Name : string = "Player" # 불변 변수
# 타입 추론var Score := 100 # int로 추론
# 함수 선언Greet(PlayerName : string) : string = "안녕하세요, {PlayerName}님!"
# 반환 타입 없는 void 함수PrintScore(Score : int) : void = Print("점수: {Score}")2. 타입 시스템
섹션 제목: “2. 타입 시스템”# 기본 타입var I : int = 42var F : float = 3.14var B : logic = true # bool 대신 logicvar S : string = "hello"
# 옵션 타입 (nullable 대신)var MaybePlayer : ?player = false # 없음if (P := MaybePlayer?): # 언래핑 Print("플레이어 있음: {P}")
# 배열var Items : []string = array{"sword", "shield"}Items += array{"potion"}
# 맵var Scores : [string]int = map{"Alice"=>100, "Bob"=>85}
# 튜플var Pos : tuple(float, float, float) = (1.0, 2.0, 3.0)3. 실패 가능 표현식 (Failable)
섹션 제목: “3. 실패 가능 표현식 (Failable)”# Verse의 핵심 개념: 표현식은 성공 또는 실패할 수 있음# if 블록이 실패 컨텍스트를 제공
FindPlayer(Name : string) : ?player = # 실패 가능 컨텍스트 if (P := GetPlayerByName(Name)?): P else: false # 실패 반환
# 연쇄 실패: 하나라도 실패하면 전체 실패if: Player := FindPlayer("Alice")? Health := Player.GetHealth()? Health > 0then: Print("Alice는 살아있습니다")else: Print("Alice를 찾을 수 없거나 사망")
# 실패 가능 함수 정의GetTopPlayer()<decides><transacts> : player = Players := GetActivePlayers() Players[0] # 비어있으면 실패4. 동시성 모델
섹션 제목: “4. 동시성 모델”# Verse의 구조적 동시성# spawn: 비동기 태스크 시작MyTask := spawn: loop: Sleep(1.0) UpdateScoreboard()
# race: 먼저 완료된 것만 선택race: block: Sleep(10.0) Print("10초 경과") block: WaitForPlayerAction() Print("플레이어가 먼저 행동함")
# sync: 모두 완료될 때까지 대기sync: LoadAssetA() LoadAssetB() LoadAssetC()Print("모든 에셋 로드 완료")
# 채널 통신Channel := channel(int){}
spawn: Channel.Send(42)
Value := Channel.Receive()Print("수신: {Value}")5. 클래스와 인터페이스
섹션 제목: “5. 클래스와 인터페이스”# 인터페이스 정의damageable := interface: TakeDamage(Amount : float) : void GetHealth() : float
# 클래스 구현enemy := class(damageable): var Health : float = 100.0 Name : string
# 인터페이스 구현 TakeDamage(Amount : float) : void = set Health = Max(0.0, Health - Amount) if (Health <= 0.0): OnDeath()
GetHealth() : float = Health
OnDeath() : void = Print("{Name} 사망")
# 상속boss_enemy := class(enemy): var Phase : int = 1
override TakeDamage(Amount : float) : void = # 1페이즈에서 데미지 감소 ActualDamage := if (Phase = 1): Amount * 0.5 else Amount super.TakeDamage(ActualDamage)6. UEFN 게임플레이 디바이스
섹션 제목: “6. UEFN 게임플레이 디바이스”# 트리거 디바이스와 연동using { /Fortnite.com/Devices }using { /Verse.org/Simulation }
trigger_handler := class(creative_device):
# 에디터에서 드래그한 디바이스 참조 @editable MyTrigger : trigger_device = trigger_device{}
@editable var RewardAmount : int = 100
# 게임 시작 시 자동 호출 OnBegin<override>()<suspends> : void = # 트리거 이벤트 구독 MyTrigger.TriggeredEvent.Await() OnTriggered()
OnTriggered() : void = Print("트리거 발동! 보상: {RewardAmount}") # 모든 플레이어에게 점수 지급 for (P : GetActivePlayers()): if (FortChar := P.GetFortCharacter[]): FortChar.GiveScore(RewardAmount)7. 오류 처리 패턴
섹션 제목: “7. 오류 처리 패턴”# 실패 가능 + 옵션 조합 패턴SafeDivide(A : float, B : float)<decides> : float = B <> 0.0 # B가 0이면 실패 A / B
# 사용if (Result := SafeDivide(10.0, 0.0)?): Print("결과: {Result}")else: Print("0으로 나눌 수 없음")
# 기본값 패턴GetPlayerScore(P : player) : int = if (Score := ScoreMap[P]?): Score else: 0Verse의 핵심은 실패 가능 표현식과 구조적 동시성입니다. if/else가 단순 조건분기가 아니라 실패 컨텍스트를 제공하며, ? 연산자로 옵션 값을 안전하게 언래핑합니다. spawn, race, sync로 비동기 게임플레이 로직을 명확하게 구조화하고, @editable로 에디터에서 디바이스를 연결하는 패턴이 UEFN 개발의 기본 워크플로입니다.