Search Issue Tracker
Won't Fix
Won't Fix in 6000.6.X
Votes
0
Found in
6000.0.65f1
6000.3.3f1
6000.4.0b3
6000.5.0a4
6000.6.0a1
Issue ID
UUM-131681
Regression
Yes
Terrain shadows changing shape when they are viewed at a different angle from the same position
How to reproduce:
1. Open the attached “IN-125410“ project
2. Open the “SampleScene“ Scene
3. In Scene view, position your Scene Camera so the “CentreView“ GameObject is in the center of the Scene view and both “LeftCube“ and “RightCube“ are at the edges of the Scene view and fully visible
4. In Scene view, rotate your Scene Camera so the “RightCube“ is at the center of the Scene view
5. Note how the Terrain shadow looks on the ground
6. In Scene view, rotate your Scene Camera so the “LeftCube“ is at the center of the Scene view
7. Observe the Terrain shadow
Actual result: The Terrain shadow does not have the same shape
Expected result: The Terrain shadow has the same shape
Reproducible with: 2023.2.0a11 (73bfca82bf31), 6000.0.65f1, 6000.3.3f1, 6000.4.0b3, 6000.5.0a4
Not reproducible with: 2023.1.0a1, 2023.2.0a10 (67f0519c7f6d)
Reproducible on: Windows 11
Not reproducible on: No other environments tested
Add comment
All about bugs
View bugs we have successfully reproduced, and vote for the bugs you want to see fixed most urgently.
Latest issues
- Texture2D hash changes inside of an AssetBundle when rebuilding a SpriteAtlas bundle with an empty AssetPostprocessor Script enabled
- Aniso Level still applies when Generate MipMap is disabled in Texture Import Settings
- Mipmap Limit Groups long names are not truncated when creating a new Mipmap Limit Group with a long name
- “ArgumentException: Invalid double parameter.” error is thrown when Infinity is typed into the Fixed Timestep field
- GameObject becomes gray when using HDRP and STP together on macOS
Resolution Note:
Thank you for reporting a bug to Unity.
The behavior you are seeing is caused by a performance optimization in the terrain heightmap LOD system. Terrain mesh tessellation is determined per-frame based on the camera frustum. Patches outside the frustum are simplified aggressively to reduce GPU load, and since shadow casting geometry spans a much wider area than what is visible to the camera, those out-of-frustum patches render at a coarser level of detail. When you change camera angle, different patches move in and out of the frustum, and the shadow-casting geometry changes with it. This is working as designed after the optimization was introduced, and we will not be reverting it because the performance impact on large terrain scenes would be too severe.
You can enforce a minimum tessellation level on terrain patches regardless of frustum visibility using the Terrain.heightmapMinimumLODSimplification property. Setting this to a non-zero value prevents the heightmap from simplifying below a certain detail level even for geometry outside the camera frustum, which stabilizes shadow-caster geometry.
Attach the following script component to any GameObject in your scene:
using System.Collections.Generic;
using UnityEngine;
public class TerrainMinimumLOD : MonoBehaviour
{
// Higher values enforce more detail. Valid range: [0, log2(heightmapResolution / 17)].
// 0 = no limit (default). Start with 1 or 2 and increase until shadows are stable.
[SerializeField, Min(0)]
int m_MinimumLODSimplification = 3;
readonly Dictionary<Terrain, int> m_OriginalValues = new();
void OnEnable()
{
foreach (var terrain in Terrain.activeTerrains)
{
m_OriginalValues[terrain] = terrain.heightmapMinimumLODSimplification;
terrain.heightmapMinimumLODSimplification = m_MinimumLODSimplification;
}
}
void OnDisable()
{
foreach (var (terrain, original) in m_OriginalValues)
{
if (terrain != null)
terrain.heightmapMinimumLODSimplification = original;
}
m_OriginalValues.Clear();
}
}
Alternatively, you can set the property directly on each Terrain instance in the Inspector under Basic Terrain > Minimum Detail Limit, or via script:
foreach (var terrain in Terrain.activeTerrains)
terrain.heightmapMinimumLODSimplification = 3;
Tuning guidance
The valid range is 0 to log2(heightmapResolution / 17). For a 513-resolution heightmap that is 0–4, for a 1025-resolution heightmap it is 0–5. A value of 1 or 2 is usually sufficient to eliminate shadow instability. Be aware that higher values increase the number of vertices the GPU must process for terrain that is not in view, so profile on your target hardware and use the lowest value that resolves the visible artifacts.
We recognize this is a frustrating regression and apologize for the inconvenience. The workaround above gives you per-terrain control, so you can apply it selectively to only the terrains whose shadows are visible and keep the performance cost minimal.
We have reviewed the issue carefully, and in this case, the development team is unable to prioritize fixing this bug. There are a number of reasons we make this decision, including the impact and severity of the issue across our user and customer base, and the possibility that future plans may solve the problem in a different way, or that a workaround for the bug may be available.
Today we will be closing this case. Thank you again for taking the time to report this issue, and please let us know if there is anything else that changes the impact or severity of this issue.
Resolution Note (6000.6.X):
Thank you for reporting a bug to Unity.
The behavior you are seeing is caused by a performance optimization in the terrain heightmap LOD system. Terrain mesh tessellation is determined per-frame based on the camera frustum. Patches outside the frustum are simplified aggressively to reduce GPU load, and since shadow casting geometry spans a much wider area than what is visible to the camera, those out-of-frustum patches render at a coarser level of detail. When you change camera angle, different patches move in and out of the frustum, and the shadow-casting geometry changes with it. This is working as designed after the optimization was introduced, and we will not be reverting it because the performance impact on large terrain scenes would be too severe.
You can enforce a minimum tessellation level on terrain patches regardless of frustum visibility using the Terrain.heightmapMinimumLODSimplification property. Setting this to a non-zero value prevents the heightmap from simplifying below a certain detail level even for geometry outside the camera frustum, which stabilizes shadow-caster geometry.
Attach the following script component to any GameObject in your scene:
using System.Collections.Generic;
using UnityEngine;
public class TerrainMinimumLOD : MonoBehaviour
{
// Higher values enforce more detail. Valid range: [0, log2(heightmapResolution / 17)].
// 0 = no limit (default). Start with 1 or 2 and increase until shadows are stable.
[SerializeField, Min(0)]
int m_MinimumLODSimplification = 3;
readonly Dictionary<Terrain, int> m_OriginalValues = new();
void OnEnable()
{
foreach (var terrain in Terrain.activeTerrains)
{
m_OriginalValues[terrain] = terrain.heightmapMinimumLODSimplification;
terrain.heightmapMinimumLODSimplification = m_MinimumLODSimplification;
}
}
void OnDisable()
{
foreach (var (terrain, original) in m_OriginalValues)
{
if (terrain != null)
terrain.heightmapMinimumLODSimplification = original;
}
m_OriginalValues.Clear();
}
}
Alternatively, you can set the property directly on each Terrain instance in the Inspector under Basic Terrain > Minimum Detail Limit, or via script:
foreach (var terrain in Terrain.activeTerrains)
terrain.heightmapMinimumLODSimplification = 3;
Tuning guidance
The valid range is 0 to log2(heightmapResolution / 17). For a 513-resolution heightmap that is 0–4, for a 1025-resolution heightmap it is 0–5. A value of 1 or 2 is usually sufficient to eliminate shadow instability. Be aware that higher values increase the number of vertices the GPU must process for terrain that is not in view, so profile on your target hardware and use the lowest value that resolves the visible artifacts.
We recognize this is a frustrating regression and apologize for the inconvenience. The workaround above gives you per-terrain control, so you can apply it selectively to only the terrains whose shadows are visible and keep the performance cost minimal.
We have reviewed the issue carefully, and in this case, the development team is unable to prioritize fixing this bug. There are a number of reasons we make this decision, including the impact and severity of the issue across our user and customer base, and the possibility that future plans may solve the problem in a different way, or that a workaround for the bug may be available.
Today we will be closing this case. Thank you again for taking the time to report this issue, and please let us know if there is anything else that changes the impact or severity of this issue.