Skip to content

✍️ 필사 모드: Game Development Complete Guide 2025: Unity vs Unreal vs Godot, ECS, Multiplayer, Optimization

English
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

1. Game Engine Selection Guide

In 2026, game development has more viable choices than ever. Unity remains strong in indie mobile and mid-range PC, Unreal Engine 5 brings AAA visual quality to everyone, and Godot 4 is rapidly growing in the open-source camp.

1.1 Engine Comparison

AspectUnityUnreal Engine 5Godot 4
LicenseRevenue-based (Personal Free, Pro $2040/year)5% royalty after $1MFree, MIT
Main languageC#C++ / BlueprintGDScript / C#
Learning curveMediumSteepEasy
Graphics qualityURP/HDRPLumen, NaniteOpenGL/Vulkan
Mobile optimizationExcellentGood (Mobile renderer)Good
Console supportAll consolesAll consolesLimited
MarketplaceAsset Store (huge)Marketplace (good)AssetLib (growing)
Build sizeSmall to mediumLargeVery small
Indie recommendedGoodGoodExcellent
AAA recommendedPossibleStandardNot suitable

1.2 Which Engine to Pick?

Pick Unity for: mobile games, 2D games, fast prototyping, large community needs, AR/VR cross-platform.

Pick Unreal for: visual fidelity is top priority, open worlds, photorealistic graphics, cinematic cutscenes.

Pick Godot for: indie projects, learning, zero license fees, small games, lightweight engine.

2. Unity Deep Dive

2.1 MonoBehaviour vs DOTS/ECS

// Traditional MonoBehaviour
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    [SerializeField] private float speed = 5f;
    [SerializeField] private float jumpForce = 10f;

    private Rigidbody rb;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    void Update()
    {
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");

        Vector3 movement = new Vector3(horizontal, 0, vertical) * speed * Time.deltaTime;
        transform.Translate(movement);

        if (Input.GetKeyDown(KeyCode.Space) && IsGrounded())
        {
            rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
        }
    }

    bool IsGrounded()
    {
        return Physics.Raycast(transform.position, Vector3.down, 1.1f);
    }
}
// Unity DOTS/ECS
using Unity.Entities;
using Unity.Mathematics;
using Unity.Burst;

public struct PlayerInput : IComponentData
{
    public float2 Move;
    public bool Jump;
}

public struct Velocity : IComponentData
{
    public float3 Value;
}

public struct PlayerSpeed : IComponentData
{
    public float Value;
}

[BurstCompile]
public partial struct PlayerMovementSystem : ISystem
{
    [BurstCompile]
    public void OnUpdate(ref SystemState state)
    {
        float deltaTime = SystemAPI.Time.DeltaTime;

        foreach (var (input, velocity, speed, transform)
            in SystemAPI.Query<RefRO<PlayerInput>, RefRW<Velocity>, RefRO<PlayerSpeed>, RefRW<LocalTransform>>())
        {
            float3 movement = new float3(input.ValueRO.Move.x, 0, input.ValueRO.Move.y) * speed.ValueRO.Value;
            velocity.ValueRW.Value = movement;
            transform.ValueRW.Position += movement * deltaTime;
        }
    }
}

2.2 Job System and Burst Compiler

using Unity.Collections;
using Unity.Jobs;
using Unity.Burst;
using Unity.Mathematics;

[BurstCompile]
public struct ParallelMovementJob : IJobParallelFor
{
    public NativeArray<float3> Positions;
    [ReadOnly] public NativeArray<float3> Velocities;
    public float DeltaTime;

    public void Execute(int index)
    {
        Positions[index] += Velocities[index] * DeltaTime;
    }
}

public class JobScheduler : MonoBehaviour
{
    public void UpdatePositions()
    {
        var positions = new NativeArray<float3>(10000, Allocator.TempJob);
        var velocities = new NativeArray<float3>(10000, Allocator.TempJob);

        var job = new ParallelMovementJob
        {
            Positions = positions,
            Velocities = velocities,
            DeltaTime = Time.deltaTime
        };

        JobHandle handle = job.Schedule(positions.Length, 64);
        handle.Complete();

        positions.Dispose();
        velocities.Dispose();
    }
}

2.3 Addressables - Async Asset Management

using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;

public class AddressableLoader : MonoBehaviour
{
    [SerializeField] private AssetReferenceGameObject playerPrefab;

    async void Start()
    {
        AsyncOperationHandle<GameObject> handle = playerPrefab.InstantiateAsync();
        await handle.Task;

        if (handle.Status == AsyncOperationStatus.Succeeded)
        {
            GameObject player = handle.Result;
            Debug.Log($"Loaded: {player.name}");
        }
    }

    void OnDestroy()
    {
        Addressables.Release(playerPrefab);
    }
}

2.4 URP vs HDRP

FeatureURP (Universal)HDRP (High Definition)
TargetMobile, VR, console, low-end PCHigh-end PC, console
QualityGoodCinematic
PerformanceExcellentHeavy
LightingForward, Forward+Deferred, Forward
Use caseIndie, mobileAAA, simulators

3. Unreal Engine 5 Deep Dive

3.1 Blueprint vs C++

Unreal offers two workflows. Blueprint is visual node-based (great for prototyping), C++ for performance and complex logic.

#include "MyCharacter.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"

AMyCharacter::AMyCharacter()
{
    PrimaryActorTick.bCanEverTick = true;

    SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
    SpringArm->SetupAttachment(RootComponent);
    SpringArm->TargetArmLength = 400.0f;
    SpringArm->bUsePawnControlRotation = true;

    Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
    Camera->SetupAttachment(SpringArm, USpringArmComponent::SocketName);

    GetCharacterMovement()->bOrientRotationToMovement = true;
    GetCharacterMovement()->RotationRate = FRotator(0.0f, 540.0f, 0.0f);
    GetCharacterMovement()->JumpZVelocity = 600.0f;
    GetCharacterMovement()->AirControl = 0.2f;
}

void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
    Super::SetupPlayerInputComponent(PlayerInputComponent);

    PlayerInputComponent->BindAxis("MoveForward", this, &AMyCharacter::MoveForward);
    PlayerInputComponent->BindAxis("MoveRight", this, &AMyCharacter::MoveRight);
    PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
}

void AMyCharacter::MoveForward(float Value)
{
    if (Value != 0.0f)
    {
        const FRotator Rotation = Controller->GetControlRotation();
        const FRotator YawRotation(0, Rotation.Yaw, 0);
        const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
        AddMovementInput(Direction, Value);
    }
}

3.2 Lumen - Dynamic Global Illumination

Lumen is one of UE5's flagship features, handling real-time indirect lighting and reflections without baking.

APostProcessVolume* PPV = ...;
PPV->Settings.bOverride_DynamicGlobalIlluminationMethod = true;
PPV->Settings.DynamicGlobalIlluminationMethod = EDynamicGlobalIlluminationMethod::Lumen;
PPV->Settings.bOverride_LumenSurfaceCacheResolution = true;
PPV->Settings.LumenSurfaceCacheResolution = 1.0f;

3.3 Nanite - Virtualized Geometry

Nanite automatically LODs billions of polygons. Modelers no longer need to author manual LODs.

UStaticMesh* Mesh = ...;
Mesh->NaniteSettings.bEnabled = true;
Mesh->NaniteSettings.PositionPrecision = 0;
Mesh->NaniteSettings.PercentTriangles = 1.0f;

3.4 World Partition

Automatically divides massive open worlds into grid cells, loading only what's needed.

4. Godot 4 Deep Dive

4.1 GDScript - Python-like Scripting

extends CharacterBody3D

const SPEED = 5.0
const JUMP_VELOCITY = 4.5

var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")

func _physics_process(delta):
    if not is_on_floor():
        velocity.y -= gravity * delta

    if Input.is_action_just_pressed("jump") and is_on_floor():
        velocity.y = JUMP_VELOCITY

    var input_dir = Input.get_vector("move_left", "move_right", "move_forward", "move_back")
    var direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()

    if direction:
        velocity.x = direction.x * SPEED
        velocity.z = direction.z * SPEED
    else:
        velocity.x = move_toward(velocity.x, 0, SPEED)
        velocity.z = move_toward(velocity.z, 0, SPEED)

    move_and_slide()

4.2 Scene System and Signals

extends Node

signal player_died(score)
signal score_changed(new_score)

var score = 0:
    set(value):
        score = value
        score_changed.emit(score)

func _ready():
    var player = $Player
    player.died.connect(_on_player_died)

func _on_player_died():
    player_died.emit(score)
    get_tree().reload_current_scene()

func add_score(amount: int):
    score += amount

4.3 C# Support (Mono)

using Godot;

public partial class PlayerController : CharacterBody3D
{
    public const float Speed = 5.0f;
    public const float JumpVelocity = 4.5f;

    public float Gravity = ProjectSettings.GetSetting("physics/3d/default_gravity").AsSingle();

    public override void _PhysicsProcess(double delta)
    {
        Vector3 velocity = Velocity;

        if (!IsOnFloor())
            velocity.Y -= Gravity * (float)delta;

        if (Input.IsActionJustPressed("jump") && IsOnFloor())
            velocity.Y = JumpVelocity;

        Vector2 inputDir = Input.GetVector("move_left", "move_right", "move_forward", "move_back");
        Vector3 direction = (Transform.Basis * new Vector3(inputDir.X, 0, inputDir.Y)).Normalized();

        if (direction != Vector3.Zero)
        {
            velocity.X = direction.X * Speed;
            velocity.Z = direction.Z * Speed;
        }
        else
        {
            velocity.X = Mathf.MoveToward(Velocity.X, 0, Speed);
            velocity.Z = Mathf.MoveToward(Velocity.Z, 0, Speed);
        }

        Velocity = velocity;
        MoveAndSlide();
    }
}

5. Game Loop Fundamentals

// Pseudocode: the heart of every game engine
while (gameRunning)
{
    ProcessInput();
    Update(deltaTime);
    Render();
    SyncFrameRate();
}

5.1 Fixed vs Variable Timestep

public class Player : MonoBehaviour
{
    void Update()
    {
        // Input, camera, UI - variable timestep
        ProcessInput();
    }

    void FixedUpdate()
    {
        // Physics, AI - fixed timestep (50Hz default in Unity)
        ApplyPhysics();
    }
}

6. Physics Engines

6.1 PhysX vs Chaos vs Bullet vs Box2D

EngineUsed inNotes
PhysX (NVIDIA)Unity, older UnrealStable, GPU acceleration
ChaosUnreal Engine 5+Epic in-house, destruction sim
BulletBlender, Godot partialOpen-source, rigid/soft body
Box2D2D gamesLightweight, accurate
public class BallController : MonoBehaviour
{
    private Rigidbody rb;
    public float bounciness = 0.8f;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
        var material = new PhysicMaterial
        {
            bounciness = bounciness,
            dynamicFriction = 0.6f,
            staticFriction = 0.6f
        };
        GetComponent<Collider>().material = material;
    }

    void OnCollisionEnter(Collision collision)
    {
        Debug.Log($"Hit: {collision.gameObject.name} at {collision.relativeVelocity.magnitude}");
    }
}

7. Multiplayer Architectures

7.1 Network Model Comparison

ModelProsConsBest for
Peer-to-PeerZero server costNAT issues, cheatingIndie co-op
Client-ServerAuthoritative, stableServer costCompetitive
Dedicated ServerBest stabilityMost expensiveAAA FPS, MOBA
Listen ServerHost is serverDies with hostCasual co-op

7.2 Unity Netcode for GameObjects

using Unity.Netcode;
using UnityEngine;

public class NetworkPlayer : NetworkBehaviour
{
    [SerializeField] private float moveSpeed = 5f;

    private NetworkVariable<int> health = new NetworkVariable<int>(100,
        NetworkVariableReadPermission.Everyone,
        NetworkVariableWritePermission.Server);

    public override void OnNetworkSpawn()
    {
        if (IsOwner)
        {
            Camera.main.GetComponent<CameraFollow>().target = transform;
        }
        health.OnValueChanged += OnHealthChanged;
    }

    void Update()
    {
        if (!IsOwner) return;

        Vector3 input = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
        if (input.magnitude > 0.1f)
        {
            MoveServerRpc(input * moveSpeed * Time.deltaTime);
        }

        if (Input.GetKeyDown(KeyCode.Space))
        {
            ShootServerRpc();
        }
    }

    [ServerRpc]
    void MoveServerRpc(Vector3 movement)
    {
        transform.position += movement;
    }

    [ServerRpc]
    void ShootServerRpc()
    {
        var bullet = Instantiate(bulletPrefab, transform.position, transform.rotation);
        bullet.GetComponent<NetworkObject>().Spawn();
    }

    [ClientRpc]
    void TakeDamageClientRpc(int damage)
    {
        if (IsOwner)
        {
            ShowDamageUI(damage);
        }
    }

    void OnHealthChanged(int previous, int current)
    {
        UpdateHealthBar(current);
    }
}

7.3 Mirror Networking

using Mirror;
using UnityEngine;

public class MirrorPlayer : NetworkBehaviour
{
    [SyncVar(hook = nameof(OnHealthChanged))]
    public int health = 100;

    void OnHealthChanged(int oldHealth, int newHealth)
    {
        Debug.Log($"Health: {oldHealth} -> {newHealth}");
    }

    void Update()
    {
        if (!isLocalPlayer) return;

        if (Input.GetKeyDown(KeyCode.Space))
        {
            CmdShoot();
        }
    }

    [Command]
    void CmdShoot()
    {
        RpcPlayShootEffect();
    }

    [ClientRpc]
    void RpcPlayShootEffect()
    {
        Instantiate(muzzleFlash, transform.position, transform.rotation);
    }
}

7.4 Photon vs Steamworks

  • Photon: Cloud-based, easy to use, freemium
  • Steamworks: Steam P2P, friends integration, standard for Steam games

8. Performance Optimization

8.1 Draw Call Optimization

Draw calls are commands sent to the GPU. Too many causes CPU bottleneck.

// Static batching
public class StaticOptimizer : MonoBehaviour
{
    void Start()
    {
        StaticBatchingUtility.Combine(gameObject);
    }
}

// GPU Instancing
public class InstancedRenderer : MonoBehaviour
{
    public Mesh mesh;
    public Material material;
    public int count = 10000;

    private Matrix4x4[] matrices;

    void Start()
    {
        matrices = new Matrix4x4[count];
        for (int i = 0; i < count; i++)
        {
            matrices[i] = Matrix4x4.TRS(
                Random.insideUnitSphere * 100,
                Quaternion.identity,
                Vector3.one
            );
        }
    }

    void Update()
    {
        Graphics.DrawMeshInstanced(mesh, 0, material, matrices, count);
    }
}

8.2 LOD (Level of Detail)

public class LODSetup : MonoBehaviour
{
    void Start()
    {
        LODGroup group = gameObject.AddComponent<LODGroup>();
        LOD[] lods = new LOD[3];

        lods[0] = new LOD(0.6f, GetRenderers(0));
        lods[1] = new LOD(0.3f, GetRenderers(1));
        lods[2] = new LOD(0.1f, GetRenderers(2));

        group.SetLODs(lods);
        group.RecalculateBounds();
    }

    Renderer[] GetRenderers(int level)
    {
        return new Renderer[] { transform.GetChild(level).GetComponent<Renderer>() };
    }
}

8.3 Occlusion Culling

Skip rendering objects hidden behind walls. Unity auto-bakes; Unreal uses Visibility System.

8.4 Texture Optimization

FormatMobilePCConsole
ASTCiOS, modern AndroidPartialPartial
ETC2AndroidNoNo
BC7NoPC standardPS5, Xbox

9. Asset Pipeline

9.1 Model Import Best Practices

  • Polygon count: characters 5k-50k, environment 1k-10k
  • Textures: power-of-two (512, 1024, 2048)
  • UVs: single channel, within 0-1 range
  • Bones: under 50 for characters (under 30 for mobile)

9.2 Animation

  • Unity: Animator State Machine, Animation Rigging
  • Unreal: Animation Blueprint, Control Rig, Live Link
  • Godot: AnimationPlayer, AnimationTree

10. Audio: FMOD vs Wwise

AspectFMODWwise
PricingIndie free (under $150k)Indie free (under $200k)
IntegrationUnity, UnrealUnity, Unreal
UISimpleComplex, powerful
Use caseIndie, mid-sizeAAA

11. Platform Deployment

11.1 Mobile (iOS / Android)

  • iOS: Xcode build, App Store Connect, IDFA compliance
  • Android: Google Play Console, App Bundle (.aab) required

11.2 PC (Steam / Epic / GOG)

  • Steam: Steamworks SDK, Steam Pipe, Workshop
  • Epic: Epic Online Services, Epic Games Store

11.3 Console (PS5 / Xbox / Switch)

  • Developer registration required (license)
  • TRC/XR/Lotcheck certification
  • Builds need dev kits

12. Indie vs AAA Workflows

AspectIndie (1-10)AAA (100-500)
EngineGodot, Unity, UnrealUnreal, in-house
WorkflowGeneralist, fast iterationSpecialized roles
AssetsAsset Store, outsourceIn-house production
MarketingSocial media, influencersTV, trailers, events
ReleaseSteam, itch.ioAll platforms simultaneously

13. Quiz

Q1. The key advantage of ECS?

A1. Data-oriented design maximizes cache efficiency. Components are laid out contiguously in memory, making SIMD and multithreading effective. Hundreds of thousands of entities can run at 60fps.

Q2. Difference between Lumen and Nanite in Unreal Engine 5?

A2. Lumen is dynamic global illumination handling real-time indirect lighting and reflections. Nanite is virtualized geometry that auto-LODs billions of polygons. Lumen is light, Nanite is mesh.

Q3. Why do too many draw calls hurt performance?

A3. Each draw call has CPU-to-GPU command overhead. Too many makes the game CPU-bound and the GPU idle. Reduce them via batching, instancing, and texture atlases.

Q4. Advantages of server-authoritative model?

A4. The server holds all authority, so memory tampering on clients can't affect game state. Strong against cheating, but adds latency, requiring client-side prediction.

Q5. Static vs dynamic batching?

A5. Static batching merges non-moving objects into a single mesh at build/start time. More memory but zero runtime cost. Dynamic batching merges small dynamic objects every frame, with CPU overhead.

14. References

  1. Unity Documentation: https://docs.unity3d.com
  2. Unity DOTS: https://unity.com/dots
  3. Unity Learn: https://learn.unity.com
  4. Unreal Engine 5 Documentation: https://docs.unrealengine.com
  5. Unreal Engine - Lumen Technical Details: https://docs.unrealengine.com/5.3/en-US/lumen-global-illumination-and-reflections-in-unreal-engine
  6. Unreal Engine - Nanite Virtualized Geometry: https://docs.unrealengine.com/5.3/en-US/nanite-virtualized-geometry-in-unreal-engine
  7. Godot Documentation: https://docs.godotengine.org
  8. Godot 4 Tutorials: https://godotengine.org/learn
  9. Mirror Networking: https://mirror-networking.com
  10. Photon Engine: https://www.photonengine.com
  11. Game Programming Patterns: https://gameprogrammingpatterns.com
  12. GDC Vault: https://www.gdcvault.com
  13. Brackeys YouTube: https://www.youtube.com/@Brackeys
  14. Sebastian Lague YouTube: https://www.youtube.com/@SebastianLague

15. Closing Thoughts

Game development is where technology meets art. Whichever engine you pick, the goal is creating an enjoyable experience for players. Unity remains the indie standard with its versatility and huge community, Unreal Engine 5 has set a new bar for visual fidelity, and Godot 4 grows rapidly with open-source spirit and lightness.

Engines are tools. Game design, gameplay loops, and player psychology matter more. Starting with small projects and shipping them is the most valuable experience you can accumulate.

현재 단락 (1/499)

In 2026, game development has more **viable choices than ever**. Unity remains strong in indie mobil...

작성 글자: 0원문 글자: 16,289작성 단락: 0/499