lang: “en”
UE “Reflection” Concept
- Reflection: UE provides runtime type information and dynamic access capabilities through systems like UClass and UProperty.
UE’s reflection system is a code-generation mechanism implemented via the UHT tool and specific macros. You mark classes with UCLASS, variables with UPROPERTY, and functions with UFUNCTION — these macros are recognized by UHT.
Before compilation, UHT scans these markers and generates.generated.hand.cppfiles containing the reflection registration code for each class, such as theStaticClass()function and the construction logic for UClass objects.
The generated code registers class information into the engine’s globalGObjectClassesarray, enabling the engine at runtime to dynamically retrieve class structure, invoke functions, or access properties — which in turn powers blueprint interaction, garbage collection, and other core features.
This exists because UE needs to dynamically process code information at runtime. Blueprint visual scripting, for example, requires the engine to know via reflection which functions and variables a C++ class exposes so that blueprints can call them.
Say you write a character class in C++ with a Jump() function marked with UFUNCTION. Without reflection, the blueprint editor has no idea Jump() exists — the function name, parameters, and all that metadata get optimized away in the compiled machine code.
With reflection, UHT generates reflection metadata for Jump() at compile time, including its name, parameter types, return value, and which class it belongs to. At runtime, the engine uses this metadata to surface Jump() in the blueprint editor as a callable node you can drag in.
If you later add a height parameter to Jump() in C++, the reflection system automatically updates the metadata, and the corresponding blueprint node syncs up to show the new parameter — no manual binding code between blueprint and C++ required.
Undo/Redo — Command Pattern (Lightweight)
1 | Wrap each operation as ICommand { Do(); Undo(); } |
2. Snapshot Pattern (for complex scenarios):
1 | Serialize a snapshot of the entire object state before each operation |
Hybrid approach for real projects:
- Simple property edits → Command pattern (record oldValue/newValue)
- Complex operations (node graph changes, scene edits) → Snapshot or Diff pattern
- Merge mechanism: collapse consecutive operations of the same type (e.g., dragging a slider merges into a single history entry)
UE Smart Pointer Comparison
| Pointer Type | Managed Object | Ownership | Core Role | Use Case |
|---|---|---|---|---|
| TObjectPtr | UObject-derived | Shared | Safe UObject access, participates in garbage collection automatically | Replaces traditional UPROPERTY pointers; everyday UObject references |
| TWeakObjectPtr | UObject-derived | None | Weak reference to UObject, does not prevent GC | Avoids circular references; temporary access to UObjects that may be destroyed |
| TSoftObjectPtr | UObject-derived | None | Soft reference to UObject, supports async asset loading | References assets that may not be loaded, e.g., meshes or textures outside the current level |
| TSharedPtr | Non-UObject types | Shared | Manages lifetime via reference counting | Multiple owners sharing a non-UObject resource |
| TUniquePtr | Non-UObject types | Exclusive | Sole ownership, non-copyable | Managing non-UObject resources that don’t need sharing, e.g., custom data structures |
| TWeakPtr | Non-UObject types | None | Weak reference to a TSharedPtr, does not increment ref count | Avoids circular references when used alongside TSharedPtr |
Key Distinctions
Object boundary: The first three are strictly for UObject-derived classes and rely on UE’s garbage collection system; the last three are for non-UObject types and use manual memory management.
UObject pointer breakdown:
- TObjectPtr is a strong reference that keeps the UObject alive — the go-to choice for everyday development.
- TWeakObjectPtr is a weak reference; when a UObject is marked for collection, the pointer is automatically nulled. Common in scenarios like UI widgets holding references to character objects.
- TSoftObjectPtr stores a resource path rather than a direct memory address. The asset can be asynchronously loaded when it isn’t in memory, making it ideal for open-world games referencing distant assets.
Non-UObject pointer breakdown:
- TSharedPtr shares an object via reference counting, automatically freeing memory when the count reaches zero. Be mindful of circular references — they must be avoided manually.
- TUniquePtr is an exclusive pointer: no copying allowed, ownership transfers only through move semantics. Lowest performance overhead.
- TWeakPtr must be bound to a TSharedPtr. Once TSharedPtr releases the object, TWeakPtr automatically becomes invalid, resolving circular reference issues.
What is ECS Architecture? How Does It Differ from Traditional OOP?
| OOP | ECS | |
|---|---|---|
| Data layout | Objects scattered on the heap | Components laid out in contiguous memory |
| Cache friendliness | Poor (pointer chasing) | Good (data locality) |
| Logic organization | Methods bound to classes | Systems iterate over Components independently |
| Composability | Requires multiple inheritance / composition patterns | Natural composition (just attach Components) |
ECS essentially saves CPU time on data lookups.
Core concepts:
- Entity: an ID only, stores no data
- Component: pure data (Position, Velocity, Health…)
- System: pure logic (MovementSystem iterates all Position+Velocity components)
Core difference: OOP centers on objects — data and logic are encapsulated in classes, which tends to grow complex inheritance trees. ECS separates data from logic: entities are containers for components, systems process batches of the same component type, contiguous data storage improves cache efficiency, and the architecture naturally supports dynamic composition and parallel computation.
UE5 Mass system example: as an ECS implementation, Mass stores entity data in “fragments” and unifies logic in “processors.” The Matrix Awakens demo’s crowd simulation of thousands of characters packs position, velocity, and other data into contiguous storage, letting the movement processor batch-update all character coordinates — performance that far exceeds the traditional Actor approach.
Stack vs. Heap
- Heap: Dynamically allocated memory, variable size, lifetime controlled by the programmer, slower access. Suitable for large objects or data whose size is determined at runtime. (No fixed access order.)
- Stack: Automatically allocated memory, fixed size, lifetime controlled by the function call, fast access. Suitable for local variables and function parameters. (Fixed access order: last in, first out.)
What Is Function Calling and How Have You Used It in Projects?
How it works: The LLM doesn’t execute functions directly — it outputs a structured function-call intent (function name + arguments), which the host program parses and executes.
What Is RAG and How Did You Implement It?
RAG (Retrieval-Augmented Generation) = retrieve relevant documents first, then have the LLM answer based on those retrieved results.
What Is ControlNet and What Problem Does It Solve?
Reference answer:
ControlNet adds spatial control capabilities to a pretrained Diffusion Model.
The problem it solves: Raw Text-to-Image generation cannot precisely control the composition, pose, edges, or other spatial structure of generated images.
How it works:
- A parallel “Zero Convolution” branch is added to each block of Stable Diffusion’s U-Net
- Additional conditioning images are fed as input (edge detection / Canny, depth maps, pose / OpenPose, normal maps, etc.)
- During training, only the ControlNet branch is trained; the original model weights are frozen
Common ControlNet types:
- Canny Edge: controls outlines
- Depth: controls depth structure
- OpenPose: controls human pose
- Segment: controls region segmentation
- Scribble: controls sketch-based guidance
What Is LoRA and Why Is It So Popular?
LoRA (Low-Rank Adaptation) is a parameter-efficient fine-tuning method.
LoRA freezes the original model weights and trains only a small number of low-rank matrices to approximate the parameter updates needed for task adaptation. The trainable parameter count is just 0.1%–1% of full fine-tuning, drastically reducing VRAM usage and training cost. During inference, the weights can be merged with the base model, adding no extra latency.
In game development, LoRA lets you quickly fine-tune an image-to-image model to generate stylistically consistent character equipment and environment assets, or fine-tune a dialogue model so NPCs produce setting-appropriate natural dialogue — a great fit for small teams that need to move fast.
What Is the Difference Between MVC, MVP, and MVVM?
| Pattern | Component Responsibilities | Component Relationships | Pros / Cons |
|---|---|---|---|
| MVC | Model (data) / View (UI) / Controller (logic) | Controller directly operates both Model and View | Simple and intuitive, good for small projects; Controller can become bloated |
| MVP | Model (data) / View (UI) / Presenter (logic) | Presenter directly operates Model, updates View indirectly | Presenter is highly testable; View depends on Presenter, increasing coupling |
| MVVM | Model (data) / View (UI) / ViewModel (logic) | ViewModel directly operates Model, updates View via data binding | Two-way binding simplifies UI updates; steeper learning curve, potential performance overhead |
MVP’s Presenter and MVVM’s ViewModel are very similar in responsibility — both act as intermediaries handling business logic and data interaction. The key difference is that MVVM’s data-binding mechanism lets ViewModel update the View directly, eliminating the large amount of UI-update code you’d write in a Presenter. This makes the code more concise and testable. MVVM suits projects with complex, frequent UI interactions; MVP fits simpler UIs or scenarios where strict test isolation is needed.
What Are the Complete Stages of the GPU Rendering Pipeline?
Reference answer:
The GPU Rendering Pipeline is the full process by which a GPU executes graphics rendering:
Application Stage (CPU side):
1 | 1. Application Stage |
Geometry Stage (GPU vertex shaders):
1 | 2. Vertex Shader |
Rasterization Stage:
1 | 5. Primitive Assembly & Clipping |
Fragment / Pixel Stage:
1 | 8. Fragment Shader (Pixel Shader) |