keenanwoodall / Deform

A fully-featured deformer system for Unity that lets you stack effects to animate models in real-time

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Change Mesh On The Fly

usernameHed opened this issue · comments

Hello. I have a Build() process in my project where I need at one point, to change the current Mesh of the GameObject (and theire is an ElasticDeformable on it. How do I do it correctly without breaking everything ?

`
Deformable deformable = gameObject.GetComponent();

            deformable.ChangeMesh(ModelData.Mesh);
            deformable.ResetDynamicData();

`

And it work, but then I have a lot of errors: "A Native Collection has not been disposed, resulting in a memory leak. Enable Full StackTraces to get more details."

It seems to work thought, but I don't like those errors :/
My Goal is to "Reset" the ElasticDeformable, then Change the Mesh of the MeshFilter, and then "Enable" Again the ElasticDeformable. One note thought: Doing so while enabling/Disabling the ElasticDeformable Component doesn't seams to work.

I'm not sure what version you're on, but on the latest if you want to change the mesh, you should only need to call deformable.ChangeMesh(someMesh)
However, for the Elastic Deformable, simply swapping the mesh is not enough because you also need to reset the additional position and velocity data used for the elastic calculations. If you don't reset the data it will look like this:
QZOdqFFXyY
To reset the dynamic data, all you need to call is DisposeData() followed by AllocateData()
Iny6kVe9AR
Here's the example script I wrote to test changing meshes at runtime. Let me know if it works for ya!

using Deform;
using UnityEngine;

public class MeshSwapExample : MonoBehaviour
{
    [SerializeField] private Deformable deformable;
    [SerializeField] private Mesh swapMesh;
    [SerializeField] private KeyCode swapKey = KeyCode.Space;

    private Mesh to, from;

    private void Start()
    {
        to = swapMesh;
        from = deformable.GetOriginalMesh();
    }

    private void Update()
    {
        if (deformable == null)
            return;

        if (Input.GetKeyDown(swapKey))
        {
            deformable.ChangeMesh(to);
            (to, from) = (from, to);
            
            if (deformable is ElasticDeformable elasticDeformable)
            {
                // You would normally want to call Complete() before disposing/changing the data to finish any running jobs that are using the data,
                // but the deformable.ChangeMesh() call above already calls Complete() so it's not necessary in this case:
                // elasticDeformable.Complete(); 
                elasticDeformable.DisposeData();
                elasticDeformable.AllocateData();
            }
        }
    }
}

Thanks, I will test that! I had found a dirty solution: remove the ElasticDeformable & create a new one :") I know it's sad... but I had to find something :')

I will try that. I suggest to add an Utility function for the future :)

Elastic
Well unfortunatly, I have the same behavior as before... It works fine, but when I leave the play mode, I have 140+ error "A Native Collection has not been disposed, resulting in a memory leak. Enable Full StackTraces to get more details."

Hmmm I an unable to reproduce this behavior on my end. Do you mind sharing a repro project, or the exact Unity/Deform version + some code I can run that should cause the error?