GameEngine
Scene
GameObject : ObjectName / Tag / Layer
DataManager
InputManager
PoolManager
ResourceManager
ScneneManager
SoundManager
UIManager
Transform
Rigidbody
CapsuleCollider
SphereCollider
BoxCollider
Camera
AudioListender
Light
MeshFilter
MeshRenderer
NavMeshAgent
Material
Animator
Poolable
RectTransform
CanvasRenderer
Image
Text
Button
DefaultUIMaterial
AnimationController
Animation
EntryPoint
GameProcess
void GameEngine::Process()
{
// Time TimeManager deltaTime 계산
m_timeManager->ProcessDeltaTime();
float deltaTime = m_timeManager->GetDeltaTime();
// Input InputManger 유저 키입력 체크
m_inputManager->ProcessUserInput();
// Physics SceneManager FIXED_DELTATIME FixedUpdate() 처리
constexpr float PHYSICS_DELTATIME = 0.02f;
m_elapsedPhysicsTime += deltaTime;
while (m_elapsedPhysicsTime >= PHYSICS_DELTATIME)
{
m_sceneManager->FixedUpdate(PHYSICS_DELTATIME);
m_elapsedPhysicsTime -= PHYSICS_DELTATIME;
}
// Update - Object 현재 Scene GameObject Update()
m_sceneManager->Update(deltaTime);
// Update - Collision 현재 충돌 상태 CollisionManager 처리
m_collisionManager->ProcessCollision(deltaTime);
// UI UI Event 처리
m_UIManager->ProcessUIEvent();
// Camera Camera이동
m_cameraManager->ProcessCamera();
// Render Renderer에서 BeginRender
m_renderer->BeginRender();
// GameObject Render 현재 씬에 있는 GameObject에 있는 Render 대상인 Component MeshRenderer
m_sceneManager->Render(m_renderer);
m_renderer->EndRender();
// DebugRender Time/Scene/Camera
}
// 2957번 이진 탐색 트리
/*
그 시점에서 만들어진 BT의 height 누적 합
set 입력받는 수
map 입력받는수, BT에서 height
X의 높이: max(X보다 작으면서 가장 큰 값 높이 / X보다 크면서 가장 작은 값 높이) + 1
https://everenew.tistory.com/102
*/
deffered rendering 할 때 사용한다
어두운 곳을 더 어둡게 한다
음영이 생길 확률을 계산 → blur로 부드럽게 하기
// 2812번 크게 만들기
/*
앞자리 가장 큰 수 유지 -> 앞에서부터 뺄 수 있을만큼 빼면서 크게 만들기
현재 수보다 작은 수가 앞에 있으면 지우기
끝까지 갔는데 cnt 남았으면 뒤에서 빼서 맞춰주기
결과 string 이여서 char로 넣기
시간초과 난다!
string (+) 연산 -> 벡터에 넣기
*/
톤을 다르게 할 수 있다 → 씬의 시간대, 분위기를 만들 수 있다
Color Grading으로 라이트 변화 X
FBX File
Hair and Fur Simulation / Cloth Simulation
Anim Curves / Anim Notifies
Pose Assets
State Machine / Event Graph
Controller / Pawn
LODs / Multi-Threaded Update
Render Target / Texture / Compression / Derived Data Cache
Shading Model / Per Pixel Shading / Material Node
Shader Permutations
Render Target
UI / Post Processing / Surface
All Logic
Distance Culling / Frustrum Culling / Mesh LODs / Visibility Culling / Occlusion Visibility Processes
Scan Depth
Static Meshes / Instanced Static Meshes / Skeletal Meshes / Landscapes / Procedural Meshes / Geometry Collection
Drawcalls / Lightmaps
Global Illumination Radiosity
Buffer A / B / C / D / E
Dynamic Shadows
Raytraced GI
Capsule Shadows
Tone mapper / Bloom / Screen Space Ambient Occlusion / Screen Space Sub Surface Scattering / Screen Space Global Illumination / Depth of Field / Exposure
Normalize 해서 벡터 크기 1만들어서 사용하기 때문에 한다
float long으로 바꾼다
u인 매직 넘버 뺀다
뉴턴 미적분으로 근사치 정확도 높힌다
static float InvSqrt(float InFloat)
{
// Performs two passes of Newton-Raphson iteration on the hardware estimate
// v^-0.5 = x
// => x^2 = v^-1
// => 1/(x^2) = v
// => F(x) = x^-2 - v
// F'(x) = -2x^-3
// x1 = x0 - F(x0)/F'(x0)
// => x1 = x0 + 0.5 * (x0^-2 - Vec) * x0^3
// => x1 = x0 + 0.5 * (x0 - Vec * x0^3)
// => x1 = x0 + x0 * (0.5 - 0.5 * Vec * x0^2)
//
// This final form has one more operation than the legacy factorization (X1 = 0.5*X0*(3-(Y*X0)*X0)
// but retains better accuracy (namely InvSqrt(1) = 1 exactly).
const __m128 fOneHalf = _mm_set_ss(0.5f);
__m128 Y0, X0, X1, X2, FOver2;
float temp;
Y0 = _mm_set_ss(InFloat);
X0 = _mm_rsqrt_ss(Y0); // 1/sqrt estimate (12 bits)
FOver2 = _mm_mul_ss(Y0, fOneHalf);
// 1st Newton-Raphson iteration
X1 = _mm_mul_ss(X0, X0);
X1 = _mm_sub_ss(fOneHalf, _mm_mul_ss(FOver2, X1));
X1 = _mm_add_ss(X0, _mm_mul_ss(X0, X1));
// 2nd Newton-Raphson iteration
X2 = _mm_mul_ss(X1, X1);
X2 = _mm_sub_ss(fOneHalf, _mm_mul_ss(FOver2, X2));
X2 = _mm_add_ss(X1, _mm_mul_ss(X1, X2));
_mm_store_ss(&temp, X2);
return temp;
}
FORCEINLINE static float FMod(float X, float Y)
{
if (fabsf(Y) <= SMALL_NUMBER)
{
return 0.f;
}
const float quotient = (float)TruncToInt(X / Y);
float intPortion = Y * quotient;
if (fabsf(intPortion) > fabsf(X))
{
intPortion = X;
}
return (X - intPortion);
}
/// <summary>
/// Euler Angle를 가지고 있는 Rotator를 쿼터니언으로 변환
/// </summary>
/// <param name="inRotator"></param>
Quaternion::Quaternion(const Rotator& inRotator)
{
float sinPitch = 0.f, sinYaw = 0.f, sinRoll = 0.f;
float cosPitch = 0.f, cosYaw = 0.f, cosRoll = 0.f;
sinPitch = sinf(inRotator.pitch * 0.5f);
sinYaw = sinf(inRotator.yaw * 0.5f);
sinRoll = sinf(inRotator.roll * 0.5f);
cosPitch = cosf(inRotator.pitch * 0.5f);
cosYaw = cosf(inRotator.yaw * 0.5f);
cosRoll = cosf(inRotator.roll * 0.5f);
w = sinYaw * sinPitch * sinRoll + cosYaw * cosPitch * cosRoll;
x = sinYaw * sinRoll * cosPitch + sinPitch * cosRoll * cosYaw;
y = sinYaw * cosPitch * cosRoll - sinPitch * sinRoll * cosYaw;
z = -sinYaw * sinPitch * cosRoll + sinRoll * cosYaw * cosPitch;
}
표면에서 빛이 산란하는 방식을 설명하는 모델
BRDF : 표면에서 빛 반사 Bidirectional Reflectance Distribution function
BTDF : 표면에서 빛 투과 Bidirectional Transmittance Distribution function
BSDF : 반사 + 투과
Masking / Shadowing
표면에서 반사할 때 빛 각도에 대한 각 재질의 수치
// 모든 점들 중 가장 먼 점 찾기
Vector3 farthestPoint = (*std::max_element(points.begin(), points.end(),
[&](Vector3 const& lhs, Vector3 const& rhs)
{
return (center - lhs).SizeSquared() < (center - rhs).SizeSquared();
}));
Character Movement Component / Movement Component
Navigation Mesh
Camera Manager / Camera / Springarm Component / Camera Component
GameMode / PlayerState
Actions / Axis / Input Component
Network Framework
Static Meshes / Skeletal Meshes / Geometry / Procedural Mesh / Landscapes / Skies
Audio Actors / Reflection Captures / Light Actors / BP Actors / Gameplay
Sequencer / World Properties / Level Blueprint
Navmesh Agent / Navmesh / Lightmaps / Volumetric Lightmaps / Lighting / Hierachical LODs
Stats / GPU Profiler / Statistics Panels / View Modes / Cull Max Draw Distance
Inheritance / Framework / Events Functions Variables / Function Libraries
Replication / Actor / GameMode / Pawn / Controller / GameState / PlayerState / Character/ AI Controller / PlayerController
Data Tables / Data Assets / Curves
Components / Event Graph
Variables / Function / Macro
Actor BP / Level BP / Anim BP / Sequencer / Niagara
Direct References / Casting / C++
Build → Cooking → Staging → Saved & Cooked → Packaging
Engine / Referenced Assets / DLL Modules / Game Level
Folder Structure / UProject
Material / Skeletal Mesh / Blueprint / Sequencer / Niagara
AssetManager / Primary Assets / UAssets / Derived Data Cache / Assets / Import
Network Framework
Loading Assets / Garbage Collector / Memory Management
GameInstance / Ticking / Subsystems
GameState / GameMode
Player State / PlayerController / Input Component / Pawn & Character
Enum / Strings / Structs / Collections / Transform Types
Fstring / FName / FText
TMap / TArray / TSet
FVector / FRotator / FQuat / FTransform
UObject / Actor / Components / Life Cycle / Smart Pointers
TWeakPtr / TSharedPtr / TSharedRef/ TUniquePtr
Creation / Destruction
Specifiers / Data Objects / Data Tables / Data Assets / Curves
Player
Monster
NPC
Item
Projectile
Background
Player, Monster, NPC
→ Static O / Kinematic O / Static O
움직이는 플랫폼, 중력 X
→ Dynamic O / Kinematic X / Static X
Background
→ Dynamic X / Kinematic X / Static X
Collider 만 붙힌다
Projectile / Item
| Player | Monster | NPC | Item | Projectile | Ground | |
|---|---|---|---|---|---|---|
| Player | O | O | O | O | O | |
| Monster | X | X | O | O | ||
| NPC | X | X | O | |||
| Item | X | X | ||||
| Projectile | X | |||||
| Ground |
Player
UpdateIdle()
{
// #[SPACE]키
→ State.Jumping
→ rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
}
UpdateMoving()
{
// #[SPACE]키
→ State.Jumping
→ rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
}
OnCollisionEnter(Collision)
{
// #몬스터 && (State.Idle || State.Moving || State.Jumping)
→ 플레이어 피 깎고 플레이어 보던 반대 방향으로 밀기
// #Ground
→ State.Idle
}
OnCollisoinStay()
{
// #NPC && [ALT]키
→ NPC에 맞는 대화 시작하기
}
OnTriggerEnger(Collider)
{
// #Item
→ 각 아이템에 맞는 처리 하고 아이템 삭제하기
// #Projectile
→ 플레이어 피 깎기
}
while (1)
{
// 입력 처리
g_hidManager->Poll();
// 애니메이션 엔진 업데이트
g_gameObjectManager->PreAnimationUpdate(dt);
g_animationEngine->UpdateAnimations(dt);
g_gameObjectManager->PostAnimationUpdate(dt);
// 물리 엔진 업데이트
g_physicsWorld->Step(dt);
// 랙돌 피직스 업데이트
g_animationEngine->UpdateRagDolls(dt);
// 물리 엔진 업데이트 이후 처리
g_gameObjectManager->postPhysicsUpdate(dt);
// 애니메이션 엔진 업데이트 이후 처리
g_animationEngine->finalize();
// 이펙트 엔진 업데이트
g_effectManager->Update(dt);
// 오디오 엔진 업데이트
g_audioEngine->Update(dt);
// 렌더링 엔진 업데이트
g_renderManager->Render(dt);
// dt 계산
dt = CalculateDeltaTime();
}
/// <summary>
/// Start 스크립트 인스턴스가 활성화된 경우에만 첫 번째 프레임 업데이트 전에 호출됩니다
/// </summary>
void Initialize()
{
AWake();
OnEnable();
Reset();
Start();
}
/// <summary>
/// FixedUpdate는 종종 Update보다 더 자주 호출됩니다.
/// 프레임 속도가 낮은 경우 프레임당 여러 번 호출될 수 있으며,
/// 프레임 속도가 높은 경우 프레임 사이에 전혀 호출되지 않을 수도 있습니다.
/// 모든 피직스 계산과 업데이트는 FixedUpdate 직후에 발생합니다.
/// FixedUpdate 내에서 이동 계산을 적용할 때 값에 Time.deltaTime을 곱할 필요가 없습니다.
/// 이는 FixedUpdate가 프레임 속도와 무관하게 안정적인 타이머에 호출되기 때문입니다.
/// </summary>
void Physics()
{
FixedUpdate();
// === Internal Animation Update ===
StateMachineUpdate();
OnStateMachineEnterExit();
ProcessGraph();
FireAnimationEvents();
StateMachineBehaviourCallbacks();
OnAnimatorMove();
InternalPhysicsUpdate();
// === Internal Animation Update ===
ProcessAnimation();
OnAnimatorIK();
WriteTransform();
WriteProperties();
OnTriggerXXX();
OnCollisionXXX();
}
void InputEvents()
{
OnMouseXXX();
}
/// <summary>
/// Update는 프레임당 한 번 호출됩니다. 프레임 Update의 주요 핵심 기능입니다.
///
/// LateUpdate는 업데이트가 완료된 후 프레임당 한 번 호출됩니다.
/// Update에서 수행되는 모든 계산은 LateUpdate가 시작될 때 완료됩니다.
/// LateUpdate의 일반적인 용도는 3인칭 카메라 팔로잉입니다.
/// Update 안에서 캐릭터를 움직이고 회전하게 하면 LateUpdate에서 모든 카메라 이동 및 회전 계산을 수행할 수 있습니다.
/// 이렇게 하면 카메라가 위치를 추적하기 전에 캐릭터가 완전히 이동했는지 확인할 수 있습니다
/// </summary>
void GameLogic()
{
Update();
// === Internal Animation Update ===
StateMachineUpdate();
OnStateMachineEnterExit();
ProcessGraph();
FireAnimationEvents();
StateMachineBehaviourCallbacks();
OnAnimatorMove();
ProcessAnimation();
OnAnimatorIK();
WriteTransform();
WriteProperties();
LateUpdate();
}
/// <summary>
/// OnPreCull: 카메라가 씬을 컬링하기 전에 호출됩니다. 컬링은 카메라에 표시되는 오브젝트를 결정합니다. OnPreCull은 컬링이 발생하기 직전에 호출됩니다.
/// OnBecomeVisible / OnBecomeInvisible: 오브젝트가 카메라에 표시 / 비표시될 때 호출됩니다.
/// OnWillRenderObject : 오브젝트가 보이는 경우 각 카메라에 대해 한 번씩 호출됩니다.
/// OnPreRender : 카메라가 씬 렌더링을 시작하기 전에 호출됩니다.
/// OnRenderObject : 모든 일반 씬 렌더링이 완료된 후 호출됩니다.이 시점에서 GL 클래스 또는 Graphics.DrawMeshNow를 사용하여 커스텀 지오메트리를 그릴 수 있습니다.
/// OnPostRender : 카메라가 씬 렌더링을 완료한 후에 호출됩니다.
/// OnRenderImage : 이미지의 포스트 프로세싱을 허용하기 위해 씬 렌더링이 완료된 후 호출됩니다.
/// </summary>
void SceneRendering()
{
OnPreCull();
OnWillRenderObject();
OnBecameVisible();
OnBecameInvisible();
OnPreRender();
OnRenderObject();
OnPostRender();
OnRenderImage();
}
void GUIRendering()
{
OnGUI();
}
/// <summary>
/// 일시 정지가 감지된 프레임이 끝날 때 호출되며,
/// 사실상 일반 프레임 업데이트 사이에 호출됩니다.
/// OnApplicationPause가 호출된 후 한 프레임이 추가로 발행되어 게임에서 일시 중지 상태를 나타내는 그래픽을 표시할 수 있습니다.
/// </summary>
void Pausing()
{
OnApplicationPause();
}
void Decommisioning()
{
OnApplicationQuit();
OnDisable();
OnDestroy();
}
int main()
{
Initialize();
while (true)
{
Physics();
InputEvents();
GameLogic();
SceneRendering();
GizmoRendering();
GUIRendering();
EndOfFrame();
if (Paused)
{
Pausing();
}
}
Decommisioning();
}
Transform에서 Parent-Child구조를 갖고 있는다
Scene에서 전부 갖고있기 X
Parent → Child로 Update / FixedUpdate / Render 등 전체 루프 재귀적으로 돌려준다
하나의 Entity안에 있는 Component는 Define에 있는 Component Order대로 실행한다
Collision Layer에서 설정한 Layer들끼리만 충돌한다
HDR 데이터 → LDR : float → byte
지형 만들 때 쓴다
공간 4분할 트리구조 + 6면 모두 안쪽에 있는 것 그리기
충돌처리 X
갈 수 있는 영역인지 아닌지 판단
entity.lock()->SetScene(shared_from_this());
this로 shared를 만들어서 넘겨줄 수 있다
Transform
Collider / BoxCollider / Collision / Rigidbody / CollisionManager / PhysicsManager
언리얼 강의 듣던 내용 마저 듣기
DX강의 보기
모던 C++ 챌린지 따라 치고 정리하기
이득우의 게임수학 책 읽기
리얼타임 렌더링 책 읽기
게임엔진 책 읽기
나중에 볼 영상 다 보기
공부 폴더 유튜브 다 보기
면접 질문 다시 쭉 쓰기
1Q2Q4Q 내용 정리하기
모든 Collider들을 CollisionManager에 등록시킬까…?
처음에 그냥 float 값 get set이 필요한 줄 알았다. float GetYaw / AddYawRotation(float)로 회전값을 float 값으로 변경이 가능했다
변수로 Vector3 프로퍼티를 가져야 한다고 해서 Rotator에 ToVector3를 추가, Quarternion에 ToVector3를 추가 했다. 그래서 Vector3 m_eulerAngle에 Quarternion이 수정되면 값이 바뀌게 두었다.
m_eulerAngle 값 에디터에서 조절해서 값 바꿔야 한다
현재 m_rotation을 바꾸면 m_eulerAngle을 바꾸게는 했다.
m_eulerAngle 바꾸면 어떻게 m_rotation 바꿔주지…?
X pitch Y yaw Z roll
Add()함수 호출…? 에디터에서 변경할 때 값만 바꾸는거 아닌가…?
값을 바꿀 때 원하는 함수를 호출할 수 있다!
reflection으로 에디터에서 값을 변경할 때
AddPitchRotation() / AddYawRotation() / AddRollRotation() 불러 주기로 했다.
표준이 아니다 c++에서는 = 0 만 표준이다
MS에서 만든 내용이여서 당연하게 썼고 이게 표준인 줄 알았다.
Entity들의 부모자식관계를 갖고있다. 그래서 자식 Entity e의 Component 하나를 업데이트 하기 위해서 Entity parent Transform에서 갖고와야한다.
Parent component update 후에 본인의 트랜스폼에서 자식의 트랜스폼을 전부 갖고온다. 그래서 자식 오브젝트로 접근해서 자식 오브젝트의 해당 컴포넌트를 업데이트 한다.
오브젝트에서 컴포넌트들을 업데이트 할 때 중간에 트랜스폼을 왔다갔다 하는 것이 적합한지에 대한 의문이다. 기능을 제공해 Component이지만 Entity의 Component를 Update 하기 위해서는 필수적으로 존재한다. 의존성이 역전이 된 것 같다.
CPU → GPU로 버텍스 데이터를 다시 넘기기 X
offset 정보만 넣어서 SRT 조정하기 O
뒷면 컬링 해주기, 뒷면 결정 방향 정하기
scale이 다른 연산에 영향을 안 미친다