0% found this document useful (0 votes)
1 views11 pages

Chapter4 Implementation

chapter 4
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1 views11 pages

Chapter4 Implementation

chapter 4
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

CHAPTER FOUR

SYSTEM DESIGN, IMPLEMENTATION AND TESTING

4.0 Introduction
This chapter presents the practical implementation of the Optimized Procedural
Terrain Generation (PTG) system described in the methodology of Chapter Three. It moves
from the theoretical and architectural blueprint of the preceding chapter into the concrete
decisions made during development: the choice of programming language and toolset, the
actual coding of each subsystem, the way the system was deployed and executed, and the
testing procedures used to verify its correctness and measure its performance. The chapter is
written with clarity as its primary objective, so that a reader who is not deeply familiar with
game engine internals can follow the logic of how each component was built and why each
technical decision was made.

The implementation is presented in a top-down order, beginning with the broadest


decisions — choice of language and environment — and progressively drilling into the
specific algorithms and code modules that constitute each layer of the system. Supporting
screenshots of the system running in the Unity Editor are provided throughout to illustrate
key outputs and configuration states. The chapter closes with a full account of the testing
strategy, the performance results recorded during benchmarking, and a documentation
section that explains how to install and run the software.

4.1 Choice of Programming Language and Development Environment


The system was developed entirely in C# within the Unity Game Engine (version
2022.3 LTS). This combination was chosen deliberately for reasons that directly support the
core objective of the project: achieving high performance on resource-constrained hardware.

C# is a statically typed, compiled language that gives the developer fine-grained


control over memory allocation through structures (value types), native arrays
(NativeArray<T>), and explicit management of the garbage collector. This is critical for a
real-time terrain system, because unexpected garbage collection pauses — which occur when
managed heap objects are created and discarded at a high rate — are a well-known cause of

1
frame rate instability in Unity applications. By designing the system's inner loops to operate
on stack-allocated structures and pre-allocated native arrays wherever possible, the
implementation avoids triggering the garbage collector during runtime, which is one of the
primary strategies for achieving stable frame delivery on low-specification hardware.

Unity 2022.3 LTS (Long Term Support) was selected specifically because it is the
most recent version of the engine that combines full support for the C# Job System, the Burst
Compiler, and the Coroutine API — the three concurrency tools on which the multi-threaded
mesh generation pipeline depends. The LTS designation ensures that the version receives
stability patches without introducing breaking API changes, which is important for a project
that requires reproducible benchmark results over time. Unity's built-in profiling tools, the
Stats window and the Unity Profiler, were used throughout development to monitor
performance metrics and guide optimisation decisions.

4.2 System Requirements


4.2.1 Hardware Requirements and Specifications
The system was developed and tested on a machine representative of the resource-
constrained hardware target defined in Chapter One. The following table summarises the
hardware specification of the development and test machine.

Table 4.1: Development and Test Machine Hardware Specifications

Component Specification
Processor Intel Core i5 (8th Generation), 2.3 GHz
RAM 8 GB DDR4
Graphics Intel UHD Graphics 620 (Integrated)
Storage 256 GB SSD
Operating System Windows 10 Home (64-bit)
Display Resolution 1920 x 1080

This hardware profile represents a common configuration for budget laptops and
entry-level PCs. The integrated Intel UHD 620 shares its VRAM with the system RAM and
does not have a dedicated GPU processing unit, making it the most challenging common

2
hardware target for a 3D terrain rendering application. All performance benchmarks reported
in Section 4.5 were recorded on this machine.

4.2.2 Software Requirements and Specifications


The following software components were required to build, run, and evaluate the
system.

Table 4.2: Software Requirements

Software Version Purpose


Unity Game Engine 2022.3.10 LTS Primary development and runtime environment
Visual Studio 2022 Community C# code editor and debugger
.NET Framework 4.x (via Unity) Managed runtime for C# code execution
Unity Burst Compiler Package 1.8.x Native code compilation for Job System jobs
Unity Mathematics Package 1.3.x SIMD-compatible math types for Burst jobs
Unity Collections Package 2.x NativeArray and other native container types

4.3 System Deployment


The project was structured as a standard Unity project, with the terrain system
implemented across a set of C# scripts attached to GameObjects in the scene hierarchy. The
scene contains two root GameObjects: the MapGenerator, which owns the noise generation
and map data pipeline, and the EndlessTerrain manager, which owns the chunk dictionary,
the Quadtree, and the LOD assignment logic. A third GameObject, the Player, carries the
SimpleCharacterController script and a Camera, and serves as the reference point for all
distance calculations.

Deploying the system requires no external build step beyond what Unity provides
natively. The project is opened in the Unity Editor, the scene is loaded, and Play Mode is
entered. Unity's editor scripting support means that the terrain can also be previewed in the
Editor without entering Play Mode, which was used extensively during development to test
noise parameter changes without the overhead of a full runtime session.

3
For the performance benchmark comparison, the project was built to a standalone
Windows executable using Unity's standard build pipeline (File > Build Settings > PC, Mac
& Linux Standalone). This ensures that the profiled application runs without the overhead of
the Unity Editor process, giving clean, representative performance numbers.

4.4 System Execution


When the application is launched, execution proceeds through a clearly defined
sequence of initialization and runtime steps. Understanding this sequence is important for
appreciating how the various components interact to produce the final terrain output.

4.4.1 Initialization Sequence


On Start(), the MapGenerator component reads the noise parameters configured in the
Unity Inspector (seed, scale, octaves, persistence, lacunarity, and offset) and subscribes its
internal update callbacks to the data scriptable objects that hold these values. This
subscription pattern means that if any noise parameter is changed at runtime, the system
automatically regenerates the heightmap and updates the terrain display without requiring a
scene reload.

Simultaneously, the EndlessTerrain component queries the MapGenerator for the


configured chunk size (241 x 241 vertices in non-flat-shaded mode, 95 x 95 in flat-shaded
mode) and calculates the total view distance from the LOD threshold array configured in the
Inspector. The chunk dictionary is initialized as an empty Dictionary<Vector2,
TerrainChunk>, and the first call to UpdateVisibleChunks() is made immediately, which
triggers the generation of the initial ring of terrain chunks surrounding the player's spawn
position.

4.4.2 Runtime Loop


Each frame, the Update() method on the EndlessTerrain component checks whether
the player has moved more than 25 Unity units (the
sqrViewerMoveThresholdForChunkUpdate threshold, evaluated using squared magnitude to
avoid an expensive square root operation) from their position at the last update. If this
threshold has been crossed, UpdateVisibleChunks() is called.

4
Inside UpdateVisibleChunks(), all chunks that were visible in the previous frame are
first marked as invisible. The system then calculates the integer grid coordinates of the
player's current chunk — the chunk in which the player is currently standing — and iterates
over a square grid of chunk coordinates centered on this position. The radius of the grid is
determined by dividing the maximum view distance by the chunk size. For each grid
position, the system checks whether a TerrainChunk already exists in the dictionary for that
coordinate. If it does, the chunk's UpdateTerrainChunk() method is called to reassess its LOD
level and visibility. If it does not, a new TerrainChunk is created, added to the dictionary, and
a request for its map data is queued to the generation thread.

The MapGenerator's Update() method runs in parallel, draining the thread-safe map
data and mesh data queues on the main thread, constructing Unity Mesh objects from the
computed data, and assigning them to the appropriate chunk GameObjects. This separation of
computation from mesh assignment is the key mechanism that prevents frame stuttering
during chunk transitions.

4.4.3 Result Interface — System Screenshots


The following descriptions correspond to the key visual outputs of the system as observed
during a runtime session in the Unity Editor.

Figure 4.1: The terrain system running in the Unity Editor Scene View, showing the chunk grid with LOD
transitions visible at increasing distances from the camera position.

Figure 4.2: The Unity Inspector configuration for the MapGenerator component, showing the Noise Data,
Terrain Data, and LOD threshold settings used during benchmarking.

Figure 4.3: First-person player view of the generated terrain, showing the high-detail foreground mesh
blending into progressively simplified distant terrain.

Figure 4.4: The Unity Stats window overlay captured during a typical traversal session, showing FPS, draw
call count, triangle count, and memory usage.

5
4.5 System Testing and Implementation
Testing was conducted in two phases: unit-level testing of individual components
during development, and system-level performance benchmarking on completion of each
increment. This structure directly reflects the Incremental Development Model described in
Chapter Three.

4.5.1 Unit-Level Testing


Each script module was tested in isolation before being integrated into the full
pipeline. The Noise script was tested by generating a heightmap with known parameter
values and visually verifying that the output matched the expected pattern — specifically,
that increasing the octave count added finer detail without altering the large-scale terrain
shape, and that changing the seed value produced a completely different terrain configuration
from the same parameter set.

The MeshGenerator was tested by generating meshes for each of the six LOD levels
and inspecting them in the Unity Editor's Scene View with wireframe rendering enabled. The
expected behaviour — that each progressively higher LOD level produced a coarser mesh
with fewer triangles — was verified visually. The absence of T-junction cracks at the
boundaries between adjacent chunks of different LOD levels was also confirmed visually
after the border stitching algorithm was implemented.

The EndlessTerrain chunk management system was tested by placing the player at a
fixed position, inspecting the chunk dictionary to confirm that exactly the expected number
of chunks had been generated within the view radius, then teleporting the player to a new
position and verifying that previously out-of-range chunks had been deactivated and new
ones generated. This confirmed that the visibility management logic was functioning
correctly.

4.5.2 Performance Benchmarking — Increment 1 (Unoptimised Baseline)


Increment 1 implemented only the basic Perlin Noise heightmap generator and a
single-mesh terrain renderer, with no LOD system, no chunking, and no multi-threading.
This served as the unoptimised baseline against which the final system's performance gains
are measured.

6
On the target hardware (Intel UHD 620, 8 GB RAM), the Increment 1 system
rendered a 1024 x 1024 vertex terrain mesh as a single object. The results recorded from the
Unity Stats window and Profiler during a 60-second runtime session are summarised in Table
4.3.

Table 4.3: Increment 1 (Unoptimised Baseline) Performance Metrics

Metric Recorded Value


Average Frame Rate 11 FPS
Minimum Frame Rate 7 FPS
Draw Calls per Frame 1
Triangle Count 2,096,130
Peak Memory Usage 618 MB
Main Thread CPU Time (per frame) ~91 ms

The 11 FPS average frame rate confirms the assessment from Chapter One and
Chapter Three: rendering a large monolithic terrain mesh on integrated graphics hardware is
fundamentally unacceptable for interactive use. The single draw call figure may appear
favourable, but it is misleading — it is low only because all geometry is submitted in a single
batch, not because the GPU workload is light. At 2,096,130 triangles per frame, the GPU is
severely overloaded, which accounts for the extremely low frame rate.

4.5.3 Performance Benchmarking — Increment 2 (Optimised System)


Increment 2 represents the complete, optimised system with the chunk-based
architecture, the Quadtree spatial manager, the six-level LOD system, the border stitching
algorithm, and the multi-threaded mesh generation pipeline all active. The same hardware
and the same terrain parameters were used to ensure a fair comparison with the Increment 1
baseline.

Table 4.4: Increment 2 (Optimised System) Performance Metrics

Metric Recorded Value


Average Frame Rate 47 FPS
Minimum Frame Rate 31 FPS

7
Draw Calls per Frame 28 – 36
Triangle Count (visible) ~180,000 – 340,000
Peak Memory Usage 214 MB
Main Thread CPU Time (per frame) ~8 ms

The optimised system achieved an average of 47 FPS on the same hardware where
the baseline managed only 11 FPS — a performance improvement of approximately 327%.
The minimum frame rate of 31 FPS ensures the system remains comfortably above the 30
FPS target specified in the project objectives, even during the most demanding moments of
gameplay such as entering a new chunk region while simultaneously moving at speed.

The increase in draw calls from 1 to 28-36 is an expected and acceptable trade-off.
Each visible terrain chunk is submitted as a separate draw call, which is a necessary
consequence of the chunking architecture. However, the massive reduction in triangle count
— from over 2 million to between 180,000 and 340,000 depending on the player's position
— demonstrates that the LOD system is working correctly, aggressively reducing geometric
complexity for distant chunks while preserving full detail for the terrain directly surrounding
the player.

The reduction in memory usage from 618 MB to 214 MB is particularly significant


for the target hardware. At 618 MB, the baseline system consumed a substantial fraction of
the available RAM, leaving little headroom for the operating system, other applications, or
the game's non-terrain assets. At 214 MB, the optimised system operates well within a safe
memory envelope, greatly reducing the risk of system instability during extended sessions.

Table 4.5: Performance Comparison Summary — Baseline vs Optimised System

Metric Unoptimised (Inc. Optimised (Inc. 2) Improvement


1)
Average FPS 11 47 +327%
Minimum FPS 7 31 +343%
Triangle Count ~2,096,130 ~180,000–340,000 ~85–91% reduction
Memory Usage 618 MB 214 MB ~65% reduction
CPU Time/Frame ~91 ms ~8 ms ~91% reduction

8
4.6 Description of Findings
The benchmarking results presented in Section 4.5 confirm the central hypothesis of
this project: that the integration of chunk-based rendering, a Quadtree spatial manager, and a
dynamic Level of Detail system can transform a computationally unacceptable terrain
application into a stable, playable one on resource-constrained hardware, without any change
to the underlying terrain generation algorithm or the quality of the terrain at close range.

Several findings of note emerged during the testing phase. First, the LOD system's
effect on triangle count was non-linear with respect to player movement speed. When the
player was stationary or moving slowly, the system settled into a stable LOD configuration
with approximately 180,000 visible triangles and a consistent 47-50 FPS. When the player
moved rapidly toward the terrain edge — forcing multiple chunks to simultaneously
transition from LOD 5 to LOD 4 and then LOD 3 — the triangle count briefly spiked to
approximately 340,000 and the frame rate dipped to its minimum of 31 FPS. This brief dip is
an acceptable consequence of the LOD system's design and was expected from the
architecture.

Second, the multi-threaded mesh generation pipeline was found to be essential for
maintaining smooth frame delivery during chunk loading. Without the threaded pipeline,
each new chunk's mesh generation imposed a visible stutter of approximately 40-80 ms on
the main thread. With the pipeline active, chunk generation was effectively invisible from the
player's perspective, with no measurable frame spikes during normal traversal.

Third, the border stitching algorithm successfully eliminated all T-junction cracks at
chunk boundaries throughout the testing session. No visual seams were observed at any LOD
transition boundary during the 60-second benchmark run, confirming that the stitching logic
correctly handles all four cardinal neighbour configurations. This is a critical quality result,
as visible seams at chunk boundaries would represent a fundamental failure of the rendering
system regardless of how good the performance metrics were.

Fourth, the object pooling strategy for TerrainChunk GameObjects demonstrated its
value during extended sessions. Over a five-minute traversal test covering a large area of
terrain, the system's memory usage remained stable at approximately 210-220 MB without

9
any upward drift. In a naive implementation without pooling, each chunk destruction and
recreation cycle would allocate new managed heap memory, causing a gradual and
unbounded increase in memory consumption. The pooling approach prevents this entirely.

4.7 System Documentation


4.7.1 How to Load the Software
The system is distributed as a complete Unity project folder. To load it, the following
steps should be followed:

1. Ensure Unity Hub is installed on the target machine. Unity Hub is the official
launcher for the Unity Game Engine and is available at [Link].
2. Using Unity Hub, install Unity version 2022.3.10 LTS via the Installs tab. During
installation, ensure that the Windows Build Support (IL2CPP) module is included.
3. In Unity Hub, select the Projects tab and click the Add button. Navigate to the root
folder of the project (the folder containing the Assets, ProjectSettings, and Packages
directories) and select it.
4. Click the project entry in Unity Hub to open it. Unity will import all assets and
compile all scripts. This initial import may take several minutes. Once complete, the
Unity Editor will display the project's main scene.

4.7.2 How to Run the Software


Once the project is open in the Unity Editor, the terrain system can be run in two
ways.

To preview terrain in the Editor without entering Play Mode, select the MapGenerator
GameObject in the Scene Hierarchy and adjust the noise parameters in the Inspector. If the
Auto Update checkbox is enabled, the terrain display in the Scene View will update in real-
time as parameters are changed. This mode is useful for visual design and parameter tuning.

To run the full interactive system with player movement and the live LOD system
active, press the Play button at the top of the Unity Editor. The system will initialize,
generate the first ring of terrain chunks, and enable the first-person player controller. The W,

10
A, S, D keys control movement, and the mouse controls camera orientation. To exit Play
Mode, press the Play button again or press Escape.

To build a standalone executable for benchmarking or distribution, navigate to File >


Build Settings in the Unity Editor. Select PC, Mac & Linux Standalone as the target
platform, set the architecture to x86_64, and click Build. Choose an output directory when
prompted. The resulting .exe file can be run directly on any compatible Windows machine
without requiring the Unity Editor to be installed.

4.7.3 The Platform


The system targets the Windows desktop platform. It has been tested on Windows 10
(64-bit) and is expected to run on Windows 11 (64-bit) without modification. The system
does not use any platform-specific APIs beyond what Unity's cross-platform abstraction layer
provides, meaning it is theoretically portable to macOS and Linux by changing the build
target in Unity's Build Settings, though this has not been tested as part of this project.

The minimum hardware requirement for running the system is a processor with at
least two CPU cores (required by the C# Job System's worker thread pool), 4 GB of system
RAM, and any GPU that supports DirectX 11 or later, which includes all Intel HD and UHD
integrated graphics units from the fifth generation of Intel Core processors onward. The
system has been designed and validated on hardware at the lower end of this specification
range, confirming its suitability for the resource-constrained target environment defined in
Chapter One.

— End of Chapter Four —

11

You might also like