Search Issue Tracker
Not Reproducible
Votes
0
Found in
2021.3.38f1
2022.3.28f1
6000.0.1f1
Issue ID
UUM-71455
Regression
No
VFX Graph Memory leak when calling the ClearPropertyBinders and AddRemoveVFXProperty
Reproduction steps:
1. Open the attached “Repro“ project
2. Open the “Assets/Scenes/TestScene.unity“ Scene
3. Open the Profiler window (Window > Analysis > Profiler)
4. Select the “Memory“ Profiler Module
5. Enter the Play Mode
6. Wait and observe the Native and Untracked Memory
Expected result: Native and Untracked Memory stays the same
Actual result: Native and Untracked Memory is slowly increasing
Reproducible with: 2021.3.38f1, 2022.3.28f1, 6000.0.1f1
Reproducible on: M1 MacOS 14.4.1
Not reproducible on: No other environment 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
- Usage of Adaptive Probe Volumes throws a lot of IndexOutOfRangeException and Assertion Failed errors
- Prefab overrides don't recover missing managed references
- Trail Renderer visual doesn't match the positions of vertices when they have been offset
- [Mobile] The Material is not visible when using the Decal Renderer Feature
- Uncaught TypeError: Cannot read properties of undefined is thrown when the tab is inactive for several minutes
Resolution Note:
I wasn't able to reproduce locally using 2022.3.29f1.
However, I suspecting the memory growth only visible in windows task manager a result of many per frame allocation/destroy. You have to be aware AddPropertyBinder is actually allocating a new Monobehavior which isn't a small object.
We are recommending usage of pooled object in this scenario and prevent creation of new property binder using "enable" property.
For this specific use case, the VFXBind.cs file could be modified this way:
```
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.VFX;
using UnityEngine.VFX.Utility;
[ExecuteAlways]
public class VFXBind : MonoBehaviour
{
[SerializeField]
private VisualEffect vfx;
[SerializeField]
private VFXPropertyBinder vfxBinder;
[SerializeField]
private string propertyName;
public VisualEffect VFX => vfx;
private Transform target;
static VFXPositionBinder GetFirstOrCreatePositionBinder(VFXPropertyBinder propertyBinder)
{
//Do *not* use GetPropertyBinders helper, it only iterate through active binders, GetComponent will return not enabled component
var binder = propertyBinder.GetComponent<VFXPositionBinder>();
if (binder == null)
{
binder = propertyBinder.AddPropertyBinder<VFXPositionBinder>();
}
return binder;
}
public void StartBind(Transform newTarget)
{
#if false
vfxBinder.AddPropertyBinder(new VFXPositionBinder
{
Property = propertyName,
Target = target
});
target = newTarget;
vfx.enabled = false;
Update();
vfx.enabled = true;
#endif
vfx.enabled = false;
//Suggestion: use Lazy allocation of VFXPositionBinder, keep it & reuse it
//vfxBinder.ClearPropertyBinders();
if (newTarget)
{
var binder = GetFirstOrCreatePositionBinder(vfxBinder);
binder.Property = propertyName;
binder.Target = newTarget;
binder.enabled = true;
}
vfx.enabled = true;
}
public void StopBind()
{
//Suggestion: Don't clear it, only disable the binder
//vfxBinder.ClearPropertyBinders();
var binder = GetFirstOrCreatePositionBinder(vfxBinder);
binder.enabled = false;
}
private void OnValidate()
{
vfx = GetComponent<VisualEffect>();
vfxBinder = GetComponent<VFXPropertyBinder>();
}
private void Update()
{
if (target && vfx.HasVector3(propertyName))
{
//vfx.SetVector3(propertyName, target.position);
}
}
#if UNITY_EDITOR
[SerializeField]
private Transform testTarget;
[ContextMenu("Start Bind")]
private void StartBindTest()
{
StartBind(testTarget);
}
[ContextMenu("End Bind")]
private void EndBindTest()
{
StartBind(null);
}
#endif
}
```
=> Since this object is instantiated in a pool, we can lazily allocate and enable/disable the required property binder. It prevents creating a new property binder every time an object is activated from the pool.