Unity에서 멀티스레딩 구현 방법
- Unity는 기본적으로 메인 스레드에서 실행되며, 멀티스레딩은 C# Task, Thread, 또는 Unity의 Job System과 Burst Compiler를 통해 구현할 수 있음.
멀티스레딩 구현 방식:
- C# Task:
- 간단한 비동기 작업에 적합.
async void Start() { await Task.Run(() => { // 비동기 작업 수행 }); }
- Unity Job System:
- Unity 엔진과 통합된 고성능 멀티스레딩 도구.
- 데이터 중심의 작업 분할에 적합함.
using Unity.Jobs; struct MyJob : IJob { public void Execute() { // 작업 로직 } } void Start() { MyJob job = new MyJob(); JobHandle handle = job.Schedule(); handle.Complete(); }
- Burst Compiler:
- Unity Job System과 함께 사용하여 CPU 성능을 극대화함.
CPU와 GPU의 작동 차이
- CPU: 논리 연산과 제어 작업에 최적화된 장치로, 복잡한 작업을 처리함.
- GPU: 대규모 병렬 연산에 최적화된 장치로, 그래픽 렌더링 및 데이터 병렬 처리를 담당함.
특징 | CPU | GPU |
작업 성격 | 직렬 연산(순차적) | 병렬 연산 |
용도 | 게임 로직, AI 처리 | 렌더링, 대량 데이터 처리 |
코어 수 | 적은 수의 고성능 코어 | 많은 수의 저전력 코어 |
월드 스페이스(World Space)와 로컬 스페이스(Local Space)의 차이
- 월드 스페이스: 객체가 전체 세계 좌표계에 상대적으로 위치함.
- 로컬 스페이스: 객체가 부모 객체의 좌표계에 상대적으로 위치함.
차이점:
- 월드 스페이스는 절대적인 좌표를 사용하며, 씬 전체의 위치를 나타냄.
- 로컬 스페이스는 객체의 부모-자식 관계를 기반으로 좌표를 나타냄.
예시 코드:
Vector3 worldPosition = transform.position; // 월드 스페이스 위치
Vector3 localPosition = transform.localPosition; // 로컬 스페이스 위치
벡터의 내적과 외적 사용 상황
- 내적(Dot Product):
- 두 벡터의 방향이 얼마나 유사한지 계산.
- 주로 광원 계산, 시야 체크 등에 사용됨.
float dot = Vector3.Dot(vectorA, vectorB); if (dot > 0) Debug.Log("같은 방향");
- 외적(Cross Product):
- 두 벡터의 수직 벡터를 계산.
- 주로 회전 축 계산, 평면 법선 벡터 등에 사용됨.
Vector3 cross = Vector3.Cross(vectorA, vectorB);
쿼터니언을 사용하는 이유
- **쿼터니언(Quaternion)**은 회전을 나타내는 데이터 구조로, Gimbal Lock 문제를 방지하고 효율적인 회전 연산을 가능하게 함.
- Unity에서 회전은 Quaternion을 사용하며, EulerAngles와 호환 가능함.
예시 코드:
// 객체를 회전
transform.rotation = Quaternion.Euler(0, 90, 0);
네트워크 프로토콜(IP, TCP, UDP)
- IP(Internet Protocol): 데이터를 네트워크를 통해 전달하는 프로토콜.
- TCP(Transmission Control Protocol): 신뢰성을 보장하는 연결 기반 프로토콜.
- UDP(User Datagram Protocol): 속도를 우선시하는 비연결형 프로토콜.
TCP와 UDP의 차이:
특징 TCP UDP
연결 | 연결형 | 비연결형 |
신뢰성 | 보장 | 보장하지 않음 |
속도 | 느림 | 빠름 |
사용 예시 | 파일 전송, 채팅 | 스트리밍, 실시간 게임 |
렌더링 파이프라인(Rendering Pipeline)
- 렌더링 파이프라인은 3D 데이터를 화면에 렌더링하는 과정으로, 주요 단계는 다음과 같음:
- Application 단계: 게임 로직 실행.
- Geometry 단계: 객체의 변환 및 조명 계산.
- Rasterization 단계: 3D 객체를 2D 픽셀로 변환.
3D 오브젝트의 픽셀 표현 과정
- 모델링: 3D 객체가 폴리곤으로 정의됨.
- 월드 변환: 객체가 월드 좌표계로 변환됨.
- 뷰 변환: 카메라 좌표계로 변환됨.
- 투영 변환: 3D 좌표를 2D 화면으로 변환함.
- 래스터화(Rasterization): 픽셀로 변환되고 셰이더를 통해 색상 계산.
셰이더를 활용한 경험
- HLSL 셰이더를 사용하여 스킬 연결 효과를 구현한 적이 있음. 스크립트를 참고하여 아래와 같은 셰이더를 작성함.
코드 설명:
Shader "Custom/SkillConnectionLine"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color ("Color", Color) = (1,1,1,1)
_FlowSpeed ("Flow Speed", Float) = 1
_FlowIntensity ("Flow Intensity", Range(0,1)) = 0.5
_GlowIntensity ("Glow Intensity", Range(0,2)) = 1
_IsActive ("Is Active", Float) = 0
}
SubShader
{
Tags { "RenderType"="Transparent" "Queue"="Transparent" }
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off
Cull Off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float4 color : COLOR;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float4 color : COLOR;
};
sampler2D _MainTex;
float4 _Color;
float _FlowSpeed;
float _FlowIntensity;
float _GlowIntensity;
float _IsActive;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.color = v.color;
return o;
}
float4 frag (v2f i) : SV_Target
{
float2 flowUV = i.uv;
flowUV.x += _Time.y * _FlowSpeed * _IsActive;
float4 col = tex2D(_MainTex, flowUV) * _Color * i.color;
if (_IsActive > 0)
{
float flow = sin(flowUV.x * 6.28318 + _Time.y * _FlowSpeed) * 0.5 + 0.5;
flow *= _FlowIntensity;
float glow = 1 - abs