Unreal Engine 5.8 tutorial

Part 4 — Bridging to 3D

Move into 3D in Unreal Engine 5.8: coordinates and units, the asset pipeline, PBR materials, and the lighting trinity — Lumen, Nanite, and MegaLights — plus collision and tracing.

The framework you learned (Actors, Components, GameMode, Controllers, Enhanced Input, the lifecycle) is identical in 3D. What changes is spatial reasoning and the asset pipeline. Don’t relearn the engine — just add the third dimension.

This part is mostly a set of short, self-contained labs. You’ll do them in the same Wisp project you created in Part 0 (Third Person template, Starter Content, Paper2D + Enhanced Input enabled). Make a scratch map to experiment in — File → New Level → Open World (or Basic if you want a tiny floor), and save it as Content/_Wisp/Maps/L_Lab_3D. Nothing here is throwaway: the material, the Mote mesh, and the Lumen-reactive light you build become the literal starting point for Part 5’s L_Hollow_3D.

4.1 Coordinate space and units

  • Unreal is left-handed, Z-up. X = forward, Y = right, Z = up. Rotations are Pitch (Y axis), Yaw (Z axis), Roll (X axis) stored as an FRotator.
  • 1 Unreal Unit = 1 cm. A human is ~180 units tall. Keep this in mind when importing models — wrong scale is the #1 beginner asset bug.
  • Transforms are Location + Rotation + Scale, and they compose down the component attachment tree (child transforms are relative to parents), exactly like a scene graph.

Viewport orientation, fast. Right-drag to look, W/A/S/D to fly, mouse wheel to change fly speed. With an actor selected: W = Move gizmo, E = Rotate, R = Scale, F = focus camera on it, End = snap it to the floor below. The colored gizmo arrows are red = X, green = Y, blue = Z — the same axis convention as the bullet above.

4.2 The 3D asset pipeline

AssetWhat it isComes from
Static MeshNon-deforming geometry (rocks, props, walls)DCC tools (Blender, Maya) as FBX/glTF, or Quixel Megascans, or Fab (Epic’s asset marketplace)
Skeletal MeshMesh bound to a skeleton (characters, creatures)FBX with a rig
MaterialA shader graph defining surface appearanceMade in the Material Editor
TextureImage data feeding materials (albedo, normal, roughness…)PNG/TGA/EXR
Animation SequenceA clip of skeletal animationFBX, mocap, or Control Rig

Fab (fab.com) is where you get free/paid meshes, materials, and full sample scenes — it replaced the old Marketplace/Quixel Bridge. Megascans (photoscanned assets) are free for UE users there. For this whole part you don’t need Fab at all: every shape you need ships with the engine’s Basic Shapes (a Sphere, Cube, Cylinder, Cone, Plane) and with Starter Content. Use the View Options eye icon at the bottom-right of the Content Browser and tick Show Engine Content if you don’t see Engine/BasicShapes.

4.3 Materials — PBR shader graphs

Unreal uses physically based rendering. A material is a node graph (like a Blueprint, but for the GPU) outputting into pins: Base Color, Metallic, Roughness, Normal, Emissive, etc.

  • Build a base Material, then create Material Instances to tweak parameters (color, tiling) cheaply without recompiling the shader — like instances of a class with different field values. Use instances liberally; they’re nearly free and the right workflow.
  • Substrate is the newer, more flexible material framework (layered materials, used by the new 5.8 Toon Shader). The classic material model still works everywhere; learn it first.

4.4 Lab A — Build M_WispGlow and two instances

The Wisp is “a fragile spark of light.” That look is an emissive material: a color multiplied by an intensity so it glows brighter than 1.0 and reads as a light source. You’ll build one parametric base material, then make a cyan and a magenta instance from it.

  1. In the Content Browser, go to Content/_Wisp/Characters/. Right-click → Material. Name it M_WispGlow. Double-click to open the Material Editor.
  2. Select the main result node (the one named M_WispGlow). In its Details panel, set Shading Model = Unlit. (Unlit means the surface ignores scene lighting and just shows its Emissive — perfect for a self-luminous orb. The Base Color, Metallic, Roughness, and Normal pins gray out, which is expected.)
  3. Add a color parameter: hold 3 and left-click an empty area of the graph to drop a Constant3Vector. Right-click it → Convert to Parameter, name it GlowColor. Double-click its swatch and set a bright value (start with white, the instances will override it).
  4. Add an intensity parameter: hold 1 and click to drop a Constant (scalar). Right-click → Convert to Parameter, name it GlowIntensity, default value 8.0. Give it a Slider Min of 0 and Slider Max of 50 in its Details so the instance editor shows a usable slider.
  5. Hold M and click to drop a Multiply node. Wire GlowColor → Multiply A, GlowIntensity → Multiply B.
  6. Wire the Multiply output into the main node’s Emissive Color pin. Click Apply, then Save.

The graph, in words:

Constant3Vector "GlowColor"  --A--> [ Multiply ] --> (Emissive Color)
Scalar "GlowIntensity" (8.0) --B--^

Now make the two instances:

  1. Back in the Content Browser, right-click M_WispGlowCreate Material Instance. Name it MI_WispGlow_Cyan.
  2. Open it. Tick the checkbox next to GlowColor to override it, then set RGB to roughly (0.0, 0.94, 1.0) — the site’s neon cyan. Tick GlowIntensity and leave it near 8.0. Save.
  3. Repeat: right-click M_WispGlowCreate Material Instance, name it MI_WispGlow_Magenta, set GlowColor to roughly (1.0, 0.18, 0.58). Save.
  4. Drag Engine/BasicShapes/Sphere into the level. Scale it to 0.3 on all axes (a ~30 cm orb). With the sphere selected, drag MI_WispGlow_Cyan onto it (or assign it under Details → Materials → Element 0).

Why a base material + instances? Editing the base M_WispGlow recompiles a shader (slow); editing a Material Instance just changes parameter values (instant, no recompile). It’s the GPU version of “configure, don’t fork.” Once Lumen is on (Lab C), an intensity around 815 makes the emissive orb actually bounce light onto nearby surfaces.

Test it: Press G (Game View, hides editor icons) and look at the sphere. It should glow a flat, bright cyan that does not darken in shadow — because it’s Unlit. Swap the material to MI_WispGlow_Magenta and confirm it turns magenta instantly with no shader-compile progress bar.

4.5 Lab B — Nanite on a static mesh

Nanite is virtualized geometry: the engine stores a mesh as a hierarchy of triangle clusters and streams only the clusters (and only the detail) visible on screen, so multi-million-triangle meshes cost roughly what a few thousand triangles used to. You enable it per static mesh.

  1. Drag Engine/BasicShapes/Cube into the level (or use a Starter Content prop such as SM_Rock for something with more triangles to visualize).
  2. In the Content Browser, right-click the static mesh assetNanite → Enable. (You can also open the Static Mesh editor and tick Nanite Settings → Enable Nanite Support, then Apply Changes.) The mesh now carries a Nanite representation.
  3. Visualize it: in the viewport, View Mode dropdown (top-left, defaults to “Lit”) → Nanite Visualization → Triangles. You’ll see the live triangle density change as you fly toward/away from the mesh. Switch to Nanite Visualization → Clusters to see the colored cluster patches Nanite streams. Set it back to Lit when done.

Scope notes for 5.8. Nanite primarily targets static meshes; support has broadened over releases (e.g. Nanite for some foliage/skeletal cases) but treat static props as the safe default. Every Nanite mesh keeps a fallback mesh (a regular low-poly version) used when Nanite is unsupported or disabled — you can tune the fallback’s triangle percent in Nanite Settings. Nanite materials can’t do world-position-offset-heavy or certain translucent tricks the same way; for the Wisp’s tiny glowing orb you don’t need Nanite at all — this lab is to see it working on a prop.

Test it: In Triangles view mode, fly the camera right up to the mesh and then far away. The triangle coloring should visibly densify up close and simplify at distance, with no popping LOD snap. If the view mode shows the mesh in a flat “not Nanite” color, the asset didn’t get enabled — re-check step 2.

4.6 Lab C — Lumen: move a light, watch GI bounce

Lumen is fully dynamic global illumination and reflections: light bounces off surfaces in real time with no baked lightmaps, and it updates instantly as lights or geometry move. First confirm it’s the active renderer, then prove it to yourself.

  1. Open Edit → Project Settings → Rendering. Under Global Illumination, confirm Dynamic Global Illumination Method = Lumen. Under Reflections, confirm Reflection Method = Lumen. (These are the defaults on the Third Person template, but verify.)
  2. In your scratch map, make a simple box room: drop a floor Plane and a couple of Cube walls from Engine/BasicShapes, scaled up. Assign a plain colored material (e.g. a Starter Content M_*) so bounced color is obvious — a strongly red wall bouncing onto a white floor reads clearly.
  3. Place a movable light: Quickly Add (the green “+” in the toolbar, or Window → Place Actors) → Lights → Point Light. Select it; in Details set Mobility = Movable, raise Intensity so the room is clearly lit.
  4. Press G for Game View and drag the Point Light around with the move gizmo. Watch indirect light — the colored bounce on the floor and ceiling — track the light in real time. That bounce is Lumen; no “Build Lighting” step is needed.
  5. Compare: go back to Project Settings and set Dynamic Global Illumination Method to None. Return to the viewport: the room goes flat and the bounced color disappears (only direct light remains). Set it back to Lumen.

Software vs Hardware Ray Tracing. Lumen runs in two modes. Software Ray Tracing (the default) traces against signed-distance fields and runs on a wide range of GPUs. Hardware Ray Tracing uses the GPU’s RT cores for sharper reflections and more accurate GI, at higher cost — toggle it under Project Settings → Rendering → Hardware Ray Tracing (and set Lumen → Use Hardware Ray Tracing when available). Separately, Lumen Lite is Beta in UE 5.8 — a cheaper medium-quality GI path aimed at 60 fps on weaker hardware/handhelds. Because it’s Beta, don’t ship the slice on it; use standard Lumen for WISP and treat Lumen Lite as an experiment.

Test it: With Lumen on and a red wall next to a white floor, the floor near the wall should pick up a faint red tint that moves as you drag the light. Toggle GI to None and back; the tint should vanish and return. That on/off difference is global illumination.

4.7 Lab D — MegaLights: many movable shadowed lights

MegaLights lets you place hundreds of dynamic, shadow-casting lights while holding frame rate, using stochastic sampling and denoising instead of rendering a full shadow map per light. It is production-ready in UE 5.8. For WISP this is the feature that lets every beacon you relight be its own real, shadow-casting light without tanking performance.

  1. Enable it project-wide: Project Settings → Rendering, under the Direct Lighting category, enable MegaLights. When you tick it, the editor prompts you to also enable Support Hardware Ray Tracing — accept that, since ray-traced shadows are MegaLights’ default. A restart may be requested. (For quick A/B testing you can flip the scalability toggle from the console with ~: r.MegaLights.Allow 0 to bypass it and r.MegaLights.Allow 1 to allow it again — do not use r.MegaLights.Enabled, which isn’t the correct variable.)
  2. Turn on a frame-rate readout: console → stat fps (and stat unit for Game/Draw/GPU milliseconds). For a closer look at the lighting cost, use stat gpu or ProfileGPU (Ctrl + Shift + ,). Note the baseline numbers.
  3. Place several lights: add ~8–12 Point and Spot lights around your box room. For each, set Mobility = Movable and tick Cast Shadows. Give them varied colors (cyan/magenta to match the Wisp palette). Each light also exposes an Allow MegaLights property (on by default) and a MegaLights Shadow Method set to Ray Tracing (Default) or Virtual Shadow Maps — leave the defaults for now.
  4. Confirm shadows: each light should cast soft, real-time shadows from the cubes onto the floor, and the lights should be cheap enough that stat fps stays close to your baseline.

MegaLights does not build on VSM. Ray-traced shadows are MegaLights’ default; Virtual Shadow Maps (VSM) are just an optional per-light shadow method you can pick under MegaLights Shadow Method. And Lumen is a separate system entirely — it handles indirect lighting (GI and reflections), not shadows. For best results in 5.8, pair MegaLights with Lumen Hardware Ray Tracing. If you ever see noisy shadows while MegaLights settles, that’s the denoiser converging — it’s expected during fast light motion.

Test it: With MegaLights off, add a dozen shadow-casting movable lights and watch stat unit — GPU ms climbs and fps drops. Enable MegaLights and look again: the same dozen lights should cost dramatically less GPU time while still casting shadows. That delta is the whole point of the feature.

4.8 Collision and physics

  • Every primitive component has a collision setting: a channel (WorldStatic, Pawn, etc.) and a response per channel (Ignore / Overlap / Block).
  • Overlap fires BeginOverlap/EndOverlap events (triggers, pickups). Block produces physical contact (Hit events, can’t pass through).
  • Collision presets (BlockAll, OverlapAllDynamic, Pawn, Custom…) bundle these settings.
  • Simulate Physics turns a component into a rigid body driven by Chaos, Unreal’s physics engine (rigid bodies, ragdolls, destruction, cloth).
  • Tracing (line/sphere/box traces, a.k.a. raycasts) is how you query the world: “what’s under the crosshair?”, “is the ground below me?”. LineTraceByChannel is your raycast.

4.9 Lab E — Overlap trigger + a downward LineTrace

Two things every gameplay system leans on: detecting when something enters a volume (the Mote pickup, the Beacon trigger) and querying geometry with a trace (snapping to ground, “what am I standing on”). You’ll wire both in Blueprint.

Part 1 — print on overlap. Build a tiny trigger Actor. It’s the seed of the Mote pickup, but you’ll formalize the canonical BP_Mote Blueprint in Part 5 — here you’re just proving the overlap and prepping the Mote’s mesh and material:

  1. Content Browser → Content/_Wisp/Blueprints/ → right-click → Blueprint Class → Actor. Name it BP_OverlapProbe. Open it.
  2. In the Components panel, Add → Sphere Collision. Select it; set Sphere Radius = 80. Under Collision, set Collision Presets = OverlapAllDynamic (Pawn responds Overlap, not Block). Optionally add a Static Mesh child set to Engine/BasicShapes/Sphere with MI_WispGlow_Cyan so you can see it.
  3. Select the Sphere Collision component. In its Details, scroll to Events and click the + next to On Component Begin Overlap. This drops an On Component Begin Overlap (SphereCollision) node in the Event Graph.
  4. From that node’s Other Actor pin, drag off and add Cast To Character (so only the player triggers it, not random geometry). From the cast’s success exec pin, add a Print String node with In String = Mote collected.
  5. Compile, Save. Drag BP_OverlapProbe into the level at about player chest height (Z ~90).

The graph, in words:

On Component Begin Overlap (SphereCollision)
   -> (Other Actor) Cast To Character
        -> [success] Print String  In String = "Mote collected"

Test it: Press Play and walk the third-person character into the sphere. Mote collected should print to the top-left of the screen each time you enter the volume. If nothing prints, the most common cause is the collision preset blocking instead of overlapping the Pawn — re-check step 2.

Part 2 — trace straight down and draw the hit. Add a ground-check to the character. Open BP_ThirdPersonCharacter (you’ll rename a copy of this to BP_Wisp in Part 5; experimenting here is fine).

  1. In the Event Graph, add an Event Tick (or wire to a key for a one-shot test — Tick is fine for a debug line).
  2. Get Actor Location → this is your trace Start.
  3. Compute End = Start with Z lowered by 500. Drag off Get Actor Location, add a Make Vector using its X and Y, and (Z − 500). Simplest: from Get Actor Location, add a + (vector) node and add (0, 0, -500).
  4. Add Line Trace By Channel. Wire Start and End. Set Trace Channel = Visibility. Tick Draw Debug Type = For One Frame (the node’s built-in debug draw — you’ll see a line and a hit point in the viewport).
  5. From the trace’s Return Value (bool: did it hit), branch. On true, drag the Out Hit struct, Break Hit Result, and feed its Location into a Draw Debug Sphere (Radius 20, a couple seconds duration) for an explicit marker. Optionally Print String the hit actor’s name from Break Hit Result → Hit Actor → Get Display Name.

The graph, in words:

Event Tick
   Start = Get Actor Location
   End   = Start + (0, 0, -500)
   -> Line Trace By Channel  (Start, End, Channel = Visibility,
                              Draw Debug Type = For One Frame)
        -> Branch (Return Value)
             [true] -> Break Hit Result -> Draw Debug Sphere (Location, Radius 20)
                    -> Print String (Hit Actor -> Get Display Name)

If you prefer C++, the same downward trace from an Actor method is short and compilable in UE 5.8:

void AWispCharacter::GroundCheck()
{
    const FVector Start = GetActorLocation();
    const FVector End   = Start - FVector(0.f, 0.f, 500.f);

    FHitResult Hit;
    FCollisionQueryParams Params(SCENE_QUERY_STAT(GroundCheck), /*bTraceComplex*/ false);
    Params.AddIgnoredActor(this);

    const bool bHit = GetWorld()->LineTraceSingleByChannel(
        Hit, Start, End, ECC_Visibility, Params);

    DrawDebugLine(GetWorld(), Start, End,
        bHit ? FColor::Green : FColor::Red, false, 0.f, 0, 1.f);

    if (bHit)
    {
        DrawDebugSphere(GetWorld(), Hit.ImpactPoint, 20.f, 12, FColor::Cyan, false, 0.f);
    }
}

Test it: Press Play. A line should shoot from the character down to the floor, with a sphere marker sitting on the surface beneath the feet. Jump (Space): mid-air the marker drops to wherever the trace next hits, and if you leap off a ledge the hit point jumps to the lower ground. That’s your raycast working — the same query you’ll use for ground snapping, foot placement, and “is the Wisp over a pit” checks later.

Exercise 4 — WISP: the Mote, in 3D

Prep the Mote’s first 3D form in L_Lab_3D — the assets, not the final Blueprint. (1) Build the Mote’s look: take the engine Sphere, save it into Content/_Wisp/Meshes/ as SM_Mote, scale it small (~0.25), and assign your MI_WispGlow_Cyan emissive material so it reads as a glowing pickup. Keep the BP_OverlapProbe from Lab E as your throwaway test of the overlap that prints Mote collected when the Character enters it — you’ll wrap this mesh, material, and overlap into the canonical BP_Mote Blueprint in Part 5, so do not save a BP_Mote here. (2) Place a movable Point Light beside SM_Mote and confirm Lumen bounces its color onto the floor when you drag it (Lab C). (3) For the win, enable MegaLights (Lab D) and scatter 3–5 Mote orbs, each with its own little shadow-casting light, and verify stat fps holds. Same framework as the 2D prototype — just the third axis, real PBR materials, and UE5’s lighting trinity doing the heavy lifting.