InternalSettings.worldCamera is readonly — causes incorrect panel resize sensitivity in ScreenSpaceCamera mode
Description of the bug
DynamicPanelsCanvas.InternalSettings.worldCamera is a readonly field captured during construction. In the Unity Editor, InternalSettings is lazily instantiated (m_internal starts as null, created on first access of the Internal property). If this first access occurs before Canvas.worldCamera is fully assigned — which can happen depending on script execution order or after a domain reload — the worldCamera is permanently stale (null or wrong camera) for the entire Play Mode session.
This causes RectTransformUtility.ScreenPointToLocalPointInRectangle to produce incorrect local coordinates, resulting in abnormally high sensitivity when resizing panels (the panel resizes much faster than the mouse moves).
Key observations:
- The issue is intermittent — it depends on whether
InternalSettings was constructed before or after Canvas.worldCamera was ready.
- If the bug occurs, switching the Canvas to
ScreenSpaceOverlay at runtime immediately fixes it. Switching back to ScreenSpaceCamera reintroduces the bug (the readonly field still holds the stale value).
- When the bug does NOT occur (normal behavior), switching to
ScreenSpaceOverlay at runtime causes the opposite problem — resize becomes too slow — because worldCamera is non-null but Overlay mode expects null.
Reproduction steps
- Set up a
DynamicPanelsCanvas on a Canvas with RenderMode = ScreenSpaceCamera and a worldCamera assigned.
- Enter Play Mode.
- Try resizing a panel by dragging its edges. Occasionally the resize sensitivity is abnormally high (the panel resizes much faster than the mouse moves).
- If the bug occurs, switch the Canvas
RenderMode to ScreenSpaceOverlay at runtime — the issue disappears immediately.
- Switch back to
ScreenSpaceCamera — the issue reappears (stale worldCamera is never refreshed).
- If the bug did NOT occur on step 3, switching to
ScreenSpaceOverlay causes resize to become too slow (opposite problem — worldCamera is non-null but Overlay expects null).
Root cause in the code:
internal class InternalSettings
{
public readonly Camera worldCamera; // captured once, never updated
public InternalSettings( DynamicPanelsCanvas canvas )
{
if( canvas.UnityCanvas.renderMode == RenderMode.ScreenSpaceOverlay ||
( canvas.UnityCanvas.renderMode == RenderMode.ScreenSpaceCamera && !canvas.UnityCanvas.worldCamera ) )
worldCamera = null;
else
worldCamera = canvas.UnityCanvas.worldCamera ? canvas.UnityCanvas.worldCamera : Camera.main;
}
}
#if UNITY_EDITOR
private InternalSettings m_internal;
internal InternalSettings Internal
{
get
{
if( m_internal == null )
m_internal = new InternalSettings( this ); // lazy init, captures worldCamera at whatever state it's in
return m_internal;
}
}
#else
internal InternalSettings Internal { get; private set; } // set once in Awake(), also never updated
#endif
Suggested fix — make worldCamera a property that reads the current value at access time:
public Camera worldCamera
{
get
{
if( canvas.UnityCanvas.renderMode == RenderMode.ScreenSpaceOverlay ||
( canvas.UnityCanvas.renderMode == RenderMode.ScreenSpaceCamera && !canvas.UnityCanvas.worldCamera ) )
return null;
return canvas.UnityCanvas.worldCamera ? canvas.UnityCanvas.worldCamera : Camera.main;
}
}
Platform specs
- Unity version: 6000.3.15f1
- Platform: Windows Editor
- Device: N/A
- How did you download the plugin: Unity Asset Store
- plugin version: 1.3.4 · April 05, 2026
Additional info
No error messages in the console. The bug is silent — it only affects coordinate conversion correctness, producing no logs or exceptions.
Current workaround (using reflection to reset the stale InternalSettings after Canvas.worldCamera is confirmed ready):
var field = typeof(DynamicPanelsCanvas).GetField("m_internal", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
field.SetValue(canvas, null);
var prop = typeof(DynamicPanelsCanvas).GetProperty("Internal", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
prop.GetValue(canvas); // triggers lazy re-construction with correct worldCamera
Additional notes:
- This issue is specifically problematic in the Editor due to the lazy initialization pattern (
#if UNITY_EDITOR). In builds, Internal is set in Awake(), which is more deterministic but still susceptible if Canvas.worldCamera isn't assigned by that point.
InternalSettings.worldCameraisreadonly— causes incorrect panel resize sensitivity in ScreenSpaceCamera modeDescription of the bug
DynamicPanelsCanvas.InternalSettings.worldCamerais areadonlyfield captured during construction. In the Unity Editor,InternalSettingsis lazily instantiated (m_internalstarts as null, created on first access of theInternalproperty). If this first access occurs beforeCanvas.worldCamerais fully assigned — which can happen depending on script execution order or after a domain reload — theworldCamerais permanently stale (null or wrong camera) for the entire Play Mode session.This causes
RectTransformUtility.ScreenPointToLocalPointInRectangleto produce incorrect local coordinates, resulting in abnormally high sensitivity when resizing panels (the panel resizes much faster than the mouse moves).Key observations:
InternalSettingswas constructed before or afterCanvas.worldCamerawas ready.ScreenSpaceOverlayat runtime immediately fixes it. Switching back toScreenSpaceCamerareintroduces the bug (thereadonlyfield still holds the stale value).ScreenSpaceOverlayat runtime causes the opposite problem — resize becomes too slow — becauseworldCamerais non-null but Overlay mode expects null.Reproduction steps
DynamicPanelsCanvason a Canvas withRenderMode = ScreenSpaceCameraand aworldCameraassigned.RenderModetoScreenSpaceOverlayat runtime — the issue disappears immediately.ScreenSpaceCamera— the issue reappears (staleworldCamerais never refreshed).ScreenSpaceOverlaycauses resize to become too slow (opposite problem —worldCamerais non-null but Overlay expects null).Root cause in the code:
Suggested fix — make
worldCameraa property that reads the current value at access time:Platform specs
Additional info
No error messages in the console. The bug is silent — it only affects coordinate conversion correctness, producing no logs or exceptions.
Current workaround (using reflection to reset the stale
InternalSettingsafterCanvas.worldCamerais confirmed ready):Additional notes:
#if UNITY_EDITOR). In builds,Internalis set inAwake(), which is more deterministic but still susceptible ifCanvas.worldCameraisn't assigned by that point.