fbx 파일은 3D 모델, 애니메이션, 재질 등을 저장하고 교환하기 위해 널리 사용되는 파일 형식이다.
이 fbx 파일에는 다양한 3D 소프트웨어 간에 데이터를 전송하기 위한 복잡한 계층 구조와 네임스페이스가 포함될 수 있는데 네임스페이스를 유지하게 되면 이름 충돌을 피하고, 객체를 논리적으로 그룹화하며 특정 객체를 고유하게 식별하는 데 사용된다.
리임포트 시 임포트 대화창 표시
사용자가 fbx를 리임포트 할 때 fbx 옵션 대화창이 표시된다.
리임포트는 이미 가져온 파일을 다시 가져올 때 임포트 대화창을 표시할지 여부를 결정하는 옵션이다.
리임포트는 한번 가져온 외부 파일을 다시 가져오는 과정으로 외부에서 파일이 수정되었을 때 변경된 내용을 언리얼 엔진 프로젝트에 반영하기 위해 사용된다. 임포트 대화창은 파일을 언리얼 엔진으로 가져올 때 다양한 임포트 옵션을 설정할 수 있는 인터페이스를 제공한다.
리임포트 시 임포트 대화창 표시를 활성화했을 때 리임포트 시 보이는 창
데이터 소스 폴더
리임포트 프로세스를 편하게 하기 위해 상대 소스 파일 경로를 저장할 프로젝트 데이터 소스 폴더를 지정한다.
특정 폴더를 지정하게 되면 언리얼 엔진에서는 이 폴더를 소스 데이터의 기본 위치로 인식하게 되고 텍스처, 모델, 오디오 파일 등 다양한 에셋을 위치한 폴더에 저장하게 된다.
애니메이션 리임포트 경고
애니메이션의 시퀀스 길이와 커브를 예전 데이터와 비교하고 변경사항이 있을 경우 사용자에게 알려준다.
익스포트
어태치 계층구조 유지
활성화 시 어태치먼트 계층 구조도 익스포트 한다.
어태치먼트 계층구조란 오브젝트 간의 부모-자식 관계를 말한다. 이는 오브젝트를 서로 연결하여 한 오브젝트의 변환(위치, 회전, 크기)이 다른 오브젝트에 영향을 미치도록 설정하는 기능이다.
모델을 언리얼 엔진에 익스포트 할 때 어태치먼트 계층구조를 유지하면 원본 모델의 부모-자식 관계가 언리얼 엔진에서도 동일하게 적용된다. 이는 외부 3D 소프트웨어에서 설정한 계층구조가 언리얼 엔진에서도 동일하게 유지되도록 한다.
어태치먼트 계층구조는 오브젝트 간의 부모-자식 관계를 설정하여 변환 상속 및 조직화를 용이하게 한다. 이를 통해 씬의 복잡한 구조를 간단하게 관리하고 애니메이션이나 움직임을 쉽게 구현할 수 있다. 익스포트 시에도 이 계층구조를 유지하면 외부 소프트웨어와의 호환성을 높일 수 있다.
Unreal Automation Tool(UAT)
UAT 완료 파악
에디터는 UAT 작업(쿠킹 및 패키징)을 완료할 때마다 사용자에게 알릴 시도를 한다.
UAT 항상 빌드
게임을 실행하기 전에 UAT/UBT를 언제나 빌드한다. 비활성화될 경우 반복 소요 시간이 줄어든다.
이 설정은 특정 디버깅 기능과 관련된 옵션으로 AI 컴포넌트의 일부인 비헤이비어 트리(Behaviour Tree)의 동작을 실시간으로 모니터링하고 분석하는 데 사용할 수 있다. 비헤이비어 트리는 주로 NPC나 기타 게임 내 인공지능 캐릭터의 행동을 제어하는 데 사용된다.
설정을 활성화하면 에디터나 게임이 실행되는 동안 비헤이비어 트리의 모든 활동과 상태 변화가 지속적으로 기록되는데 이는 개발자가 AI의 행동 패턴을 더 잘 이해하고 문제를 진단하는데 도움 받을 수 있다.
유용한 기능이지만 데이터를 항상 수집하기 때문에 성능에 영향을 줄 수 있다. 데이터 수집 과정에서 추가적인 처리가 필요하기 때문에 특히 대규모 AI 시스템을 사용하는 게임에서는 성능 저하에 유의해야 한다.
일반적으로 이 설정은 개발 중이나 테스트 단계에서 문제를 해결하기 위한 디버깅 용도로 사용되며 성능을 위해서 릴리즈 버전에서는 비활성화하는 것이 좋다. 수집된 데이터는 언리얼 엔진의 디버거 도구를 통해 시각적으로 표현될 수 있으며 이를 통해 개발자는 비헤이비어 트리의 각 노드에서 발생하는 결정과 변경사항을 보다 쉽게 추적할 수 있다.
블랙보드 키를 알파벳 순으로 디스플레이
비헤이비어 트리의 블랙보드에서 사용되는 키들을 알파벳 순서로 정렬하여 표시하도록 설정하는 기능으로 블랙보드의 데이터를 관리하고 검토할 때 편의성을 높이기 위해 사용된다.
많은 수의 키가 있을 때 알파벳 순으로 정렬하면 필요한 키를 빠르고 쉽게 찾을 수 있고 키들을 체계적으로 정리하여 블랙보드를 보다 효과적으로 관리할 수 있어 가독성과 관리 용이성을 향상할 수 있다.
비헤이비어 트리 디버거 데이터 항상 수집과 블랙보드 키를 알파벳 순으로 디스플레이 설정은 사용 중인 트리와 블랙보드의 수가 많을 때 유의미한 결과를 확인할 수 있기 때문에 어떤 식으로 표시되는지 정보에 대한 확인은 이후에 다시 작성하도록 한다.
Simplygon Swarm
언리얼 엔진에서는 3D 모델 최적화와 자동 LOD 생성을 위한 소프트웨어인 Simplygon을 사용한다.
Simplygon을 통해서 게임 내에서 3D 모델의 성능을 향상하기 위해 다양한 디테일 레벨을 자동으로 생성하고 관리할 수 있다.
Simplygon Swarm은 이러한 Simplygon과 관련된 데이터를 분산처리하는 시스템이다. Simplygon은 주로 3D 모델의 폴리곤 수를 줄이는 데 사용되며, 고품질의 LOD(Level of Detail) 모델을 생성하는 데 이러한 최적화 작업을 여러 대의 컴퓨터에 분산시켜 작업 효율성을 극대화한다.
Simplygon 배포 프록시 서버 사용
Simplygon Swarm은 위 작업을 위해서 제안된 기능으로 해당 설정을 활성화하면 작업 처리와 데이터 관리에 있어 중앙 집중화된 접근 방식을 취하게 된다. 배포되기 전 개발 단계에서 사용되는 도구이며 개발 단계에서 자원의 효율성을 증가시키기 위해서 사용한다. 이 설정을 활성화해야 관련된 다른 설정들도 활성화된다.
Simplygon 배포 프록시 서버 IP
분산처리 작업을 위한 프록시 서버 IP를 설정한다.
프록시 서버는 Simplygon Swarm의 네트워크 통신 허브로 작업을 여러 에이전트(작업을 실제로 수행하는 컴퓨터)에게 분산하는 중추 역할을 한다. 이 서버는 각 에이전트의 상태를 모니터링하고 최적의 분산 전략을 수립하여 작업을 효율적으로 할당한다.
프록시 서버는 각 에이전트의 리소스 사용 상태를 파악하여 특정 에이전트에 과부하가 걸리지 않도록 작업을 분산하여 전체 시스템의 효율성을 높이고 작업 시간을 최소화하는 데 도움을 준다.
스웜 디버깅 활성화
Simplygon Swarm에서 분산 처리 작업을 진행할 때 발생하는 다양한 이벤트와 오류를 모니터링하고 로깅하는 기능이다.
이 설정을 활성화하면 시스템의 동작을 보다 상세하게 이해할 수 있으며 발생하는 문제들을 신속하게 진단하고 해결하는데 도움을 준다.
- 작업 중 발생하는 네트워크 문제, 데이터 처리 오류, 작업 실행 실패 등의 오류를 기록하여 오류를 추적한다.
- 작업 할당, 데이터 전송, 작업 완료 등의 이벤트가 발생할 때마다 로그에 기록되는 이벤트 로깅을 통해서 시스템의 전반적인 흐름과 작업 처리 상태를 확인할 수 있다.
- 시스템의 성능을 실시간으로 모니터링하면서 성능 지표를 기록하여 시스템 최적화와 자원 할당에 중요한 정보를 얻을 수 있다.
- 디버깅 데이터를 분석하여 시스템의 성능을 향상하거나 잠재적인 문제를 사전에 파악하고 수정하는 데 사용할 수 있다.
MS 단위 시간 json 요청 간 딜레이
Simplygon Swarm의 각 노드 간에 발생하는 JSON 데이터 요청들 사이에 설정된 딜레이를 의미한다. 밀리 세컨드 단위로 설정할 수 있으며(기본 5000ms) 네트워크 트래픽을 조절하고 서버의 부하를 관리할 수 있다.
효율적인 시스템 관리와 최적의 성능 유지를 위한 설정 중 하나로 데이터 처리와 네트워크 통신의 안정성을 보장하고 전체적인 시스템 운영의 효율성을 높일 수 있다.
Swarm 시스템에서는 다수의 노드가 서로 데이터를 요청하고 응답하는 과정에서 네트워크 트래픽이 급격히 증가할 수 있는데 이때 딜레이를 설정함으로써 요청이 일정한 간격으로 이루어지게 하여 네트워크의 과부하를 방지한다. 딜레이를 통해 각 요청이 처리되기까지의 시간을 일정하게 하여 서버가 한꺼번에 많은 요청을 처리해야 하는 부담을 줄인다. 이는 서버의 안정적인 운영을 도와주고 시스템의 전반적인 응답성을 개선한다.
너무 많은 요청이 짧은 시간 내에 발생할 경우 일부 요청이 실패할 가능성이 있어 딜레이를 적절히 설정하여 요청 실패율을 줄일 수 있다. 네트워크와 서버의 처리 능력을 고려하여 딜레이를 설정해야 하며 너무 짧은 딜레이는 시스템에 과부하를 주며 너무 긴 딜레이는 전체 작업의 처리 속도를 저하시킨다. 딜레이 설정 후에도 시스템의 성능과 안정성을 지속적으로 모니터링하고 필요에 따라 딜레이 값을 조정하는 것이 중요하다.
Simplygon 그리드 서버에 제출할 동시 작업 수
서버에서 동시에 처리할 수 있는 작업의 수를 지정하는 설정이다. 이 설정은 Simplygon Swarm의 작업 분산 및 처리 효율성을 관리한다. 서버의 리소스를 효율적으로 활용하기 위해 동시에 실행할 수 있는 작업의 수를 조정하여 서버의 처리 능력과 메모리 사용을 고려하여 작업의 처리 속도를 타협하여 균형 있게 조절할 수 있다.
Simplygon 스웜 zip 파일 최대 업로드 용량(MB)
Simplygon 그리드 서버로 업로드할 수 있는 zip 파일의 최대 크기를 제한하는 설정이다.
이는 서버의 데이터 처리 능력과 네트워크의 대역폭 저장 공간 등을 고려하여 설정하여 네트워크 트래픽과 서버의 저장 공간을 효율적으로 관리한다. 최대 용량보다 큰 파일은 청크로 분할된다.
서버가 한 번에 처리할 수 있는 데이터 양을 제한하여 서버의 과부하를 방지하고 데이터 처리 효율을 유지하며 대용량 파일의 업로드가 네트워크에 미치는 영향을 최소화한다. 시스템의 안정성을 유지하기 위해 각 사용자가 업로드할 수 있는 파일의 크기를 제한함으로써 서버에 발생할 수 있는 예기치 않은 문제들을 사전에 방지한다.
Simplygon 스웜 Intermediate 폴더
작업의 중간 데이터를 저장하는 경로를 지정하는 설정이다. 3D 모델 최적화 프로세스 동안 생성되는 임시 파일들이나 처리 중인 데이터를 보관하는 장소로 사용되며 스웜에 업로드되는 중간 텍스처와 메시 데이터가 저장된다.
처리 중인 3D 모델의 데이터를 체계적으로 관리하여 프로세스의 효율성을 높이고 데이터 접근성을 개선하여 데이터를 조직화하고 프로세스 중 생성되는 임시 파일들을 별도의 위치에 저장함으로써 최종 출력 파일과 중간 파일을 명확히 구분할 수 있어 이는 작업의 명확성과 추적성을 향상해 작업의 효율성을 향상한다. 대용량 데이터의 경우 처리 시 시스템의 리소스를 효과적으로 활용하고 서버의 부하를 분산시키는 역할을 한다.
extern 키워드를 사용하면 플랫폼 간 상호 운용성, 성능 최적화, 코드의 안전성과 에러 처리를 모색할 수 있다.
플랫폼 간 상호 운용성
C# 언어를 사용하는 프로젝트에서 이외의 언어로 작성된 라이브러리 함수를 호출하는 경우는 아주 흔하게 발생하는 상황이다. 예를 들어서 C#에서 Windows API를 호출하려면 DllImport 속성을 사용해서 C# 코드에서 네이티브 코드 함수를 선언해야 한다. 이를 통해 C# 프로그램에서 운영 체제 수준의 다양한 기능을 직접적으로 사용할 수 있다.
Windows API 중 몇 가지 간단한 함수를 사용해 본다.
namespace Test
{
using System;
using System.Text;
using System.Runtime.InteropServices;
internal class Program
{
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEMTIME
{
public ushort Year;
public ushort Month;
public ushort DayOfWeek;
public ushort Day;
public ushort Hour;
public ushort Minute;
public ushort Second;
public ushort Milliseconds;
}
[DllImport("Kernel32.dll")]
public static extern bool SetConsoleTitle(string title);
[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
public static extern uint GetConsoleTitle(StringBuilder buffer, uint size);
[DllImport("Kernel32.dll")]
public static extern void GetSystemTime(out SYSTEMTIME st);
static void Main(string[] args)
{
SetConsoleTitle("Bak's Console");
Console.WriteLine("Hello, World!");
StringBuilder buffer = new StringBuilder(256); // Define buffer size according to your need
GetConsoleTitle(buffer, (uint)buffer.Capacity);
Console.WriteLine("Console Title: " + buffer.ToString());
SYSTEMTIME st;
GetSystemTime(out st);
Console.WriteLine("Current System Time: {0}-{1}-{2} {3}:{4}:{5}.{6}",
st.Year, st.Month, st.Day, st.Hour, st.Minute, st.Second, st.Milliseconds);
Console.ReadLine();
}
}
}
실행 결과
외부 함수 SetConsoleTitle을 사용해서 실행되는 콘솔의 타이틀을 변경하고 GetConsoleTitle을 사용해서 변경한 콘솔의 타이틀을 가지고 와서 콘솔에 찍어본다. 그리고 GetSystemTime을 사용해서 현재 실행 중인 장치의 시간을 가지고 온다.
코드를 보면 알 수 있듯이 필요한 기능을 사용하기 위해서는 어트리뷰트를 선언할 때 추가로 필요한 값들이나 사용하고자 하는 함수의 반환값, 필요한 파라미터 등에 대한 정보들이 필요하다.
이러한 정보들은 마이크로소프트 공식 문서나 또는 이를 주제로 하는 커뮤니티에서 확인할 수 있고 이외 라이브러리들도 제공하는 곳에서 API 문서를 확인할 수 있다.
성능 최적화
C# 코드 내에서 수학 계산이나 이미지 처리와 같은 고성능의 연산을 요구하는 네이티브 라이브러리 함수를 호출하는 방법이 있다. 이러한 방식은 매니지드 코드(Managed Code)에 비해 실행 속도가 빠른 네이티브 코드의 이점을 활용할 수 있게 해 준다.
네이티브 코드를 사용하는 것이 언제나 성능적으로 이점이 있다고 할 수는 없으므로 해당 목적을 위해서 외부 라이브러리를 사용한다고 했을 때에는 .Net 환경에서 이미 최적화된 상태인 C# 라이브러리의 성능과 비교해서 네이티브 코드를 사용했을 때에 성능적인 이점이 있을 때 사용하는 것이 좋다.
// 몬스터 인터페이스 정의
public interface IMonster
{
void Attack();
}
// 구체적인 몬스터 클래스
public class Zombie : IMonster
{
public void Attack()
{
Console.WriteLine("Zombie attacks!");
}
}
public class Vampire : IMonster
{
public void Attack()
{
Console.WriteLine("Vampire attacks!");
}
}
// 몬스터 생성을 위한 팩토리 클래스
public abstract class MonsterFactory
{
public abstract IMonster CreateMonster();
}
public class ZombieFactory : MonsterFactory
{
public override IMonster CreateMonster()
{
return new Zombie();
}
}
public class VampireFactory : MonsterFactory
{
public override IMonster CreateMonster()
{
return new Vampire();
}
}
class Program
{
static void Main(string[] args)
{
MonsterFactory factory = new ZombieFactory();
IMonster monster = factory.CreateMonster();
monster.Attack();
factory = new VampireFactory();
monster = factory.CreateMonster();
monster.Attack();
}
}
특히 다양한 객체가 동일한 인터페이스를 공유하거나 시스템 구성 요소 간의 결합도를 낮추기 원할 때 유용하며 객체의 생성과 클래스의 구현을 분리함으로써 모듈화 된 코드 구조를 가능하게 한다.
빌더 패턴 (Builder Pattern)
빌더 패턴은 복잡한 객체의 생성과정을 단계별로 나누어 구축하는 디자인 패턴으로 객체의 생성 과정과 표현 방법을 분리하여 동일한 생성 절차에서 다양한 표현 결과를 얻을 수 있도록 한다. 주로 복잡한 객체를 조립해야 할 때 사용되며 각 부분의 조립 순서를 외부에서 지정할 수 있다.
// 캐릭터의 인터페이스 정의
public interface ICharacter
{
void EquipWeapon(string weapon);
void EquipArmor(string armor);
void AddAbility(string ability);
}
// 캐릭터 빌더 인터페이스
public interface ICharacterBuilder
{
ICharacterBuilder BuildWeapon(string weapon);
ICharacterBuilder BuildArmor(string armor);
ICharacterBuilder BuildAbility(string ability);
Character Build();
}
// 구체적인 캐릭터 빌더
public class HeroBuilder : ICharacterBuilder
{
private Character _character = new Character();
public ICharacterBuilder BuildWeapon(string weapon)
{
_character.EquipWeapon(weapon);
return this;
}
public ICharacterBuilder BuildArmor(string armor)
{
_character.EquipArmor(armor);
return this;
}
public ICharacterBuilder BuildAbility(string ability)
{
_character.AddAbility(ability);
return this;
}
public Character Build()
{
return _character;
}
}
// 사용 예
public class Game
{
public void CreateHero()
{
HeroBuilder builder = new HeroBuilder();
Character hero = builder.BuildWeapon("Sword")
.BuildArmor("Shield")
.BuildAbility("Invisibility")
.Build();
}
}
캐릭터가 가지는 공통적인 기능을 인터페이스로 구현한 다음 구체적인 캐릭터 클래스에서 원하는 옵션으로 조립할 수 있도록 단계를 구분한다.
할당된 메모리는 해당 객체에 대한 모든 참조가 없어질 때까지 메모리에 존재하고 더 이상 참조되지 않을 때 GC에 의해 관리된다.
public class MyClass
{
public int Number { get; set; }
}
public class Program
{
public static void Main()
{
MyClass myObject = new MyClass();
myObject.Number = 1;
Console.WriteLine(myObject.Number);
}
}
생성자
생성자는 객체가 할당될 때 호출되는 생명주기 메서드(Lifecycle Methods)이다.
클래스의 객체를 생성하는 방식을 생각해 보면 new 키워드 뒤에 클래스명의 함수를 쓰는데 이 함수는 클래스에서 따로 작성하지 않았는데도 문제없이 컴파일된다.
MyClass myObject = new MyClass();
그 이유는 클래스에 별도로 생성자에 대한 작성을 하지 않아도 컴파일 단계에서 자동으로 기본 생성자를 만들어서 사용하기 때문에 컴파일 에러가 발생하지 않게 된다.
기본 생성자의 형태는 클래스 명의 메서드로 함수 내부에는 비어있는 형태로 볼 수 있다.
public class MyClass
{
public int Number { get; set; }
// 기본 생성자 형태
public Number(){}
}
public class Program
{
public static void Main()
{
MyClass myObject = new MyClass();
myObject.Number = 1;
Console.WriteLine(myObject.Number);
}
}
생성자의 접근제한자를 private 등을 사용해서 클래스의 인스턴스 생성을 제한할 수 있다.
생성자는 파라미터를 추가한 형태로 선언이 가능하며 클래스의 인스턴스가 생성될 때 필드나 프로퍼티를 초기화하는 방법으로 사용할 수 있다.
public class MyClass
{
public int Number { get; set; }
private string _id;
private string _pw;
private int _age;
private bool _isAgree;
// 기본 생성자 형태
public Number(string id, string pw, int age, bool isAgree)
{
_id = id;
_pw = pw;
_age = age;
_isAgree = isAgree;
}
}
public class Program
{
public static void Main()
{
MyClass myObject = new MyClass("bak", "****", 19, true);
// 에러 발생
MyClass myObject = new MyClass();
}
}
이렇게 하면 인스턴스를 생성과 동시에 필드값을 초기화할 수 있다.
주의할 점은 이렇게 파라미터를 받는 생성자를 작성하게 되면 컴파일러에서는 더 이상 기본 생성자는 만들어 주지 않기 때문에 기본 생성자를 사용하려고 하면 컴파일 에러가 발생하게 되므로 기본 생성자도 사용하기를 원하면 추가로 작성해야 한다. 즉 생성자도 오버로딩이 가능하기 때문에 다양한 매개변수를 받는 생성자의 선언이 가능하다.
소멸자
생성자와는 호출 시점에만 차이가 있는 생명주기 메서드이다. (파괴자라고도 한다.)
소멸자는 객체가 소멸되는 시점에 호출되며 C#에서는 더 이상 객체가 참조되는 곳이 없을 때 GC에 의해서 관리되어 소멸될 때 소멸자가 호출된다.
따라서 소멸자의 호출 시점이 명확하지 않으므로 소멸자 내부에서 어떠한 기능을 수행시키게 한다면 동작에 대한 기대가 힘들기 때문에 C#에서는 이를 활용하는 경우는 드물다.
public class MyClass
{
public Number(){}
// 소멸자 선언
~Number(){}
}
이 설정 내용은 익스포터 하여 저장할 수 있으며 또한 저장된 파일을 임포트 하여 설정값을 불러올 수 있다.
변경된 설정은 프로젝트 폴더의 Saved > Config 폴더에 저장된다.
파생 데이터 캐시
파생 데이터 캐시(Derived Data Cache, DDC)는 개발 과정에서 생성되는 파생 데이터를 저장하는 시스템이다.
파생 데이터에는 텍스처의 압축된 버전, 셰이더의 컴파일된 버전 등을 말하여 이 캐시는 데이터의 재계산이나 재생성 없이 빠르게 로드할 수 있도록 도와줌으로 에디터 및 게임의 런타임 성능을 향상하고 전반적인 컴파일 시간을 단축하는 역할을 한다.
즉 에셋을 처음 처리할 때 필요한 계산을 수행하고 결과를 DDC에 저장하는데 이후 동일한 에셋을 다시 로드할 필요가 있을때 DDC에 저장된 경우 미리 계산된 이 데이터를 즉시 사용할 수 있어 시간을 단축할 수 있다.
빌드 시 재사용 가능한 데이터가 DDC에 존재하면 셰이더 컴파일이나 에셋 변환과 같은 시간 소모적인 작업을 생략할 수 있기 때문에 규모가 큰 프로젝트 같은 경우 작업 시간을 절약할 수 있다.
또한 DDC는 로컬뿐만 아니라 네트워크 상에서도 위치할 수 있기 때문에 이를 통해서 동일한 DDC를 공유할 수 있어 협업에서 모든 팀원이 동일한 파생 데이터에 접근이 가능하며 데이터의 일관성을 유지할 수 있다.
따라서 글로벌 로컬 DDC 패스, 글로벌 공유 DCC 경로 설정을 통해서 필요한 데이터를 더 빠르게 재구성할 수 있기 때문에 프로젝트의 이전 및 이식성의 효율성을 높일 수 있다.
글로벌로 설정하면 모든 에디터에서 공통적으로 적용되며 고급 설정을 확장하여 현재 프로젝트에서만 적용되는 설정을 할 수 있다.
파생 데이터 캐시 알림
DDC와 관련된 작업이 수행될 때 알림을 받을 수 있도록 하는 기능으로 이 설정을 통해서 개발자가 DDC의 상태를 더 잘 파악하고 이해할 수 있도록 하여 관리를 돕는다.
이 기능은 수로 DDC 작업의 시작과 완료 과정에서 발생하는 에러 등을 실시간으로 알려주기 때문에 캐시가 올바르게 작동하고 있는지 또는 문제가 발생했는지를 즉시 파악할 수 있도록 모니터링할 수 있다.
DDC 작업의 모니터링을 통해서 성능에 미치는 영향을 파악하고 캐시된 데이터의 손상여부 확인이나 진단을 할 수 있어 문제의 원인을 빠르게 파악할 수 있기 때문에 성능 최적화와 작업의 효율성을 향상할 수 있다.
파생 데이터 캐시 S3
DDC를 Amazon S3와 함께 사용하는 설정으로 대규모 게임 개발 프로젝트에서 주로 사용되는 설정이다.
S3는 Amazon Simple Storage Services로 AWS에서 제공하는 객체 스토리지 서비스로 인터넷을 통해 데이터를 저장하고 검색할 수 잇는 확장 가능한 스토리지 솔루션이다.
이 기능을 사용하면 어느 위치에서나 접근 가능한 중앙 집중식 DDC를 구축할 수 있기 때문에 전 세계에 분산된 팀원들이 동일한 파생 데이터에 액세스 하고 공유할 수 있다.
이 서비스는 높은 확정성을 제공하고 사용량에 따라 자동으로 저장 용량이 조정되기 때문에 대규모 데이터를 처리하는 상황에서도 안정적인 성능을 유지할 수 있다. 또한 데이터의 내구성과 가용성을 보장하기 위해 여러 지리적 위치에 데이터를 자동으로 복제하여 관리하기 때문에 게임 자산의 안전을 보장하며 데이터 손실의 위험을 최소화할 수 있다.
실제로 사용한 만큼의 비용을 지불하는 요금제를 제공하기 때문에 초기 투자 비용 없이 필요에 따라 스토리지를 조정할 수 있게 하여 비용의 효율성과 아마존의 네트워크 최적화와 캐싱 전략을 통해 빠른 데이터 액세스 속도를 제공한다.
저장되지 않은 변경 사항 중 선택해서 저장할 수 있는 기능이다. 클릭 시 저장할 콘텐츠의 목록 창이 팝업 된다.
레벨로 임포트
fbx 또는 obj 확장자 파일을 현재 레벨로 임포트 할 수 있다.
언리얼에서는 프로젝트에 사용되는 리소스들이 Content 폴더에 저장되고 콘텐츠들을 fbx 또는 obj 확장자 파일로 내보내기 할 수 있으며 이를 다시 프로젝트에 임포트 할 수 있다.
언리얼 엔진에서 파일과 에셋들은 크게 콘텐츠 폴더와 엔진 폴더에 구분되어서 저장된다.
콘텐츠 폴더에는 특정 프로젝트에 특화된 자산을 저장하는 데 사용되며 게임 플레이와 직접적으로 관련된 모든 콘텐츠가 포함된다. 개발자가 직접 생성하고 관리하는 파일들이 대부분이며 프로젝트별로 독립적이다.
엔진 폴더에는 언리얼 엔진 자체에 필요한 핵심 파일과 자산을 저장하는 데 사용된다. 엔진 코드, 표준 플러그인, 필수 라이브러리, 시스템 설정 파일 등이 포함되어 있다. 이 폴더에 저장된 파일들은 언리얼 엔진을 설치한 모든 프로젝트에서 공통적으로 사용되기 때문에 이 폴더의 내용이 수정되면 모든 프로젝트에 영향을 미칠 수 있다. 일반적으로 엔진 업그레이드 시 업데이트되는 파일들이다.
1998년에 출시한 1인칭 슈팅 게임 <언리얼>을 개발할 때 사용한 자체 개발 게임엔진인 '언리얼 엔진'을 타사에 제공 및 판매하기 시작했으며 이 엔진을 사용하여 다양한 게임들이 출시되었으며 현재는 에픽게임즈를 대표하는 수준의 중요한 서비스 중에 하나가 되었다.
Unreal Engine
이름은 비현실적인 엔진이지만 현재 배포되는 엔진 중에서 가장 현실적으로 그래픽을 표현할 수 있는 엔진 중 하나이다. 따라서 게임뿐만 아니라 영화나 건축 등 고퀄리티의 작업을 위해서 사용되기도 한다.
흔히 말하는 AAA급 게임을 개발하는데 주로 사용되는 엔진으로 또 다른 대표적인 게임 엔진인 유니티와 비교했을 때 상당히 무거운 편이다. 따라서 개발하고자 하는 게임의 수준에 맞춰 엔진을 선택하는 것이 필요하다.
Project Create
언리얼 엔진을 설치하고 실행하게 되면 먼저 프로젝트를 생성하게 된다. 참고로 언리얼 엔진은 컴파일러를 비주얼스튜디오를 사용하고 있다.
포스팅에서 사용할 버전은 글을 작성하는 시점에서는 가장 최근에 출시된 5.4 버전을 사용한다.
프로젝트 생성 단계에서는 어떤 프로젝트를 만들 것인지에 따라서 몇 가지 기본 템플릿이 제공된다.
프로젝트 기본 설정에서는 몇 가지 설정을 선택하여 프로젝트를 초기화할 수 있는데 이 부분은 생성 이후에도 변경이 가능하다.
블루프린트 / C++
언리얼 하면 가장 대표적인 기능이 블루프린트이다.
블루프린트는 구분하자면 언리얼 엔진으로 개발할 때 사용할 수 있는 프로그래밍 언어 중 한 종류로 볼 수 있다. 이러한 기능을 비주얼 스크립팅이라고도 하는데 유니티에서는 해당 기능은 기본기능으로 제공되지 않지만 스토어에서 구매하여 사용할 수 있다. 대부분 코딩 없이 개발이 가능한 기능으로 표현되는데 이 기능을 사용하기 위해서는 그래도 최소한의 언어적 이해도가 필요하다.
또 다른 선택 가능한 언어는 C++이다.
이 부분에서 개발자들이 더 선호하기도 한다. 또 다른 대표적인 상용엔진인 유니티의 경우 C#을 프로그래밍 언어로 사용하고 있는데 C#에서는 메모리 관리를 위한 GC가 사용된다. 이는 사용자가 메모리 관리에 대한 신경을 쓸 필요를 덜어주지만 반대로 제어할 수 없다는 점도 있다.
언리얼의 경우에도 자동으로 관리를 해주는 GC나 스마트 포인터가 존재한다. 유니티와의 차이점은 사용자가 이 관리되는 메모리를 직접 제어할 수 있다는 점에서 차이가 있어 게임의 성능을 최적화하는 데에는 언리얼이 더 유리한 측면이 있다고 보인다.
네트워크를 간단히 설명하자면, 우리가 일상적으로 인터넷에 접속하여 SNS, 뉴스, 동영상 등의 서비스를 사용하는 것과 같은 막연한 것들만 떠오르는데요. 간단하게 네트워크의 개념에 대해서 설명하자면 그물처럼 서로 연결된 노드들의 집합으로 정보와 자원을 공유하며 데이터를 교환하는 것입니다.
먼저 네트워크란 개념이 어떻게 시작되었는지 과거로 돌아가봅니다.
1960년대 컴퓨터의 성능은 어느정도 발전을 이루었지만 여전히 비싼 가격대로 아무나 사용할 수 없는 장치였습니다. 이 당시 하나의 컴퓨터를 여러 사용자가 공유할 수 있는 시스템이 제안됩니다. 이때 제안된 게 시분할 시스템(TSS, Time Sharing System)으로 한 명의 사람의 입력만 받고 처리하기에는 컴퓨터에게는 너무나 쉬운 작업이었기 때문에 이를 활용하여 여러 사람의 입력을 받고 처리하도록 최대한 컴퓨터의 능력을 활용하기 위해서 제안되었습니다. 여기서 각 사용자들에게 컴퓨터 자원을 시간적으로 분할하고 사용하게 하며 대화식 인터페이스를 통해서 출력이 사용자에게 표시되고 키보드를 통해 입력된 정보를 처리합니다. 그러나 이 아이디어는 시연까지는 되었지만 구축이 어렵고 비용이 많이 들었기 때문에 보편화되지 못했으나 아이디어를 활용해서 현재의 컴퓨터에서 동작하는 여러 가지의 시스템이 이러한 방식을 따르고 있습니다.
TSS는 보급에는 실패했지만 현대에서도 사용되는 중요한 개념들을 정립하는 계기가 되었습니다.
- 자원공유 : 하나의 컴퓨터에 여러 사용자가 작업 할 수 있도록 하드웨어 자원의 효율적 사용
- 동시접근 : 여러 사용자가 동시에 컴퓨터에 접근 하고 데이터를 교환하는 상호작용할 수 있는 환경
- 분산처리 : 데이터와 처리 작업을 여러 컴퓨터 사이에서 나누어 처리
- 통신 프로토콜 : 여러 터미널과 중앙 컴퓨터 간의 효율적인 데이터 전송을 위한 규칙
이러한 개념들은 네트워크의 초석이 되기도했습니다.
ARPANET(Advanced Research Projects Agency Network)
알파넷은 냉전 시대의 군사적 요구와 과학 연구의 필요성에 의해 만들어졌습니다.
개발 당시 미국 정부는 소련과의 기술 경쟁에서 우위를 점하기 위해 정보 기술의 발전을 꾀했으며 여러 연구 기관 간의 효율적인 정보 교류가 필요했습니다. 이 알파넷의 주요 혁신 기술은 패킷 스위칭 기술입니다. 이는 대용량 데이터를 작은 패킷으로 나누어 각각을 다른 경로로 전송하고 목적지에서 재조립하는 방식입니다. 이 기술은 데이터 전송의 신뢰성과 효율성을 크게 향상하게 되었습니다.
알파넷은 처음에는 UCLA, 스탠퍼드 연구소(SRI), UC 샌타바버라, 유타 대학교 네 개의 노드를 연결하여 운영을 시작했습니다. 이 초기 네트워크는 매우 기본적인 구조로 컴퓨터 과학자들에게 네트워킹 기술을 실험하고 개발할 수 있는 플랫폼을 제공하는 역할을 했습니다.
그리고 네트워크 통신의 기본인 TCP/IP 프로토콜이 처음 개발되기도 했습니다. 이는 이후 인터넷 표준 프로토콜로 채택되어 현재까지도 전 세계적으로 사용되고 있습니다. 이 프로토콜은 복잡한 네트워크 구조를 상호 간의 연결을 가능하게 하는 기본적인 규칙에 대한 정의입니다.
이외에도 최초의 전자 메일 시스템의 도입과 같은 다양한 혁신을 가져왔습니다. 네트워크를 통한 정보의 자유로운 교환은 학문적 공동체와 연구의 방식을 변화시켰고 현대의 인터넷 문화와 디지털 통신의 기반이 되는 등 ARPANET 그 자체로 사회적, 기술적으로 막대한 변화를 촉진하는데 기여하였습니다.
Telenet
텔레넷은 알파넷의 주요 설계자 중 한 명인 Lawrence Roberts가 창립한 것으로 1970년대에 설립된 미국 최초의 상업적 패킷 스위칭 네트워크입니다. 알파넷이 군사적인 용도로 개발되었다면 텔레넷은 알파넷의 기술을 기반으로 하여 개발되었으며 일반 기업 및 개인 사용자들에게 네트워크 서비스를 상업적으로 제공하는 것을 목표로 하였습니다.
텔레넷에서도 패킷 스위칭 기술이 사용되었으며 당시 사용되는 여러 프로토콜들을 계층구조의 개념을 도입하여 체계화시킨 x.25 표준을 도입하여 다양한 네트워크와의 호환성을 보장했습니다.
특히 금융기관, 대학, 그리고 대기업들 사이에서 인기를 끌었으며 사용자들에게 원격으로 데이터베이스에 접근하고 파일을 전송하며 다른 네트워크 서비스를 이용할 수 있는 기능을 제공했습니다. 이 서비스는 정보의 접근성을 크게 향상하고 데이터 통신 비용을 줄이는데 크게 기여하기도 했습니다.
텔레넷은 상업적인 패킷 스위칭 네트워크로서의 성공이 증명되었으며 이후 다른 많은 상업 네트워크들의 등장에 큰 영향을 미쳤으며 기술적인 혁신뿐만 아니라 군사적 용도가 아닌 일반 사업 및 개인용으로도 널리 활용될 수 있음을 보여주면서 비즈니스 모델에서도 중요한 전환점을 제공하여 인터넷이 전 세계적으로 확산되기 이전에 디지털 통신의 가능성을 넓히는 데 중요한 역할을 했습니다.
Ethernet
이더넷은 로컬 에리어 네트워크(LAN) 기술의 한 형태로 오늘날 가장 널리 사용되는 네트워킹 기술 중 하나입니다. 이더넷은 1973년에 제록스 PARC(Xerox Palo Alto Research Center)의 로버트 메트칼프(Robert Metcalfe)와 그의 동료들에 의해 처음 개발되었으며 이 기술은 컴퓨터들이 데이터 패킷을 공유 미디어를 통해 서로 전송할 수 있도록 하는 데 초점을 맞추었습니다.
1970년대 초 제록스 PARC에서는 Alto라는 개인용 컴퓨터의 네트워킹 필요성을 인식하고 이를 해결하기 위한 방안으로 이더넷을 개발하기 시작했습니다. 메트칼프는 하와이 대학교의 ALOHAnet 무선 패킷 네트워크에서 영감을 받아 유선 환경에 적합한 네트워크를 설계하게 되었습니다.
제록스 알토는 데스크톱 메타포와 그래픽 사용자 인터페이스를 이용한 최초의 컴퓨터로 상업적인 프로젝트는 아니었지만 수십 년에 걸쳐 개인용 컴퓨터 특히 매킨토시와 썬 워크스테이션의 설계에 큰 영향을 주었습니다.
이더넷 기술은 계속해서 발전하여 초기 10 Mbps에서 기가비트 오늘날에는 10 기가비트 이상의 속도로 데이터를 전송할 수 있는 기술로 발전하였으며 또한 트위스티드 페어 케이블과 광섬유 케이블(Fiber-optic cable) 같은 다양한 전송 매체가 도입되기도 했습니다.
현대에서 이더넷은 표준화와 호환성이 높아 다양한 네트워크 장비와 시스템에서 손쉽게 구현할 수 있어 광범위한 기업 환경은 물론 가정과 학교 등 다양한 곳에서 LAN을 구축할 때 기본적으로 사용되는 기술입니다. 간단한 개념과 구현의 용이성으로 인해 수십 년 동안 기술의 중심에 있었으며 네트워킹의 가장 기본적이고 중요한 기술 중 하나로 자리 잡게 되었습니다.
네트워크 케이블
이러한 네트워크의 연결을 위해서는 정보를 주고받을 수 있도록 물리적인 장치가 필요합니다.
FLAG (Fiber-Optic Link Around the Globe) = FEA(Fiber-Optic Europe-Asia)
1990년대 후반 FLAG 해저 케이블 시스템은 아시아, 중동을 연결하는 글로벌 통신망 프로젝트로 1997년에 완공되었습니다. 이 케이블 시스템은 주로 대륙 간 데이터 통신 수요를 충족시키기 위해 설계되었으며 여러 국가와 대륙을 연결하는 역할을 합니다. 이 중 한국 또한 이 케이블 시스템의 주요 노드 중 하나가 되었습니다.
약 28,000 킬로미터에 달하는 광섬유 케이블로 구성되어 있으며 영국에서 출발하여 유럽, 중동, 아시아를 거쳐 일본까지 이어지는 것으로 북아메리카와 아시아를 연결하는 주요 노선 중 하나입니다. 주요 연결 지점(Node)으로는 영국, 프랑스, 이탈리아, 이집트, 사우디아라비아, 아랍에미리트, 인도, 태국, 말레이시아, 싱가포르, 홍콩, 대만, 한국, 일본 등의 해안 도시들과 연결되어 있습니다.
현재는 FEA로 초기 FLAG 시스템이 더 많은 국가와 지역을 포괄하였지만 경제적 중요성에 따라서유럽과 아시아 지역 간의 특정 연결성의 강화에 의해서 FEA로 변경되기도 했습니다.
이외에도 아시아 태평양 지역의 여러 국가들을 연결하는 APCN(Asia Pacific Cable Network) 등 필요와 기술의 발전에 따라서 추가로 케이블들이 설치되기도 했습니다.
통신망은 규모에 따라 다양하게 분류됩니다.
LAN(Local Area Network)
근거리 통신망으로 가까운 거리에 있는 단말 간의 네트워크를 말합니다. 한정된 공간 내에 분산 설치되어 있는 단말을 통신회선 연결을 통해 상호작용 가능하게 한 네트워크로 단일 구성은 거리적으로 한정되지만 복수의 근거리 통신망을 설치하여 대형 네트워크를 형성하게 됩니다. 이때 다른 종류의 LAN은 게이트워이라는 통로를 통해서 연결되어 사용하게 됩니다.
MAN(Metropolitan Area Network)
도시권 통신망으로 근거리 통신망이 1개 기업의 범위 또는 빌딩 전체를 연결하는 네트워크라면 도시권 통신망은 이를 확장하여 하나의 도시 내로 확장한 네트워크입니다. 초기 통신망이 구축되었을 때는 존재하지 않았지만 휴대전화의 보급으로 인해서 각 도시마다 네트워크를 구축할 필요가 생기게 되어서 기지국이 생기게 되었는데 이 기지국을 칭하는 개념으로 생겨나게 되었습니다. 도시권 통신망은 다른 도시권 통신망과 직접적으로 연결되어 있습니다.
WAN(Wide Area Network)
광역 통신망으로 도시 간 또는 국가 간 등을 연결하는 통신망입니다. 대부분 통신사가 전국에 회선을 깔아서 구축한 통신망으로 가장 최상위 규모의 통신망입니다. 일반적으로 개인이 네트워크에 연결될 때는 대부분 LAN을 통해 이루어집니다. 그리고 연결하고자 하는 네트워크의 범위에 따라서 MAN을 거치거나 WAN을 거쳐 목적지에 도착하게 되는데 이때 ISP를 거치게 됩니다. 우리가 특정 사이트를 방문하다 보면 연결이 차단되기도 하는데 이것은 ISP에 의해서 관리를 받기 때문입니다.
이외에도 기업에서 통신사로부터 회선을 임대받아 광역 통신망 간의 직접 연결한 경우도 있으며 대표적으로 인트라넷이 이러한 경우입니다.
ISP(Internet Service Provider)
인터넷 서비스 제공자로 개인, 기업, 정부 등 고객을 대상으로 인터넷 접속 서비스를 제공하는 회사나 조직을 말합니다. 대한민국의 경우 KT, SKT, LG 등의 통신사들의 인터넷 서비스를 ISP라고 볼 수 있습니다.