Unit 5: Gameplay components

CSE434 — Game Development In 3D 10 min read

I. Orientation: What Makes a 3D Scene into Gameplay

A 3D scene becomes a game when three loops close: the simulation loop (physics and transforms updating every frame), the agency loop (player input producing state change), and the feedback loop (the game communicating consequence). Unit 5 assumes a working 3D project — typically Unity (2005–, C#) or Unreal Engine (1998–, Blueprints/C++) — and adds the components that turn navigable space into designed experience: opposition, machine decision-making, authored time, and narrative delivery.

Defining properties assumed throughout:

  • Frame-based update: All behaviour is sampled discretely. Update() runs once per rendered frame; FixedUpdate() runs on a fixed physics step (Unity default 0.02 s = 50 Hz). Frame-rate-independent motion requires multiplying by Time.deltaTime (seconds since last frame).
  • Component composition over inheritance: A GameObject is an empty transform; behaviour is attached. An enemy is Transform + Mesh Renderer + Collider + Rigidbody + NavMeshAgent + Health + AI controller.
  • Left-handed Y-up coordinates (Unity): +X right, +Y up, +Z forward. Rotations stored as quaternions internally to avoid gimbal lock; authored in Euler degrees.
  • Separation of decision and execution: The AI layer decides what (chase, flee, attack); the locomotion and animation layers decide how. Behaviour trees live entirely in the decision layer.
  • Authored vs. emergent time: Gameplay time is emergent (player-driven, variable); cutscene time is authored (fixed-duration, deterministic). Immersive storytelling is largely the craft of blurring that boundary.

II. Game Creation in 3D — From Empty Scene to Playable Loop

A. Purpose and Principle

The goal is a minimal vertical slice: a player who can move, a world that resists, and a win/lose condition. Everything later in the unit hangs off this skeleton.

B. Game creation in 3D

  • Scene and level geometry: Block out with primitives (Cube, Plane) before art. Greyboxing fixes metrics first — a human-scale player capsule is 1.8 m tall, a doorway 2.1 m, a comfortable jump 1.5 m horizontally.
  • The player controller: Character movement is either physics-driven (Rigidbody.AddForce) or kinematic (CharacterController.Move). Kinematic is preferred for responsiveness.
CSHARP
// Kinematic third-person movement, camera-relative
Vector3 input = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
Vector3 dir = Quaternion.Euler(0, cam.eulerAngles.y, 0) * input.normalized;
velocity.y += gravity * Time.deltaTime;          // gravity = -9.81 m/s^2
controller.Move((dir * speed + Vector3.up * velocity.y) * Time.deltaTime);
  • Symbols: speed in m/s (walk ≈ 2, run ≈ 5.5); velocity.y in m/s, reset to 0 on controller.isGrounded.
    • Collision and triggers: A Collider marked Is Trigger generates OnTriggerEnter(Collider other) without blocking motion — the standard hook for pickups, checkpoints and damage volumes. Non-trigger colliders resolve penetration and raise OnCollisionEnter.
    • Camera: Third-person cameras need collision-aware boom arms — raycast from pivot to desired position and pull in on hit, else the camera clips through walls.
    • Game state and the loop: A single persistent manager (singleton or Unreal GameMode) owns score, lives, and phase (Menu → Play → Win/Lose). Scene-independent data survives via DontDestroyOnLoad.
    • Lighting and bake: Static geometry uses baked lightmaps (offline global illumination stored in textures); dynamic objects use light probes. This is the primary performance lever in 3D — real-time GI on all surfaces is rarely affordable.

C. Applications and Limitations

  • Applies to: Any genre needing spatial traversal — the same skeleton serves shooters, platformers and walking simulators.
  • Limits: Kinematic controllers ignore momentum transfer, so ice, wind and moving platforms need explicit special-casing rather than falling out of the physics.

III. Adding Enemy to the Game — Opposition as a Component Stack

A. Definition

An enemy is an agent that perceives the player, navigates toward or around them, applies damage, and can be destroyed — a self-contained prefab so it can be instanced many times.

B. Adding enemy to the game

  • Prefab authoring: Build once, instance many. The prefab holds mesh, Animator, CapsuleCollider, Rigidbody (often Is Kinematic if the AI moves it), NavMeshAgent, and scripts.
  • Navigation mesh: Bake a walkable surface (Unity Navigation window; Unreal NavMeshBoundsVolume). The agent's radius, height, max slope (e.g. 45°) and step height (0.4 m) carve the mesh. Pathing then uses A* over navmesh polygons with string-pulling to smooth corners.
CSHARP
agent.speed = 3.5f;              // m/s
agent.stoppingDistance = 1.8f;   // stop just inside melee reach
agent.SetDestination(player.position);
  • Perception: Sight is a two-gate test — distance, then angle, then a line-of-sight raycast to reject targets behind cover.
CSHARP
bool CanSee(Transform t) {
    Vector3 to = t.position - eye.position;
    if (to.magnitude > viewRange) return false;                      // viewRange = 15 m
    if (Vector3.Angle(eye.forward, to) > viewAngle * 0.5f) return false;  // viewAngle = 110 deg
    return !Physics.Raycast(eye.position, to.normalized, to.magnitude, obstacleMask);
}
  • Health and damage: A Health component holds current/max and exposes TakeDamage(int amount); at current <= 0 it fires an OnDeath event so VFX, loot and score all subscribe rather than being hard-coded.
  • Attack cadence: Gate attacks on a cooldown timer, not on frames: if (Time.time >= nextAttack) { Attack(); nextAttack = Time.time + 1.2f; }. Damage is applied on an animation event mid-swing so the hit reads visually.
  • Spawning and difficulty: Instantiate(enemyPrefab, spawnPoint.position, Quaternion.identity) from a pool; scale challenge by concurrency and spacing, not only by HP inflation.
  • Telegraphing: Every attack needs a wind-up of roughly 0.3–0.5 s (anticipation pose, audio cue) so the encounter is readable and fair.

IV. AI Behavior Trees — Hierarchical Decision-Making

A. Formal Statement

A behaviour tree is a directed rooted tree, evaluated (ticked) from the root each cycle, in which every node returns one of three statuses — Success, Failure, or Running — and control flow is determined entirely by how composite nodes react to their children's statuses.

B. AI behavior trees

  • Node taxonomy:
    • Sequence (→): Ticks children left to right; returns Failure on the first failing child, Success only if all succeed. Logical AND — use for ordered plans.
    • Selector / Fallback (?): Returns Success on the first succeeding child, Failure only if all fail. Logical OR — use for prioritised alternatives.
    • Decorator: One child; transforms its status. Inverter swaps Success/Failure; Cooldown, Repeat, Succeeder and blackboard condition guards are the common ones.
    • Leaf: Condition (a test, no side effects) or Action (does work, may return Running across many ticks).
  • The blackboard: Shared key–value memory (TargetActor, LastKnownPosition, HomePoint). Nodes never talk to each other directly; they read and write the blackboard, which keeps subtrees reusable.
  • Running and reactivity: Returning Running lets a multi-frame action (walk to cover) persist while the tree is re-ticked. Because the root re-evaluates every tick, a higher-priority branch can abort a lower one — Unreal formalises this as observer aborts on decorators.
  • Worked structure — a guard enemy:
TEXT
Selector
├── Sequence            [Combat]
│   ├── Condition: CanSeePlayer?
│   ├── Decorator(Cooldown 1.2s) → Action: Attack
│   └── Action: ChasePlayer          (returns Running)
├── Sequence            [Investigate]
│   ├── Condition: HasLastKnownPos?
│   └── Action: MoveTo(LastKnownPos)
└── Action: PatrolWaypoints          [Fallback]

Tick trace: player unseen and no memory → first two Sequences fail at their Conditions → Selector falls through to PatrolWaypoints. Player enters the 110° cone → CanSeePlayer? succeeds, ChasePlayer returns Running, and patrol never ticks.

C. Comparison with the Finite State Machine

  1. FSM: States with explicit transitions. For n states the designer may author up to n(n−1) transitions, so complexity grows quadratically and adding a "flee when low HP" state touches every existing state.
  2. Behaviour tree: Priority is implicit in sibling order and depth. "Flee when low HP" is one new Sequence inserted as the leftmost child of the root — an O(1) authoring change. The trade-off is per-tick cost, since the tree re-walks from the root; mitigated by caching the running node's path.

V. Timeline-based Cutscenes — Authored Time

A. Purpose and Principle

A timeline is a non-linear editor embedded in the engine: a horizontal time axis with parallel tracks, so animation, camera, audio and script events are keyed against a shared clock and play back deterministically.

B. Timeline-based cutscenes

  • Structural vocabulary: A Timeline asset (Unreal: Level Sequence) contains tracks; tracks contain clips; clips expose keyframes. A Director/PlayableDirector binds abstract tracks to concrete scene objects at runtime.
  • Track types in practice:
    • Animation track: Plays clips on an Animator; overlapping two clips creates an automatic blend in the crossfade region.
    • Cinemachine / Camera Cut track: Switches between virtual cameras at exact frames — this is how shot–reverse-shot is cut without moving a physical camera.
    • Audio track: Locks dialogue to the clock; lip-sync and footfalls stay in sync because both are sampled from the same time value.
    • Signal / Event track: Emits markers received by a SignalReceiver, e.g. unlock door at 04:12 — the hook that lets a cutscene change game state.
    • Animation Override / Activation track: Toggles GameObject active state to hide the gameplay HUD or swap a prop for its breakable version.
  • Keyframes and interpolation: A key stores (time, value); the curve between keys is Bezier by default. Ease-in/ease-out on camera moves is what separates a cinematic push-in from a mechanical lerp.
  • Blending gameplay and cinematic: Save the player's transform, disable input and the controller, run the timeline, then restore. Better practice is to blend the gameplay camera into the cinematic camera over ~0.5 s rather than hard-cutting, preserving spatial continuity.
  • Scripted playback:
CSHARP
director.playableAsset = introSequence;
director.time = 0;
director.Play();
director.stopped += OnCutsceneEnd;   // re-enable input here
  • Determinism caveat: Timelines assume the scene is in an expected state. If a player has already destroyed a prop the cutscene animates, the shot breaks — hence timelines are usually played at gated moments (level start, boss defeat).

VI. Immersive Storytelling — Narrative Delivered Through Space

A. Definition

Immersive storytelling conveys narrative through the player's own actions and surroundings rather than through interruption, exploiting the fact that in 3D the player controls gaze, pace and attention.

B. Immersive storytelling

  • Environmental storytelling: The level is the exposition — a barricaded door with scratch marks on the inside, a skeleton beside an empty medkit box. The player assembles causality from evidence, which lands harder than being told.
  • Diegetic delivery: Information presented inside the fiction — audio logs, radio chatter, in-world signage, a wristwatch instead of a HUD clock. Non-diegetic overlays break presence; the more diegetic, the fewer the seams.
  • Environmental affordance and lead-the-eye: Light, contrast, colour accent and converging architecture direct movement without a quest marker. A single warm light at the end of a cool corridor is a pull; the player reads it as intent.
  • Agency and pacing: The player controls when a beat lands. Design for it: barks and triggered dialogue fire on volume entry, so revelation is player-authored rather than timed.
  • Interactive/ludonarrative alignment: Mechanics should argue the theme. If the story claims the protagonist is powerless, the controls should feel constrained — mismatch between mechanic and message produces ludonarrative dissonance.
  • Presence and its fragility: Presence is the felt sense of being there, sustained by consistency and continuity. It is broken by loading interruptions, unresponsive input (>100 ms latency is perceptible), clipping geometry, and — in VR especially — any loss of head-tracking fidelity.
  • Layering the techniques: A single moment typically stacks them — a timeline shot reveals the room (authored), the props explain the massacre (environmental), an audio log names the victim (diegetic), and the exit is lit warm (affordance). No single channel carries the load.

C. Analytical Dimension: Where Cutscenes and Immersion Conflict

  • The cost of the cut: Every cutscene removes agency; the player becomes a spectator. Presence dips at the transition and must be rebuilt afterwards.
  • The mitigation: Keep control where possible (in-engine, first-person, walkable "cutscenes"), keep them short, place them at natural pauses, and let the Signal track hand control back on the same frame the shot ends — so authored time and emergent time meet without a visible seam.