The BepInEx console will not appear when launching like it does for other games on Thunderstore (you can turn it back on in your BepInEx.cfg file). If your PEAK crashes on startup, add -dx12 to your launch parameters.
TerrainScanner
TerrainScanner — Death Stranding style terrain scanner for PEAK. Provides persistent ground marks, scan outlines, and customizable visuals.
| Last updated | 2 weeks ago |
| Total downloads | 1594 |
| Total rating | 3 |
| Categories | Mods Tools World Quality Of Life Client Side All Clients Optimization |
| Dependency string | LIghtPeak-TerrainScanner-1.1.2 |
| Dependants | 1 other package depends on this package |
This mod requires the following mods to function
BepInEx-BepInExPack_PEAK
BepInEx pack for PEAK. Preconfigured and ready to use.
Preferred version: 5.4.75301Cysharp-UniTask
Provides an efficient allocation free async/await integration for Unity.
Preferred version: 2.5.0README
TerrainScanner

Terrain scanner is based on shader and is rendered by GPU. And asynchronous frame rendering, so it is fast and not stuck.
What it shows
- Slope classification (example thresholds used by the module):
- Flat: 0°–30°
- Gentle slope: 30°–50°
- Steep: 50°–90°
These thresholds are configurable via ScanConfig (see below).
Quick install / usage
-
Add the
TerrainScannerscripts (or compiled DLL) into your Unity project'sAssets/folder. The source is located insrc/TerrainScanner/in this repository. -
In your scene, attach
ActiveScanto a GameObject (for example, the Player or Camera). By default the scanner is triggered with theQkey (seeActiveScan.cs). -
Ensure
ScanConfigis properly populated at runtime with the required materials and particle prefabs:scanMaterial(shader for scan wave)markMaterial(instanced shader for marks)markParticle1/markParticle2/markParticle3(optional particle prefabs)
If you're using a mod loader (BepInEx) the plugin can populate these for you at startup.
Configuration (important fields)
Most runtime options live in ScanConfig (src/TerrainScanner/Config.cs). Important values:
horizontalCount,verticalCount— sampling grid size. Larger values increase coverage and precision but cost more CPU.gridStep— spacing between samples (meters).sampling_originHeightOffset— how far above the camera/player the ray origin starts. Increase this to scan higher terrain.sampling_maxDistanceShort/sampling_maxDistanceLong— raycast lengths for ground/ledge and long-range tests.steepSpawnProb,midSpawnProb,flatSpawnProb— per-category particle spawn probabilities.
Tune these values via the ScanConfigManager or by binding them in your plugin's initialization.
Troubleshooting
-
I see only some marks rendered even though scanning detected many hits:
- Make sure the CPU-side
Marksstruct layout matches the HLSLMarksStructuredBuffer. Field order and sizes must match. - Ensure
ComputeBufferis created with the correct stride (useMarshal.SizeOf(typeof(Marks))). - Check the instanced shader does not write depth in the fragment stage (writing
SV_DEPTHin the fragment can cause depth conflicts and hide instances). Move depth calculation to the vertex stage or remove manual depth writes.
- Make sure the CPU-side
-
Rays don't reach high cliffs:
- Increase
sampling_originHeightOffsetandsampling_maxDistanceShort.
- Increase
-
Performance concerns:
- The sampling runs in slices (uses
UniTask.Yield()to avoid blocking the main thread). If you increase resolution, consider reducinghorizontalCount/verticalCountor lowering sample frequency. - Consider limiting how many marks are uploaded to the GPU per frame (e.g. keep only the nearest N marks or prioritize by slope category).
- The sampling runs in slices (uses
Roadmap — Smarter Terrain Scanner (next major feature)
Planned: an "Intelligent Terrain Scanner" that improves scanning quality while staying performant. High-level goals and design notes:
-
Energy-based propagation model
- Each discovered sample carries an energy budget (kinetic + potential). Propagation to neighbors consumes energy for distance traveled and for climbing.
- Branching reduces energy (spawn cost). A cell is revisited only if arriving with strictly more remaining energy (best-energy rule).
-
Priority-driven exploration
- Replace the plain FIFO propagation queue with a priority queue sorted by remaining energy (prefer uphill, higher-energy fronts) so the algorithm finds viable ascent routes sooner.
-
Quantized, memory-efficient state
- Store per-cell discovered heights as quantized keys (e.g. 0.1m precision) in HashSets to avoid float equality problems and to reduce duplicates.
-
Safety & termination
- Global processed-count cap and local energy thresholds to prevent runaway propagation in caves or dense geometry.
-
Runtime tuning and visualization
- Expose energy parameters and propagation limits in
ScanConfigso users can tune behavior. - Add an optional debug overlay to visualize propagation fronts, queued items, and per-cell best-energy values.
- Expose energy parameters and propagation limits in
Why this helps:
- It prevents infinite propagation in complex geometry (caves/overhangs).
- It prioritizes realistic uphill routes, helping scans find reachable ground rather than flooding every neighboring cell.
- It keeps performance predictable and tunable.
Contributing
Contributions, issues, and suggestions are welcome. When opening a PR:
- Explain the problem or feature and include screenshots or logs if relevant.
- Keep changes focused; large refactors are easier to review if split into smaller PRs.
License
This project is licensed under the terms in LICENSE.