Skip to content
RED SAGSkills

Game Developer interview questions and answers

30 questions interviewers really ask, with what a strong answer covers. Read them, then test yourself in a timed mock interview.

Start a Game Developer mock interview

Easy questions easy

1. What is a game loop, and why is delta time important?

A strong answer covers:

  • Loop of input, update and render every frame
  • Frame time varies across machines and scenes
  • Delta time makes movement and timers frame-rate independent
  • Physics often uses a fixed timestep
  • Target frame budget, for example 16.6 ms for 60 FPS
Show model answer

The game loop is the heart of a game. Every frame it reads player input, updates the game world, such as movement, AI, physics and timers, and then renders the frame. It repeats until the game quits. Frames do not all take the same time; a fast PC might run at 144 FPS and a phone at 30 FPS, and a busy scene can be slower. Delta time is the time since the last frame. By multiplying speeds and timers by delta time, things move in units per second instead of per frame, so the game behaves the same on all machines. Physics usually runs on a fixed timestep instead, for stability. At 60 FPS the whole loop has about 16.6 ms, which is our frame budget.

2. In Unity, what is the difference between Awake, Start, Update, FixedUpdate and LateUpdate?

A strong answer covers:

  • Awake runs when the object is loaded, before Start
  • Start runs before the first Update if the component is enabled
  • Update runs once per frame for game logic and input
  • FixedUpdate runs at the fixed physics step
  • LateUpdate runs after all Updates, good for cameras
Show model answer

Awake is called when the object is created or the scene loads, even if the component is disabled, so I use it to set up references to its own components. Start is called once before the first frame Update, only if the component is enabled, so it is a good place for setup that depends on other objects already being awake. Update runs once per frame and is where I read input and run most game logic, using Time.deltaTime. FixedUpdate runs at the fixed physics rate, which may be zero, one or several times per frame, so I apply Rigidbody forces there. LateUpdate runs after all Update calls in the frame, which makes it ideal for a follow camera, so it moves after the player has moved.

3. How do you use vectors, dot product and cross product in game development?

A strong answer covers:

  • Vectors represent positions, directions and velocities
  • Normalising gives a direction of length 1
  • Dot product: angle between vectors, front/behind, view cones, lighting
  • Cross product: perpendicular vector, left/right test, surface normals
  • Distance and magnitude for range checks
Show model answer

Vectors are everywhere in games. A position is a point, a velocity is a direction with speed, and the difference between two positions gives the direction and distance from one object to another. Normalising a vector gives a pure direction of length 1. The dot product of two unit vectors gives the cosine of the angle between them, so I use it to check whether an enemy is in front of the player, to build a view cone, or for lighting, where light intensity depends on the angle to the surface normal. The cross product gives a vector perpendicular to two others. I use it to find surface normals, to build a coordinate frame for a camera, and to check whether a target is to the left or right of the player.

4. How does collision detection work in a game engine, and what is the difference between a collider and a trigger?

A strong answer covers:

  • Colliders are simple shapes like boxes, spheres and capsules
  • Broad phase finds possible pairs, narrow phase checks exact overlap
  • Collider creates a physical response; trigger only reports overlap
  • Layers and collision matrices filter what collides
  • Fast objects may need continuous collision detection
Show model answer

Game engines usually do not test collisions against the detailed mesh. Instead, objects have simple collider shapes such as boxes, spheres and capsules, or a simplified mesh. The physics engine first does a broad phase, using bounding boxes and spatial structures to find pairs that might touch, then a narrow phase that checks exact overlap and contact points. A normal collider makes objects physically collide, so they bounce or stop. A trigger only reports that something entered or left its area, with no physical response, which is perfect for pickups, checkpoints and damage zones. I use layers and the collision matrix so, for example, bullets do not hit other bullets. For very fast objects like bullets I enable continuous collision detection or use raycasts so they do not pass through walls.

5. Tell me about a game or game feature you built. What was the hardest problem and how did you solve it?

A strong answer covers:

  • Clear description of the game or feature and your role
  • A specific technical problem
  • How you investigated it, for example profiling or debugging
  • The solution and trade-offs
  • What you learned or would do differently
Show model answer

In a game jam, our team of three built a 2D platformer in Unity in 48 hours, and I wrote the player controller. The hardest problem was that the character sometimes got stuck on the edges between tiles. Using debug drawing, I saw the box collider was catching on the small seams between separate tile colliders. I switched the tilemap to a composite collider, so the ground became one smooth shape, and changed the player to a capsule collider with a small edge radius. I also added coyote time and jump buffering, so jumps felt fair. Movement became smooth, and players said the controls felt good. I learned to use visual debugging early and to test game feel with real players often.

6. Why do game engines like Unity and Unreal favour components over deep inheritance trees for game objects?

A strong answer covers:

  • Deep hierarchies become rigid when an object needs behaviour from two branches
  • Components are small reusable pieces of behaviour attached to an object
  • Designers can mix components to create new object types without code
  • Components are easier to test and reuse across projects
  • Inheritance is still useful for shallow base classes
Show model answer

With inheritance you quickly get trees like Enemy, FlyingEnemy, ShootingEnemy, and then you need a flying shooting enemy and the tree breaks. Components solve this through composition: an object is a container, and behaviour comes from small pieces like Health, Mover, Shooter or Flyer. You build a new enemy by attaching the right components, and designers can do it in the editor without new code. Each component has one job, so it is easier to reuse, test and debug. Unity GameObjects with MonoBehaviours and Unreal Actors with ActorComponents both work this way. I still use inheritance, but keep it shallow, for example a base Weapon class with a few subclasses, and put shared behaviour in components or interfaces.

7. How would you set up version control for a small game team with programmers and artists?

A strong answer covers:

  • Use Git with LFS or Perforce for large binary assets
  • Ignore generated folders such as Library, Temp, Binaries and Intermediate
  • Use file locking for binary files that cannot be merged, like scenes and art
  • Small frequent commits and branches or a clear trunk workflow
  • Unity: force text serialization and visible meta files
Show model answer

For a small team I would use Git with Git LFS, or Perforce if the art is very heavy. First, a proper ignore file so generated folders like Unity's Library and Temp or Unreal's Binaries and Intermediate never get committed. In Unity I make sure asset serialization is set to text and meta files are committed, because references depend on them. Large binaries like textures, models and audio go through LFS. Since scenes, prefabs and art files are hard to merge, I enable file locking so two people do not edit the same level at once. Programmers work on short-lived branches with pull requests, and we keep main always buildable, ideally with a CI build. Clear commit messages help when tracking down which change broke something.

8. What do you do as a programmer to make a game "feel" good to play?

A strong answer covers:

  • Responsive controls with low input latency
  • Feedback: screen shake, hit pause, particles, sound, animation
  • Forgiving mechanics like coyote time and input buffering
  • Smooth camera and easing instead of linear motion
  • Iterate with playtests and expose values for tuning
Show model answer

Game feel starts with responsiveness: input should affect the character on the very next frame, with quick acceleration and clear animations. Then I add feedback for every important action, such as a short hit pause, screen shake, particles, sound and a flash on the enemy, so hits feel heavy. I also add small forgiving rules players do not notice, like coyote time, where you can still jump a few frames after leaving a ledge, and input buffering, where a jump pressed just before landing still counts. Cameras use smoothing and easing curves instead of hard linear moves. Finally, I expose all these values to designers in data assets, because the right numbers only come from playtesting and tweaking many times.

9. What are coroutines in Unity, and when would you use them instead of Update or async/await?

A strong answer covers:

  • Coroutines are methods that pause with yield and resume on later frames
  • Good for sequences over time like fades, timed spawns or cutscenes
  • They run on the main thread, not in parallel
  • They stop when the object is deactivated or destroyed
  • async/await or Awaitable suits waiting on IO and composing results
Show model answer

A coroutine is a method that returns IEnumerator and can pause with yield, then continue on a later frame. For example, yield return new WaitForSeconds(2) waits two seconds without blocking the game. I use them for sequences over time, such as fading the screen, spawning waves with delays, or a simple cutscene, because the code reads top to bottom instead of being split across state flags in Update. They are not threads: everything still runs on the main thread, so heavy work inside them still causes hitches. They also stop if the GameObject is deactivated. For loading files, web requests or chaining results, I prefer async with Unity's Awaitable type, which handles cancellation and return values more cleanly.

10. How do you use prefabs, nested prefabs and prefab variants to keep a Unity project organised?

A strong answer covers:

  • Prefabs are reusable templates; edits propagate to instances
  • Nested prefabs let a prefab contain other prefabs
  • Variants inherit from a base prefab and override some values
  • Keep overrides small and apply changes to the right level
  • Avoid editing many scene copies by hand
Show model answer

I treat prefabs as the building blocks of the game. Anything used more than once, like an enemy, pickup or door, becomes a prefab, so a fix to the prefab updates every instance in every scene. Nested prefabs let me build bigger pieces from smaller ones, for example a room prefab that contains door and light prefabs, while each keeps its own source. Prefab variants are useful for related objects: a base Goblin prefab with variants for Archer and Shaman that only override a few values or add a component. I try to keep scene overrides small and push real changes up to the prefab or variant, otherwise it becomes hard to know where a value comes from. The overrides dropdown helps review this.

Medium questions medium

1. Your game runs at 40 FPS but must hit 60 FPS. How do you find and fix the problem?

A strong answer covers:

  • Profile on target hardware, in a development or release build
  • Find whether it is CPU-bound or GPU-bound
  • CPU: scripts, physics, GC, draw call submission
  • GPU: overdraw, shaders, resolution, shadows, post-processing
  • Fix the biggest cost first and measure again
Show model answer

At 60 FPS I have about 16.6 ms per frame, so I first profile on the target device using the Unity Profiler or Unreal Insights, not just the editor. The first question is whether the CPU or the GPU is the bottleneck, which I can see from frame timings or by lowering resolution and seeing if FPS improves. If it is CPU-bound, I look at expensive scripts, physics, garbage collection spikes and too many draw calls, and fix them with caching, pooling, batching or instancing. If it is GPU-bound, I check overdraw, heavy shaders, shadow cascades, post-processing and resolution, and use LODs, occlusion culling and simpler materials. I always fix the largest item first, measure again, and set budgets so the problem does not return.

2. How would you design a save game system?

A strong answer covers:

  • Decide what state to save; separate save data from runtime objects
  • Serialise to a format like JSON or binary with a version number
  • Use stable IDs to restore references
  • Write safely: temp file then rename, backups
  • Handle versioning/migration, platform storage and cloud saves
Show model answer

I start by deciding exactly what needs saving, such as player stats, inventory, quest progress and world changes, and I keep it in plain save data classes, separate from GameObjects or Actors. Each saveable object has a stable unique ID so I can restore it and its references on load. I serialise to JSON during development because it is easy to read, and maybe a compact binary format for release. Every save file includes a version number, so when the game updates I can migrate old saves instead of breaking them. To avoid corruption if the game crashes during saving, I write to a temporary file and then rename it, and keep a backup. Finally I use each platform save API, support cloud saves, and test loading old saves in CI.

3. How would you build the AI for an enemy guard that patrols, notices the player, chases and attacks?

A strong answer covers:

  • State machine or behaviour tree for decisions
  • Perception: sight cone with dot product and line-of-sight raycast, hearing
  • Navigation mesh for movement
  • Tuning values exposed to designers
  • Performance: update AI less often for far enemies
Show model answer

I would use a behaviour tree or a simple state machine with states like Patrol, Suspicious, Chase, Attack and Return. For perception, the guard checks if the player is within view distance, uses a dot product to see if the player is within the view cone, and then raycasts to confirm line of sight is not blocked by walls. Noise events, like footsteps, can make the guard suspicious and investigate. Movement uses a baked navigation mesh, with patrol points placed by designers. Values like view angle, reaction time and chase speed are exposed so designers can tune them without code. For performance, guards far from the player update perception less often, and I use the engine tools like Unreal Behavior Trees and EQS where they fit.

4. How would you choose between Unity, Unreal and Godot for a new project?

A strong answer covers:

  • Team skills: C# vs C++ and Blueprints
  • Target platforms, including mobile and web
  • Visual fidelity needs and built-in features
  • Licensing and pricing terms
  • Tooling, asset ecosystem and community
Show model answer

I would look at the project and the team rather than pick a favourite. Unity uses C#, has a fast iteration loop and a huge asset store, and it is strong for mobile, 2D, XR and mid-size 3D games. Unreal uses C++ and Blueprints and gives high-end graphics out of the box with features like Nanite, Lumen and strong multiplayer framework support, so it fits large 3D and realistic games, but it is heavier and has a steeper learning curve. Godot is open source, lightweight and good for 2D and smaller 3D projects, with no royalties. I would also compare licensing and revenue terms, target platforms and console support, the team existing experience, and build a small prototype of the riskiest feature before deciding.

5. How do you make game systems easy for designers to tune without changing code?

A strong answer covers:

  • Data-driven design: ScriptableObjects, Data Assets, data tables
  • Expose parameters in the editor with sensible ranges
  • Custom editor tools and debug views
  • Hot reload or quick iteration
  • Validation of designer data
Show model answer

I separate data from logic. Weapon stats, enemy types, level rewards and similar values live in data assets, such as ScriptableObjects in Unity, or Data Assets and Data Tables in Unreal, sometimes imported from a spreadsheet. The code reads these values, so a designer can create a new enemy variant just by making a new asset. I expose parameters in the inspector with clear names, tooltips and ranges, and build custom editor tools where needed, like a visual wave editor. I add in-game debug views and cheats so designers can test quickly, and support changing values while the game runs. Finally, I validate the data, for example warning when a drop table does not add up to 100 percent, so mistakes are caught before they reach players.

6. How would you build a third-person camera that follows the player smoothly and does not clip through walls?

A strong answer covers:

  • Orbit around a pivot near the character using yaw and pitch input
  • Smooth position and rotation with frame-rate independent damping
  • Sphere cast from pivot to desired position and pull the camera in on hits
  • Run in LateUpdate after the character moves
  • Handle edge cases: fading the character when too close, tuning values, Cinemachine
Show model answer

I put a pivot at the character's shoulder or head height and orbit the camera around it with yaw and pitch from the look input, clamping pitch so it cannot flip. The desired position is pivot minus forward times distance. To avoid walls, I sphere cast from the pivot toward that position and, if it hits, move the camera to just before the hit point, pulling in fast and easing back out slowly so it does not pop. All of this runs in LateUpdate so the character has already moved, and smoothing uses exponential damping or SmoothDamp so it behaves the same at any frame rate. If the camera gets very close I fade the character out. In Unity I would often start from Cinemachine, which provides orbit and collider features already.

7. Players report that their character sometimes falls through the floor. How do you investigate and fix it?

A strong answer covers:

  • Reproduce: find where and when, check frame rate and speed
  • Check for tunnelling from high speed or large timesteps; use continuous detection
  • Look for code moving the transform directly instead of the rigidbody or character controller
  • Check collider gaps, thin colliders and mesh collider issues
  • Add safety: ground checks, kill planes and respawn, logs or telemetry
Show model answer

First I try to reproduce it, using player reports or telemetry to find where and when it happens and whether it relates to low frame rate, high speed or a specific action like dashing or loading. Then I check the common causes. Tunnelling happens when the character moves further than the floor thickness in one step, so I check speed, enable continuous collision detection or use a capsule cast for movement. Teleporting the transform directly instead of moving through the rigidbody or CharacterController can skip collision completely. I also inspect the level geometry for gaps between floor colliders, very thin colliders or broken mesh colliders. Finally I add a safety net, such as a kill volume under the level that respawns the player, and log the position when it triggers to find remaining spots.

8. How would you design input handling that supports keyboard, gamepad and touch, plus key rebinding?

A strong answer covers:

  • Use an action-based system like Unity Input System or Unreal Enhanced Input
  • Gameplay reads actions, not raw keys
  • Separate action maps or contexts for gameplay, UI and vehicles
  • Rebinding UI saves overrides, for example as JSON
  • Show correct button prompts for the active device; handle dead zones
Show model answer

I would use an action-based input system, such as Unity's Input System or Unreal's Enhanced Input. Gameplay code only reads actions like Move, Jump and Interact, and each action has bindings for keyboard, gamepad and touch controls. I group actions into maps or mapping contexts, for example gameplay, UI and driving, and switch them when the game state changes so keys do not do two things. For rebinding, the settings menu starts an interactive rebind on an action, checks for conflicts, and saves the overrides, which Unity can export as JSON. The UI listens for the last used device and shows matching button prompts. I also tune stick dead zones and sensitivity and keep accessibility options like hold versus toggle.

9. How would you procedurally generate dungeon levels that are always playable?

A strong answer covers:

  • Choose an approach: rooms and corridors, BSP, cellular automata, or handmade room templates
  • Use a seeded random generator for reproducibility
  • Guarantee connectivity with a graph or spanning tree and validate with pathfinding
  • Place start, exit, keys and loot using rules and distance
  • Mix authored pieces for quality and test many seeds automatically
Show model answer

I usually combine authored room templates with a procedural layout, because pure randomness often looks messy. The generator uses a seeded random number generator so any level can be reproduced from its seed for bug reports or sharing. I place rooms with a method such as BSP splitting or random placement with overlap checks, then build a graph of rooms and connect them with a minimum spanning tree plus a few extra edges for loops. That guarantees every room is reachable. Then I place the start, the exit as the farthest room, and keys before their locked doors by walking the graph. Finally, a validation step runs pathfinding from start to exit and rejects bad seeds, and an automated test generates thousands of seeds to catch rare failures.

10. Describe how you would design a reusable object pool and what trade-offs it has.

A strong answer covers:

  • Pre-create objects and reuse them instead of Instantiate and Destroy
  • Reset state on get and release, with OnSpawn and OnDespawn hooks
  • Decide growth policy: fixed size, grow, or recycle oldest
  • Trade memory for fewer allocations and hitches
  • Bugs from stale state or references to returned objects; Unity ObjectPool API
Show model answer

An object pool keeps a set of inactive objects and hands them out instead of creating new ones, then takes them back instead of destroying them. That avoids allocation and garbage collection spikes, and Instantiate costs. I would build a generic pool, or use Unity's ObjectPool<T>, with create, get, release and destroy callbacks. On get, the object resets its state, like health, velocity and particle systems, and on release it is deactivated. I prewarm the pool during loading to the expected peak, and decide the growth policy: grow with a warning, or recycle the oldest, which suits bullet holes. The trade-offs are memory held all the time, and bugs from objects that keep stale state or from code that still holds a reference after releasing. Debug checks for double release help.

Hard questions hard

1. How would you design the networking for a fast-paced online multiplayer shooter?

A strong answer covers:

  • Authoritative dedicated server to prevent cheating
  • UDP-based transport with reliability only where needed
  • Client-side prediction and server reconciliation for the local player
  • Snapshot interpolation for remote players
  • Lag compensation for hit detection
  • Bandwidth: delta compression, relevancy and tick rate
Show model answer

I would use an authoritative dedicated server, because in a competitive shooter clients cannot be trusted. Transport is UDP with a reliability layer only for messages that need it, like game events. The server runs at a fixed tick rate, for example 30 to 60 Hz. Clients send inputs with sequence numbers. For the local player I use client-side prediction, so movement feels instant, and reconcile when the server state arrives by replaying unacknowledged inputs. Remote players are rendered slightly in the past with snapshot interpolation for smooth motion. For shots, the server uses lag compensation, rewinding hitboxes to what the shooter saw, within a limit. To save bandwidth I send delta-compressed snapshots and only relevant entities to each client. I would also plan for anti-cheat, matchmaking regions and testing with simulated latency and packet loss.

2. Design a flexible ability and buff system for an RPG with hundreds of skills.

A strong answer covers:

  • Data-driven abilities built from reusable effects
  • Attributes with modifiers: add, multiply, override, with stacking rules
  • Tags to handle conditions, immunities and cooldowns
  • Clear order of calculation and events
  • Networking and prediction if multiplayer
  • Debugging tools and performance
Show model answer

With hundreds of skills, hard-coding each one would be impossible to maintain, so I would make the system data-driven and composable. An ability is data: costs, cooldown, targeting and a list of effects. Effects are small reusable building blocks, like deal damage, apply a modifier, spawn a projectile or add a tag. Characters have attributes such as health and attack, and effects apply modifiers that add, multiply or override, with defined stacking rules and a fixed calculation order. Gameplay tags handle states like Stunned, immunities and cooldowns, so conditions are simple queries. The system raises events, like on hit, so passive skills can react. In Unreal I would build on the Gameplay Ability System, which also handles network prediction. I would add a debug view showing active effects on any character.

3. How do you manage memory in a large game that ships on consoles with fixed memory?

A strong answer covers:

  • Memory budgets per system and asset type
  • Streaming of levels, textures and audio
  • Avoid fragmentation with pools and custom allocators
  • Track allocations with tools and reports in CI
  • Reduce asset size: compression, mip levels, LODs
Show model answer

On consoles memory is fixed, so I set clear budgets early, for example how much for textures, meshes, audio, animation and gameplay, and assign owners. Most content is streamed: world partitions or level chunks load by distance, textures stream only the mip levels needed, and audio streams from disk. To avoid fragmentation over long sessions, I use pools for frequently created objects, frame or linear allocators for temporary data, and avoid many small heap allocations during gameplay. I track memory with tools like Unreal Memory Insights or platform tools, tag allocations by system, and run automated memory reports on test levels in CI so growth is caught early. Asset sizes are reduced with platform texture compression, LODs and removing unused content. Finally, we test long play sessions to catch leaks.

4. Explain how a modern real-time rendering pipeline draws a frame, and where the common performance costs are.

A strong answer covers:

  • CPU prepares visible objects: culling, sorting, draw calls
  • GPU vertex stage transforms vertices to screen space
  • Rasterisation and pixel/fragment shading
  • Forward vs deferred shading for lighting
  • Post-processing, shadows and transparency
  • Costs: draw calls, overdraw, shader complexity, bandwidth
Show model answer

On the CPU side, the engine first decides what is visible using frustum and occlusion culling, picks LODs, sorts objects by material and transparency, and submits draw calls to the GPU. On the GPU, the vertex shader transforms each vertex from object space to screen space. The rasteriser turns triangles into pixels, and the pixel or fragment shader computes their colour using textures and lighting. In a deferred renderer, the scene first writes surface data to a G-buffer and lighting is computed later per pixel, which handles many lights well; forward rendering lights each object directly and handles transparency and MSAA more easily. Shadows are extra passes, and post-processing like bloom and tone mapping runs at the end. Common costs are too many draw calls, overdraw from transparency, complex shaders, high resolution and memory bandwidth.

5. How would you reduce cheating in an online game?

A strong answer covers:

  • Server authority: never trust the client
  • Validate inputs and movement on the server
  • Send clients only the information they need
  • Client-side anti-cheat and integrity checks as an extra layer
  • Detection with analytics, reports and delayed bans
  • Secure economy and APIs
Show model answer

The most important rule is to never trust the client. The server owns important state like health, inventory, currency and match results, and clients only send inputs. The server validates those inputs, for example checking movement speed, fire rate and line of sight, so speed hacks and teleport hacks fail. To limit wallhacks, the server avoids sending positions of enemies the player cannot possibly see or hear. Client-side anti-cheat and code integrity checks add another layer against aimbots and memory editing, but they can be bypassed, so they are not the main defence. I would also use analytics and player reports to spot unusual statistics, and ban in waves so cheat makers learn less. Store and economy APIs need the same server-side checks to prevent duplication exploits.

6. The game averages 60 FPS but players complain about hitches every few seconds. How do you find and fix them?

A strong answer covers:

  • Look at frame time graphs and spikes, not averages
  • Profile on target hardware in a development build
  • Common causes: GC, loading on the main thread, shader compilation, physics spikes, logging
  • Use deep or timeline profiling around a spike: Unity Profiler, Unreal Insights, PIX
  • Fix by spreading work over frames, async loading, pooling, precompiling
  • Add a hitch budget and automated performance tests
Show model answer

Averages hide hitches, so I look at frame time over time and find spikes, ideally on the real target hardware in a development build, since the editor behaves differently. I capture a trace with the Unity Profiler or Unreal Insights, or PIX and Razor on consoles, and inspect exactly what ran in a spike frame. Typical causes are garbage collection, synchronous asset loading or Instantiate of big prefabs, shader or PSO compilation on first use, physics with many new contacts, expensive AI path requests all in one frame, or heavy logging. The fixes depend on the cause: pool objects and remove per-frame allocations, load asynchronously and preload ahead of time, precompile shaders, time-slice AI and pathfinding across frames. Afterwards I add an automated run that records frame times and fails if a hitch above budget appears.

7. How would you build a replay system that lets players rewatch a match, and what makes it hard?

A strong answer covers:

  • Two approaches: record inputs and re-simulate, or record state snapshots
  • Input replays need full determinism: fixed timestep, seeded RNG, ordered updates, float consistency
  • Snapshot replays are larger but robust; use delta compression and keyframes for seeking
  • Version the replay format; old replays may break after patches
  • Interpolate for smooth playback and support scrubbing
Show model answer

There are two main designs. The first records only player inputs per tick plus the starting state and seed, then re-runs the simulation. Files are tiny, but the simulation must be fully deterministic: fixed timestep, seeded random generators, a stable update order, no dependence on frame rate, and consistent floating-point maths, which is hard across platforms. Any patch that changes gameplay breaks old replays, so you need versioning or to keep old logic. The second records state snapshots of relevant objects, such as transforms, animations and events, a few times per second, with delta compression. It is larger but much more robust and easy to scrub. I usually add periodic full keyframes so seeking to any point is fast, and interpolate between snapshots for smooth playback. Many games, including Unreal's demo system, use the snapshot style.

8. How would you architect world streaming for a large open-world game?

A strong answer covers:

  • Divide the world into cells or chunks and load by distance and direction
  • Asynchronous loading with priorities and memory budgets
  • LOD and HLOD for distant content; low-detail proxies
  • Avoid main-thread spikes by time-slicing activation and initialisation
  • Persistent state for changed objects, and floating origin for precision
  • Engine tools: Unreal World Partition, Unity Addressables or scene streaming
Show model answer

I split the world into a grid of cells, each with its own assets and actors, and load cells within a radius of the player, with extra priority in the direction of travel and for fast vehicles. Loading is asynchronous with a priority queue and strict memory budgets per category, and unloading is just as important. Distant areas use hierarchical LOD proxies so the skyline is visible without loading full cells. The hard part is avoiding hitches, so activating loaded objects, running their setup code and adding physics is time-sliced over several frames. Objects the player changed, like opened chests, save their state in a persistent layer so cells can unload and reload correctly. For huge worlds I use origin rebasing to keep float precision. In Unreal I would build on World Partition and data layers; in Unity, Addressables and additive scenes.

9. How do you use multiple CPU cores in a game without race conditions and with real speed-ups?

A strong answer covers:

  • Use a job system with a worker pool rather than many raw threads
  • Split work into data-parallel jobs over arrays of plain data
  • Express dependencies between jobs instead of locks
  • Main thread owns engine objects; jobs read input and write separate outputs
  • Watch for false sharing, too-small jobs and sync points that stall
  • Profile with a timeline to see core usage
Show model answer

I avoid creating threads per feature and use a job system: a pool of worker threads, usually one per core, that runs small jobs. Good candidates are data-parallel tasks like updating thousands of particles, animation, culling, pathfinding or AI sensing, where the same code runs over arrays of plain data. Each job reads input data and writes to its own output, and ordering is expressed with job dependencies rather than locks, which keeps it free of races and deadlocks. Engine objects stay owned by the main thread, and results are applied there at a sync point. In Unity I would use the Job System with Burst and NativeArrays, whose safety checks catch races; Unreal has its task graph. I watch for jobs that are too small, false sharing on the same cache lines, and early Complete calls that stall the main thread, and confirm gains in a timeline profiler.

10. How would you design the backend for an online game with matchmaking and dedicated servers?

A strong answer covers:

  • Separate services: accounts, matchmaking, game server fleet, persistence
  • Matchmaker groups players by skill, latency and region, relaxing rules over time
  • Fleet manager allocates dedicated servers and autoscales by demand
  • Authoritative game servers report results; player data stored server-side
  • Security, anti-cheat, rate limits, and handling outages gracefully
  • Use platforms like Agones, GameLift or vendor services where it saves effort
Show model answer

I would separate the backend into services. An account and identity service handles login through platforms like Steam or console networks. The matchmaker takes tickets with skill rating, party size and ping to each region, groups compatible players, and relaxes rules the longer people wait so queues stay short. When a match forms, a fleet manager allocates a dedicated game server in the best region; I would use something like Agones on Kubernetes or Amazon GameLift so servers autoscale with demand and scale down at night. The game server is authoritative, validates gameplay, and reports results to a stats service that updates ratings and inventory, which only the backend can change. I would add rate limiting, anti-cheat checks, health monitoring, and degrade gracefully, for example letting players stay in menus if matchmaking is down.