-
-
Notifications
You must be signed in to change notification settings - Fork 221
Description
Hey, first of all thanks for the awesome project!
I think I spotted a bug, and I have a posible solution, but before performing a PR I want to validate in this issue if this is in fact something wanted to fix or not.
Summary
When using LifetimeScope.CreateChildFromPrefab to instantiate a prefab that contains a RectTransform (e.g., a UI View), the resulting instance appears misplaced — usually anchored to the bottom-left corner — when the Game view is set to Free Aspect.
The issue disappears when the Game view resolution matches the prefab’s original design resolution (e.g., 1920×1080).
Why I think it happens
The current implementation of CreateChildFromPrefab always instantiates the prefab using:
var child = Instantiate(prefab, transform, false);
This means the prefab is first parented under the current LifetimeScope, which typically is not a RectTransform.
Later, the caller often re-parents the instantiated object into a UI hierarchy (under a RectTransform), using SetParent(parent, false).
In Unity, changing parent from a Transform to a RectTransform causes the layout system to recalculate anchors and positions.
That leads to incorrect positioning whenever the aspect ratio doesn’t match the prefab’s original one.
Expected behavior
UI prefabs instantiated with CreateChildFromPrefab should maintain their RectTransform layout regardless of aspect ratio, even when reparented into a canvas hierarchy.
Proposed solution
Add a new overload of CreateChildFromPrefab that allows specifying the scene parent Transform at instantiation time, so the prefab can be created directly under its intended parent instead of temporarily under the LifetimeScope’s transform.
Example proposal:
public TScope CreateChildFromPrefab<TScope>(
TScope prefab,
Transform sceneParent,
IInstaller installer = null)
where TScope : LifetimeScope
{
var wasActive = prefab.gameObject.activeSelf;
using (new ObjectResolverUnityExtensions.PrefabDirtyScope(prefab.gameObject))
{
if (wasActive) prefab.gameObject.SetActive(false);
// Instantiate directly under the scene parent
var child = Instantiate(prefab, sceneParent, false);
if (installer != null)
child.localExtraInstallers.Add(installer);
// Maintain logical DI parent while allowing different scene parent
child.parentReference.Object = this;
if (wasActive) prefab.gameObject.SetActive(true);
child.gameObject.SetActive(true);
return child;
}
}
This ensures the logical DI parent remains the same (parentReference.Object = this), but the scene hierarchy is not forced under the non-UI LifetimeScope, avoiding any layout distortion.
My current Workaround
Immediately call SetParent(targetParent, false) on the instance’s RectTransform.
Reapply the layout from the original prefab:
private static void ApplyPrefabRectTransform(RectTransform instance, RectTransform prefab)
{
instance.anchorMin = prefab.anchorMin;
instance.anchorMax = prefab.anchorMax;
instance.pivot = prefab.pivot;
instance.sizeDelta = prefab.sizeDelta;
instance.anchoredPosition3D = prefab.anchoredPosition3D;
instance.localRotation = prefab.localRotation;
instance.localScale = prefab.localScale;
}
This fixes the issue but is inconvenient and error-prone.
Environment
Unity version: 6000.1.6f1
VContainer version: 1.17.0
Platform: Any (reproducible in Editor)