-
유니티 클라이언트 면접준비 - 예상 질문면접준비 2024. 1. 26. 18:33반응형
Q. - C# 과 C++의 차이점 -
A. 가장 큰 차이로는 가비지컬렉터가 있습니다. string이 C#에선 객체지만 C++에선 주소의 나열입니다.
Q. - delegate vs event -
A. 델리게이트는 public 한정자로 선언하면 클래스 외부에서 호출이 가능하지만 event는 public 한정자로
선언해도 클래스 외부에서 호출이 불가능합니다.
event는 객체의 상태 변화나 사건의 발생을 알리는 용도로 사용이 되고, delegate는 callback의 용도로 사용됩니다.
Q. - 유니티 메터리얼 -
A. 메터리얼은 게임 오브젝트의 렌더링 효과를 결정하는 속성을 가진 컴포넌트입니다.
쉐이더와 텍스처를 조합하여 오브젝트의 색상, 질감, 광택 등을 제어할 수 있습니다
Q. - 유니티 프리팹 -
A. 프리팹은 게임 오브젝트를 미리 만들어 놓고, 필요할 때마다 인스턴스화하여 사용할 수 있도록 하는 기능입니다.
프로젝트에 저장되어 있으며 필요할 때마다 가져와 사용할 수 있습니다.
이를 통해 게임 오브젝트의 중복 생성을 줄이고, 효율적인 게임 개발을 가능하게 만듭니다.
Q. - 유니티 쉐이더 -
A. 쉐이더는 그래픽 처리 유닛에서 사용되는 프로그램으로, 렌더링 엔진에서 빛, 색상, 질감 등의 시각적인 요소를 계산하는데 사용됩니다.
Q. - 유니티 빌드 -
A. 빌드는 게임을 실행 가능한 상태로 만드는 작업을 말합니다.
이 작업을 통해 게임 개발자는 플랫폼별로 게임을 빌드하여 사용자에게 제공할 수 있습니다.
Q. - 유니티 콜라이더와 리지드바디 차이 -
A. 콜라이더는 충돌 감지를 위한 컴포넌트이고,
리지드바디는 물리 엔진과 상호작용하기 위한 컴포넌트입니다.
콜라이더는 충돌하는것을 감지하고, 이에 대한 이벤트를 발생시킵니다.
리지드바디는 오브젝트의 물리적인 움직임을 제어하며, 콜라이더와 함께 사용하여오브젝트간 충돌 및 반응을 구현합니다.
Q. - 유니티 상속 사용이유 -
A. 유니티에서 상속을 사용하면 코드 재사용성을 높일 수 있습니다.
또한 상속을 사용하면 유지보수성을 높일 수 있습니다.
Q. - 유니티 레이캐스트 -
A. 게임에서 화면을 통해 물체에 광선을 쏘아 해당 위치에 대한 정보를 가져오는 기능입니다.
Q. - 유니티 캐싱 -
A. 반복적으로 사용되는 자원을 미리 로드하여 저장하는 기능입니다. 캐싱을 사용하면 자원을 반복적으로 로드하지 않아도 되므로, 게임의 성능을 향상시킬 수 있습니다.
Q. - 유니티 URP -
A. 성능 대비 고품질의 그래픽을 표현하기 위한 렌더 파이프라인입니다.
기존의 경랑 파이프라인이 URP로 변경됐습니다.
유니티 터레인을 사용하기 위해 공부하는 도중 URP를 알게 되었고,
에셋스토어에 존재하는 터레인 샘플 에셋팩을 사용하기위해 설치하게 되었습니다.
Q. - 코루틴, invoke -
A.
코루틴
1. 여러개의 루틴이 동시에 실행되게 해주며 멀티쓰레드가 아닌 유니티에서 마치 멀티쓰레드 처럼 보여 병렬적인 구조를 만드는 기능이다. (단일 쓰레드)
2. 코루틴을 사용할 때는 yield return을 해주어야 하는데, 이를 통해서 현재 위치를 기억하고 다른 루틴에게 수행권한을 넘겨주고 다시와서 처리하는 방식이다.
인보크
1. 함수를 대신 실행시켜줍니다. 또한 간단한 방법으로 지연시간 뒤에 함수를 동작하게도 할 수 있습니다.
2. Invoke는 Reflection을 통해 값을 가져오는데 이 방식이 코루틴 보다는 느립니다.
Reflection
프로그램 실행 도중에 객체의 정보 조사, 다른 모듈에 선언된 인스턴스를 생성, 기존 개체에서 형식을 가져오고 해당하는 메서드를 호출, 접근할 수 있는 강력한 기능입니다.
차이점
GameObject가 비활성화 상태일때 코루틴은 정지하고 인보크는 호출됩니다.(비활성화 > 활성화되더라도 동작 X)
코루틴은 매개변수를 전달가능하고, 인보크는 매개변수를 전달할 수 없습니다.코루틴 사용이유 필요한 순간에만 반복하고 필요하지 않을 때에 정지하여 불필요한 호출을 막기 위해 사용됩니다.
Q. - 프로세스, 쓰레드 -
A.
프로세스
1. 운영체제로부터 자원을 할당받는 독립적인 실행 단위입니다.
2. 프로세스는 다른 프로세스의 오류의 영향을 미치지 않고 독립적으로 실행됩니다.
3. 여러 프로세스가 동시에 실행되면 운영체제의 스케줄러가 CPU 시간을 분해하여 실행됩니다.
쓰레드
1. 한 프로세스 내에서 실행되는 여러 작업의 흐름으로 프로세스 내에서 실행되는 기능 단위 입니다.
2. 여러 쓰레드는 같은 프로세스 내에 존재하므로 하나의 쓰레드가 오류가 발생한다면 다른 쓰레드에 영향을 미칠수 있습니다.
3. 멀티쓰레딩을 통해서 여러 쓰레드가 동시에 실행될 수 있습니다.
Q. - 오브젝트 풀링이란 무엇인가? -
A. 총알 오브젝트같이 자주 사용되면서 바로 사라지는 오브젝트의 경우, 잠깐 동안 할당 삭제가 계속 반복되면 자원소비가
너무 커지기 때문에 특정 오브젝트를 담아 계속 재사용하는 것을 오브젝트 풀링이라고 합니다.
Q. - 객체 지향 프로그래밍이란 ? -
A. 객체 지향 프로그래밍은 객체와 클래스 중심으로 코드를 구성합니다.
추상화, 캡슐화, 상속성, 다형성 개념을 통해 객체 지향 프로그래밍에서 유연하고 확장성을 높일 수 있는 코드를 작성할 수 있습니다.
추상화 : 객체에 필요한 공통된 부분을 추출합니다.
상속성 : 부모 클래스로부터 공통된 변수와 함수, 인터페이스를 그대로 물려받습니다.
캡슐화 : 연관있는 변수와 메서드를 묶어주는 작업입니다. 클래스의 접근을 제한하고, 객체 내에서만 접근 가능하도록 정보를 은닉합니다.
다형성 : 동일한 메서드를 호출하지만 매개변수에 따라 다른 작동을 하게 만드는 것입니다. 그리고 동일한 메서드 이름을 갖고 있지만 서로 다른 클래스에서 다른 기능을 구현할 수 있습니다.(오버로딩, 오버라이딩)
Q. - Interface, abstract, virtual 설명 -
A.
Interface(인터페이스)
1. 메서드 선언만 하고 기능 구현을 갖지 않은 형태의 클래스입니다.
2. 모든 메서드는 추상 메서드로 취급되므로 추상클래스 선언을 사용하지 않아도 됩니다.
3. 인터페이스를 구현하는 클래스는 인터페이스의 모든 메서드를 반드시 구현해야됩니다.
4. 다중 상속이 허용되므로, 여러 개의 인터페이스를 한 클래스에서 구현할 수 있습니다.
abstract(추상 클래스)
1. 일반클래스와 차이로는 추상 메서드를 포함할 수 있습니다.
2. 추상 메서드는 메서드 선언만 있고, 구현은 하위 클래스에서 이뤄집니다. 추상메서드는 'abstract' 키워드를 선언해서 사용해야 합니다.
3. 추상 클래스 자체로는 직접 객체를 만들어서 사용할 수 없습니다.
4. 단일 상속만 허용됩니다.
virtual(가상)
1. 하나의 기능을 하는 완전한 클래스입니다.
2. 파생 클래스에서 상속해서 추가적인 기능 추가 및 재정의 가능합니다.
Q. - 배열과 리스트 차이 -
A.
배열
1. 연속된 메모리 공간으로 이루어져 있어서 메모리 관리가 용이합니다.
2. 배열의 값은 인덱스로 이루어져 있기에 인덱스로 접근 시 빠르게 해당 값을 찾을 수 있습니다.
리스트
1. 리스트는 포인터를 사용하여, 다음 데이터의 주소 값을 가지고 있기에 데이터 추가/삭제가 용이합니다.
2. 포인터를 사용하여 다음 데이터의 주소값을 가지고 있어야 하므로, 불필요한 메모리가 추가로 사용되어 메모리 측면에서는 비효율적이다.
3. 배열에는 인덱스라는 키 값이 존재하지만, 리스트에는 키 값이 존재하지 않기에 검색에 유용하지 않습니다.
차이점
배열은 동적으로 크기 할당이 불가능하고 리스트는 가능합니다.
언제 사용?
데이터의 크기가 정해져 있으면 배열을 사용하고 정해지지 않았다면 리스트를 사용하는것이 좋은 방법입니다.
Q. - Vector와 List의 차이점과 구조 -
A. Vector는 블록을 일렬로 붙여놓은 구조이고, List는 한 바구니에 종이들이 늘어져 있는 구조입니다. Vector는 연속된 저장소에 있기에 연산속도가 빠르지만 추가 삭제할때 해당 부분을 넓히고 줄이는 것이 힘들다는 단점이 있고, List는 앞순서가 뒷순서를 가리키는 방식이라 추가 삭제할때 해당 주소만 연결해 주면되지만 연산속도가 느리다는 단점이 있습니다.
Q. -Map은 어떤 구조로? -
A. 나무뿌리같이 갈래로 뻗어나가는 느낌의 이진트리로 되어있으며, 자료형 Key값을 가지고 Value(값)을 저장하여 사용할 수 있습니다.
Q. - 게임 최적화 방법 -
A. 문자열 연산을 반복할때 StringBuilder 클래스를 사용합니다. >> string 개체를 변경하면 새로운 String 개체가 생성되는 성질때문에 문자열 연산을 반복적으로 수행하면 메모리 낭비가 심해집니다. StringBuilder 클래스는 문자열을 수정할 때 새로운 객체를 생성하지 않고 기존 객체를 변형하기 때문에 문자열 연산을
반복하는 작업에서 StringBuilder를 사용해야합니다.
Update() 함수를 피해야 합니다. >> 매 프레임 마다 호출되는 Update 함수보다는 코루틴 함수를 사용해 불필요한 호출을 피해야 합니다.
나눗셈보다는 곱셈을 사용해야합니다 >> 나눗셈은 곱셈보다 연산속도가 월등히 느리기 때문입니다.
오브젝트 풀링 기법을 사용하여 메모리 관리를 해야합니다. > 동적 생성 및 해제는 부하가 굉장히 큰 작업이기 때문에 활성화/비활성화로 사용합니다.DrawCall 줄여야 합니다 >> Batching 시스템을 사용해야 합니다. 서로 다른 메시에서 같은 메터리얼을 쓰는 경우 Unity에서는 해당 Mesh 정보를 하나로 합쳐서 Draw Call 1개로 처리합니다. 또한 움직이지 않는 정적인 오브젝트의 경우 Static 체크를 통해 하나의 메시로 만들어서 처리합니다.
Draw Call은 CPU가 GPU에게 무엇을, 어떻게 그릴지 정해주고 그리라고 명령하는 것입니다.
다시 말해 하나의 mesh와 하나의 material로 하나의 Draw Call이 발생합니다.
Q. - namespace -
A. 프로젝트에서 협업을 하다 보면 불가피하게 클래스의 이름이 중복될 수 있습니다. 이를 방지하기 위해서 namespace를 사용합니다.
Q. - partial 클래스가 뭔가요? -
A. partial 클래스는 하나의 클래스를 여러개의 파일로 분할할 수 있도록 해주는 기능으로 컴파일시에 하나의 클래스로 인식합니다. 하나의 클래스에서 코딩이 길어지거나 새로운 클래스로 분할 하기 어려울때 사용하여 가독성을 높입니다.
Q. - 싱글톤 패턴이란? -
A. 오직 한개의 클래스 인스턴스만 갖도록 보장하고, 이에 대한 전역적인 접근점을 제공합니다.
단 하나만 존재하는 오브젝트를 손쉽게 쓸 수 있는 필요가 있을때 사용합니다.
단점
모든 곳에서 접근이 가능하므로 싱글톤 객체의 변경 시점, 변경 주체, 호출 시점을 모두 알기가 어렵습니다.
하나의 코드를 수정했을때, 싱글톤과 연결된 다양한 곳들에서 문제가 발생합니다.
Q. - FSM 패턴이란 ? -
A. 상태를 기반으로 동작을 제어하는 방식을 구현하기위한 디자인 패턴입니다.
FSM의 핵심은 단 하나의 상태만을 가진다는 점입니다. 상태를 기준으로 어떤 동작을 수행할지 결정하기 때문에 현재 상태만 알 수 있으면 어떤 동작을 수행하려 하는지 명확히 파악할 수 있고 구현이 쉽다는 장점이 있습니다.
단점
상태가 많아지면 각 상태의 전이를 관리해줘야 하기 때문에 코드가 복잡해 질 수 있습니다. 현재 상태는 하나만 존재하므로 병렬 상태처리가 어렵습니다. 예를들어서 공격하면서 점프와 같이 두상태가 동시에 존재해야하는 경우가 있습니다.
Q. - 알고있는 디자인 패턴 (설명가능) -
A. 싱글톤 패턴, FSM 패턴
Q. - 디자인 패턴이란? -
A.
자주 사용하는 설계 형태를 정형화해서 형식을 만들어 두는 것 입니다. 컴포넌트, 싱글톤, 팩토리, 스트레티지 등 다양한 패턴들이 있습니다.
사용하는 이유
개발자 간에 구조파악이나 의사소통이 원활해지고 재사용을 통해 시간이 단축될 수 있어 사용됩니다.
Q. - 내적/외적 설명 + 언제 사용하는지 -
A.
내적
벡터의 내적은 A 벡터와 B벡터의 크기를 각각 곱한 다음 사이각의 Cos값을 곱한 스칼라 값입니다.
플레이어 시선을 중심으로 좌, 우 90도가 넘어가는 순간 코사인 값은 음수를 갖기 때문에
양수값이면 플레이어 정면, 음수 값이면 플레이 후면에 존재한다는것을 알 수 있습니다.
사용
오브젝트가 앞에 있는지 뒤에 있는지 판별할때 사용합니다.
외적
외적은 내적과 다르게 스칼라 값이 벡터 값이므로 방향을 갖고, 인자의 순서가 반대일 경우,
같은 절대값의 반대부호를 가진 값을 반환합니다
플레이어의 시선과 Up벡터의 중심으로 외적을 구한다면 플레이어의 왼쪽에 있는 오브젝트는 양수,
플레이어의 오른쪽에 있는 오브젝트는 음수를 반환합니다.
사용
오브젝트가 좌우에 있는지 판별할때 사용됩니다.
Q. - STL 컨테이너란? -
A. STL이란 표준 라이브러리중 하나로 프로그램에 필요한 자료구조와 알고리즘을 템플릿으로 제공하는 라이브러리입니다. 그중 컨테이너는 같은 타입을 저장, 관리할 목적으로 만들어졌으며 클래스로 Vector, List, Map등이 있습니다.
Q. - GC(가비지 컬렉터)가 무엇인가? -
A. 힙 영역에 사용자가 할당한 메모리 중 사용하지 않는 가비지를 자동으로 할당 해제해주는 시스템입니다.
Q. - GC(가비지 컬렉터) 최적화 -
A. 가비지를 만들지 않는것이 가장 중요하다고 생각합니다.
오브젝트 풀링 사용이 대표적일거 같고, 그 밖에는 string끼리 합칠때 + 기호를 사용하는데, 이러면 메모리를 조금 더 잡아먹어서 합치는 함수인 Stringbuilder를 사용하는것이 좋다고 생각합니다
Q. - GC(가비지 컬렉터) 세대 -
A. 유니티에선 세대가 사용되지 않는 것으로 알고있습니다. 다른 곳에서의 세대를 얘기해보면, 우선 0세대의 메모리들을
순차적으로 컬렉터가 검사하여 가비지를 골라냅니다. 여기서 걸러지지 않은 메모리들은 1세대로 승급되고, 반복하면 2세대로 승급됩니다. 세대가 높아질수록 더 중요한 메모리라고 판단되어 컬렉터가 덜 검사하게 됩니다.
Q. - .Net과 Unity의 GC(가비지 컬렉터)의 차이 -
A. 내부적으로 GC(가비지 컬렉터)의 알고리즘은 'Mark and Sweep'을 기반으로 하게 되는데 그 이후의 과정이 다르게 됩니다. .Net에서는 0~2세대까지 총 3개의 세대를 통해서 관리를 하게 됩니다. 유니티에서는 'Boehm-Demers-Weiser' 알고리즘을 통해 GC(가비지 컬렉터)작업을 하게 됩니다. 'Mark and Sweep' 인것은 같으나 세대 구분이 없고 메모리 정렬도 필요없습니다. 때문에 19 버전 이상에서 제공하게 되는 점진적 GC(가비지 컬렉터) 작업을 활용하거나 오브젝트 풀링 등의 기법을 활용해서 최대한 최적화를 해줘야 할 필요가 있습니다
Q. - StringBuilder는 어떻게 string보다 수정에 용이할까 -
A. StringBuilder는 기본적으로 16문자를 담을 수 있는 자리를 잡습니다. 이렇게 할당 된 크기 내에서 어떠한 수정을 해도 가비지가 생성되지 않습니다.만일 미리 할당한 버퍼가 다 찬 상태에서 append를 하게 되면 새 버퍼를 할당한 뒤 버퍼간 링크를 구성한다고 합니다. * 다만 .Net 4.0 이전은 C++ vector 처럼 이전의 버퍼를 GC(가비지 컬렉터)로 넘기고 새 버퍼를 할당하는 방식으로 했습니다.
Q. - 유니티 함수들 실행순서 -
A.
1. Awake
2. OnEnable
3. Start
4. FixedUpdate
5. Update
6. LateUpdate
7. yield WaitForEndFrame
8. OnApplicationQuit
9. OnDisable
10. OnDestroy
Q. - 큐, 스택 차이점 -
A. Queue는 선입선출로 가장 먼저 들어온 원소가 가장 먼저 나가는 구조이고, Stack은 후입선출로 가장 늦게 들어온 원소가 가장 먼저 나가는 구조입니다.
Q. - 알고있는 자료 구조에 대해 말해봐라 -
A. 큐, 스택, 트리, 힙, 리스트, 해시테이블, 딕셔너리
Q. - Awake vs Start -
A.
Awake
1. 스크립트와 연결된 GameObject가 인스턴스화 되거나 스크립트가 처음 로드될 때 호출됩니다.
2. 해당 오브젝트가 Enable 상태가 아니라고 해도 위 조건에 따라 로드되면 호출됩니다.
3. 다른 오브젝트에 대한 참조를 생성할 때 주로 사용하게 됩니다
4. Awake 호출은 무작위성으로 인해 다른 스크립트의 참조를 통해 접근을 하면 NullReferenceException이 발생합니다.
Start
1. 해당 스크립트 컴포넌트가 활성화 되는 순간 호출됩니다.
2. 호출 시기는 Awake 보다는 느리게 첫 Update 보다는 빠르게 호출됩니다.
3. Start 에서는 참조를 통해 접근하는 작업이 가능합니다.
Q. - OnEnable vs Start -
A. 둘다 '컴포넌트가 활성화 될 때' 호출된다는 공통점이 있어 묶이게 되지만 Start는 한번, OnEnable은 활성화 될 때 마다 불리게 된다는 차이점이 있습니다.
때문에 초기화 작업에 OnEnable을 활용하면 안됩니다. OnEnable은 주로 오브젝트 풀링에 사용하게 되는 함수라고 볼 수 있습니다.
Q. - Update vs FixedUpdate vs LateUpdate -
A.
Update : 프레임 단위로 호출됩니다.
LateUpdate : Update 호출 뒤 호출됩니다.
FixedUpdate : 고정 단위로 호출되는 함수입니다.
이 고정 단위는 물리 엔진에 의해 결정이 되므로 컴퓨터 성능에 따라 프레임이 다르게 나와 호출 간격이 일정하지 않은 Update와 달리 일정하게 호출됩니다. 이런 이유로 인해서
Rigidbody를 조작할 때는 FixedUpdate를 사용하게 됩니다.
Q. - 박싱, 언박싱 -
A.
박싱 : 값 타입을 참조 타입으로 변경
언박싱 : 참조 타입을 값 타입으로 변경
값 타입
1. C#에서 구조체, 열거 타입 등은 값 타입입니다.
2. System.ValueType으로 부터 항상 상속입니다.
3. 스레드 스택에 할당이 됩니다.
참조 타입
1. C#에서는 모든 클래스는 참조 타입이 됩니다.
2. System.Object로부터 상속입니다.
3. 힙에 저장이 되며 GC(가비지 컬렉터)가 관리하게 됩니다. >> 이 힙 메모리의 주소를 가리키는 값은 스택에 저장이 됩니다.
Q. - 힙, 스택 -
A.
스택
1. 잠깐 사용하고 삭제하는 데이터를 저장합니다.
2. 해당 객체가 정의된 블록을 벗어날 때 소멸됩니다.
3. 힙보다 빠릅니다
힙
1. 가비지 컬렉터가 없으면 프로그래머가 직접 관리 해줘야 합니다.
2. 스택보다 큰 메모리를 할당받기 위해 사용됩니다.
3. 스택보다 느립니다.
반응형'면접준비' 카테고리의 다른 글
유니티 클라이언트 면접준비 - 중요하다고 생각되는것들 (0) 2024.01.29