-
Notifications
You must be signed in to change notification settings - Fork 226
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimize mesh serialization #10
Comments
How about this idea?
Edit: Changed the set to OnPreCull... |
@Joen-UnLogick That's a good thought, I'll look into it. Unfortunately, one problem I've created for myself is that the Deformable checks if the mesh filter's mesh matches the mesh being deformed. If it doesn't, the deformable reinitializes to deform the new mesh. This is meant to make it easy to change the deformed mesh, but will make things messy if I want to change to a non-unique mesh. I honestly need to rewrite the Deformable component eventually. It's a part of Deform that stands out to me as being poorly structured. |
I'd love to help, unfortunately I'm completely swamped. I've only downloaded Deform so far, hopefully within the next month I'll find time to actually try it out. :D Major props to you for having the foresight to populate "help wanted" issues like this. It allows me to pitch in on what looks like an awesome project without actually doing anything. |
First off, impressive package! I prefer the way you've structured it to MegaFiers'. Yours is more intuitive. I've been trying Deform on a mesh with 16000+ vertices and am finding having a Deformable increases my save times from less than 1 second to 30 seconds or more. I chased this down to the Deformable replacing the Skinned-Mesh-Renderer's mesh with a clone, which is then serialized by Unity. So I think this is the same problem you mentioned above. I used a variation of @Joen-UnLogick's solution, details below. OnPreCull/OnPostRender only work on Cameras, so I used OnWillRenderObject/OnRenderObject. From your comments it will break if I change the incoming mesh, but that's not an issue for me and for now it brings save times down to less than 1 second again. So a hack, but workable.
Edit: I forgot, I also had to mark the DynamicMesh as [NonSerialized] in MeshData:
|
@bleppie I'm glad you were able to find a solution that works for you. Thanks for sharing it! I'm gonna see if I can find a way to implement this serialization hack into the main branch, but I'll need to see if I can make it work without breaking anything else. In an ideal world there'd be an |
There is an on serialized call back function! :)
…Sent from my iPhone
On May 17, 2019, at 9:43 PM, Keenan Woodall ***@***.***> wrote:
@bleppie I'm glad you were able to find a solution that works for you. Thanks for sharing it! I'm gonna see if I can find a way to implement this serialization hack into the main branch, but I'll need to see if I can make it work without breaking anything else. In an ideal world there'd be an OnSerialize callback which would make things much easier!
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or mute the thread.
|
Look into the ISerializationCallBackReciever. Works wonders :)
…Sent from my iPhone
On May 17, 2019, at 9:43 PM, Keenan Woodall ***@***.***> wrote:
@bleppie I'm glad you were able to find a solution that works for you. Thanks for sharing it! I'm gonna see if I can find a way to implement this serialization hack into the main branch, but I'll need to see if I can make it work without breaking anything else. In an ideal world there'd be an OnSerialize callback which would make things much easier!
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or mute the thread.
|
@carter1990 will do, thanks! |
Just an update from my end. The hack/solution I proposed above requires one more bit of code in Deformable to reset the mesh after playing.
I tried ISerializationCallBackReceiver as suggested by @carter1990, but found that OnBeginSerialize was being called many, many times without a corresponding OnAfterSerialize, so I couldn't reset the mesh correctly. There's some more info here on the call, but it doesn't explain why OnAfterSerialize isn't bring called. |
I remember I had some sort of hiccup when using the I serialize call back. I’ll find my example. I used it to serialize dictionaries during runtime game play and it worked well. I’ll send it over today, hopefully it helps!
…Sent from my iPhone
On May 20, 2019, at 4:04 PM, Brian Knep ***@***.***> wrote:
Just an update from my end. The hack/solution I proposed above requires one more bit of code in Deformable to reset the mesh after playing.
private void OnPlayModeState(UnityEditor.PlayModeStateChange state) {
if (state == UnityEditor.PlayModeStateChange.ExitingPlayMode) {
data.Target.SetMesh(data.OriginalMesh);
}
}
I tried ISerializationCallBackReceiver as suggested by @carter1990, but found that OnBeginSerialize was being called many, many times without a corresponding OnAfterSerialize, so I couldn't reset the mesh correctly. There's some more info here on the call, but it doesn't explain why OnAfterSerialize isn't bring called.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
Before I dive deeper trying to find a solution, @keenanwoodall checking in if you or anyone else here has hopefully had any progress/ideas on this? The serialization has bloated my scene sizes over 50,000% (from 29kb to 14.6mb on one scene for example, I use it across multiple scenes and the bloating is compounding hard) so I'm keen to figure something out asap, even if it's a workaround. I tried @bleppie 's code and it helped somewhat but obviously not all the way. As a workaround I'm thinking about maybe disabling the deformable component during scene build (via OnProcessScene) and then enabling the deformable in play mode so that it grabs fresh references from the existing mesh filter, but I can't figure out what might be the most proper/safest way to nuke the existing serialized data during the scene bake stage. If you could point me in the right direction please I could at least get a workaround going in the meantime and would greatly appreciate it!! |
Hi, I unfortunately don't have anything new---I haven't worked on this since my comment---but please post what you find out. |
I'm not sure if this is a new API, but I looked for callbacks on scene saving and found this delegate I plugged into it from the Deformable to set the mesh filters mesh to the original mesh on save and it seems to work! I've only just tested this so make sure you backup your project before trying it out. There could be something wrong with my code that I'm not noticing, but it seems to be working great as of now! Here's the changes, but I'm also gonna push to the develop branch if you wanna pull from there. Deformable.OnEnable private void OnEnable()
{
InitializeData();
if (Application.isPlaying)
Manager = DeformableManager.GetDefaultManager(true);
#if UNITY_EDITOR
if (!Application.isPlaying && handle.IsCompleted)
{
PreSchedule();
Schedule().Complete();
ApplyData();
}
// Add this line
UnityEditor.SceneManagement.EditorSceneManager.sceneSaving += OnSceneSaving;
#endif
} Deformable.OnDisable protected virtual void OnDisable()
{
Complete();
data.Dispose(assignOriginalMeshOnDisable);
if (Manager != null)
Manager.RemoveDeformable(this);
// Add the next three lines
#if UNITY_EDITOR
UnityEditor.SceneManagement.EditorSceneManager.sceneSaving -= OnSceneSaving;
#endif
} Deformable.OnSceneSaving // Add this function somewhere on the Deformable
#if UNITY_EDITOR
private void OnSceneSaving(Scene scene, string path)
{
if (data != null && data.Target != null)
data.Target.SetMesh(data.OriginalMesh);
}
#endif |
After thinking about it for a bit I'm betting there's gonna be some issues with prefabs since they don't exist in the scene but will still probably get scene saving callbacks. That's where getting a dependable serialization callback would be helpful, but I bet I can detect if a deformable is a prefab in the Projects folder vs a deformable in the scene and act accordingly. I'll have to look into this later. |
Trying this now. |
I think there might be an edge case where already serialized data on a currently disabled deformable won't get swept with the OnSceneSaving function until you enable first then save the scene then disable and save again, but that aside it seems to work perfectly. Thank you again for helping with this so quickly! |
For what it's worth in case anyone else needs it, in MeshData.cs I also have this as @bleppie suggested: [NonSerialized] and I did this based on your last commit in the develop branch: removed -> [SerializeField, HideInInspector] from private ManagedMeshData originalManaged; |
oh yup I forgot to mention that part! thanks for catching that!
interesting, i'll look into it! |
It's simply because OnSceneSaving handler hasn't been attached yet since OnEnable hasn't been called. |
For what it's worth I have been using the latest changes discussed here in production and it's been flawless so far! |
Awesome!! |
Every deformable has its dynamic mesh serialized as a unique mesh. This bloats scene file size. It's unnecessary because the dynamic mesh can be generated from the original mesh.
MeshData.DynamicMesh
isn't serialized, but the target (Mesh Filter or Skinned Mesh Renderer) uses it and is serialized. Somehow the targets mesh reference needs to be overridden when serialized, to point to the original mesh. Then at runtime the dynamic mesh can be generated.The text was updated successfully, but these errors were encountered: