Removes all child elements from this element's hierarchy.
Unlike VisualElement.Clear, this method ignores the element's VisualElement.contentContainer.
Only the child elements are removed, not the element itself.
To remove all descendants, use the VisualElement.Clear overload with the VisualElementClearOptions.Recursive flag.
| Parameter | Description |
|---|---|
| options | Allows which actions are performed when clearing the children. |
Removes all child elements from this element's hierarchy, using the specified options. Use this method to reduce memory usage.
Unlike VisualElement.Clear, this method ignores the element's VisualElement.contentContainer.
Only the child elements are removed, not the element itself.
The default option only removes the immediate children and doesn't perform additional actions.
To remove all descendants from their parent, specify the VisualElementClearOptions.Recursive flag.
To invoke the VisualElement.ReleaseResources method on all descendants, specify the VisualElementClearOptions.RecursiveReleaseResources flag.
This flag implies that the hierarchy is cleared recursively, because an element must have no children when it is released.
You can use the combination of these flags to clear a large number of elements from the hierarchy and immediately release resources to reduce memory usage. For more information, refer to VisualElement.ReleaseResources.
This method also removes internal parent-child relationships between elements, which can improve garbage collection and troubleshoot memory leaks.
The following example shows how to use this method to reduce memory usage when a custom EditorWindow is closed.
using UnityEngine; using UnityEngine.UIElements; using UnityEditor;
public class VisualElementRecursiveReleaseExample : EditorWindow { [SerializeField] public VisualTreeAsset asset;
public void CreateGUI() { asset.CloneTree(rootVisualElement); }
// This makes the internal resources of elements used by this window immediately reusable for new windows. public void OnDestroy() { rootVisualElement.Clear(VisualElementClearOptions.RecursiveReleaseResources); } }
The following example shows how to release elements when implementing object pooling:
using UnityEngine; using UnityEngine.UIElements; using UnityEditor; using UnityEngine.Pool;
public class VisualElementPoolExampleWindow : EditorWindow { private ObjectPool<VisualElement> m_Pool;
[MenuItem("Window/Visual Element Pool")] public static void ShowWindow() { GetWindow<VisualElementPoolExampleWindow>("Visual Element Pool Example"); }
public void CreateGUI() { // Initialize the pool m_Pool = new ObjectPool<VisualElement>( createFunc: CreatePooledElement, actionOnGet: OnGetFromPool, actionOnRelease: null, actionOnDestroy: OnDestroyPooledElement, collectionCheck: true, defaultCapacity: 10, maxSize: 100 );
// Root element has PickingMode.Ignore by default. rootVisualElement.pickingMode = PickingMode.Position; rootVisualElement.RegisterCallback<ClickEvent>(OnClick);
// Add some instructions. var label = new Label("Click anywhere to spawn elements.\nClick on an element to return it to the pool."); label.pickingMode = PickingMode.Ignore; // Don't interfere with spawning. rootVisualElement.Add(label); }
private VisualElement CreatePooledElement() { var element = new VisualElement(); element.style.position = Position.Absolute; element.style.width = 50; element.style.height = 50; element.style.backgroundColor = new Color(Random.value, Random.value, Random.value); element.style.borderTopLeftRadius = 25; element.style.borderTopRightRadius = 25; element.style.borderBottomLeftRadius = 25; element.style.borderBottomRightRadius = 25;
// Stop click propagation so clicking on an element doesn't spawn a new one. element.RegisterCallback<ClickEvent>(OnElementClicked, TrickleDown.TrickleDown);
return element; }
private void OnGetFromPool(VisualElement element) { // Reset or configure the element when retrieved from the pool. element.style.backgroundColor = new Color(Random.value, Random.value, Random.value); }
private void OnDestroyPooledElement(VisualElement element) { // Cleanup when the element is destroyed (pool is disposed). element.UnregisterCallback<ClickEvent>(OnElementClicked, TrickleDown.TrickleDown);
// Make sure internal resources of the element are released immediately // because it is not added to the rootVisualElement of the window. element.ReleaseResources(); }
private void OnClick(ClickEvent evt) { // Spawn a new element at the click position. var element = m_Pool.Get(); element.style.left = evt.localPosition.x - 25; element.style.top = evt.localPosition.y - 25; rootVisualElement.Add(element); }
private void OnElementClicked(ClickEvent evt) { // Return element to pool when clicked. var element = evt.currentTarget as VisualElement; if (element != null) { element.RemoveFromHierarchy(); m_Pool.Release(element); }
// Stop propagation to prevent spawning a new element. evt.StopPropagation(); }
public void OnDestroy() { // Release any child element not currently in the pool. rootVisualElement.Clear(VisualElementClearOptions.RecursiveReleaseResources);
// Dispose of the pool when the window is closed. m_Pool?.Dispose(); } }