Hi,
The terrain paintbrush/raise/lower brush is not synced up, for lack of a better term, with where my cursor is. My cursor can be clicking away in the middle of the screen with nothing happening, and then I zoom out and notice the corner of the terrain is risen/lowered/textured etc. The effect is lessened with larger terrains but there is still a fair distance between the cursor + brush.
After struggling with this for a day or two, i was finally able to get it to work again by simply unchecking the terrain collider in the inspector and then turning it back on again.
Thank you for this! For me it did not work out just by unchecking, I am not sure how I did it, but it eventually worked, after I did it 10 times and reset the Terrain Collider block, and unchecked again. Really annoying problem to say the least…
Since this is still an issue after all these years I’ll share my automatic fix that doesn’t require saving or toggling the terrain collider. Create a file called TerrainUndoResync.cs in Assets\Editor\ and paste in the following code (must be placed in each individual project):
// TerrainUndoResync.cs
//
// Fixes the terrain brush desync after undo WITHOUT saving the scene or toggling the terrain collider.
//
// Why simply invoking SyncHeightmap() does nothing:
// Terrain sculpting happens on the GPU heightmap. Undo reverts that GPU
// heightmap (so the terrain LOOKS correct) but does NOT mark any region
// dirty. SyncHeightmap() only propagates regions that are flagged dirty, so
// with nothing flagged it was a no-op -- the CPU heightmap and the collider
// (which the brush raycasts against) kept the stale, pre-undo heights.
//
// The fix: mark the ENTIRE heightmap dirty, then sync. That forces the reverted
// GPU heights down onto the CPU data + collider, realigning the brush with what
// you see.
//
// Runs automatically on undo/redo.
using UnityEditor;
using UnityEngine;
[InitializeOnLoad]
public static class TerrainUndoResync
{
static TerrainUndoResync()
{
Undo.undoRedoPerformed -= OnUndoRedo;
Undo.undoRedoPerformed += OnUndoRedo;
}
// Defer one tick so the terrain has finished reverting before we resync.
static void OnUndoRedo() => EditorApplication.delayCall += Resync;
[MenuItem("Tools/Resync Terrain (Dirty + Sync) %&r")]
static void Resync()
{
var terrains = Object.FindObjectsByType<Terrain>(FindObjectsSortMode.None);
int n = 0;
foreach (var terrain in terrains)
{
var data = terrain != null ? terrain.terrainData : null;
if (data == null) continue;
int res = data.heightmapResolution;
// Mark the whole heightmap dirty so SyncHeightmap has something to
// propagate (this is the step undo skips), then push it through to
// the CPU heights, the LOD mesh, and the collider.
data.DirtyHeightmapRegion(
new RectInt(0, 0, res, res),
TerrainHeightmapSyncControl.HeightAndLod);
data.SyncHeightmap();
n++;
}
}
}
Tested and confirmed working. Fix generated with Claude Opus 4.8