Skip to content

Issue: InternalSettings.worldCamera is readonly — causes incorrect panel resize sensitivity in ScreenSpaceCamera mode #25

Description

@skycaaf

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

  1. Set up a DynamicPanelsCanvas on a Canvas with RenderMode = ScreenSpaceCamera and a worldCamera assigned.
  2. Enter Play Mode.
  3. Try resizing a panel by dragging its edges. Occasionally the resize sensitivity is abnormally high (the panel resizes much faster than the mouse moves).
  4. If the bug occurs, switch the Canvas RenderMode to ScreenSpaceOverlay at runtime — the issue disappears immediately.
  5. Switch back to ScreenSpaceCamera — the issue reappears (stale worldCamera is never refreshed).
  6. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions