Hi I wasn’t sure who to ask about this. If there is a forum for advanced topics, writing libraries etc, I can try there.
My question is: can we detect when the Mesh class’s vertex arrays get updated, so that I can update metadata (normals, tangents and similar) for my shader? The idea being that people could use my shader effect globally, or add it as a component on a model with no additional code required.
This is very similar to the Mesh.RecalculateNormals()
concept, but for my own metadata. I believe that I’m trying to replicate the OnMeshChanged
delegate from Unreal Engine:
***** details *****
From what I can tell, it is NOT possible to do reactive programming in Unity at this time, at least not for most of the built-in Unity classes like GameObject and Mesh, which are sealed so can’t be inherited. I asked a similar question 2 years ago with no viable solutions so far:
But short of that, I may have found a workaround for my use case specifically, by using MeshUpdateFlags with the Mesh class and then intercepting the “mesh users” notification in a Renderer, MeshRenderer or ShapeModule:
By default, it appears that MeshUpdateFlags.DontNotifyMeshUsers
is false by default, so Mesh change notifications from methods like Mesh.SetVertexBufferData()
should already be happening:
But I see no indication of this in Unity, and can’t find a way to expose those events so I can watch them.
The reason I’m asking this has to do with writing future-proof code in libraries. I could attempt to hack around this issue by creating a MyMesh class that’s not inherited from Mesh but has a Mesh member variable inside it via composition. I could override all of the functions so that MyMesh is a wrapper and passes calls through to the Mesh like a proxy. There are problems with this approach though that prevents it from being future-proof:
- I could include a MeshInterface in MyMesh so that it’s a drop-in replacement wherever Mesh is used, but the Unity maintainers didn’t provide an interface for Mesh. And even if I could use an interface this way, I would have to update my interface and re-release my library every time there’s a Unity release that updates the Mesh class’s interface (this is an anti-pattern)
- I wouldn’t be able to run my shader as a global effect in an existing project, because all of the code would have to be refactored to use MyMesh instead of Mesh (this is an anti-pattern)
These approaches would have been future-proof:
- I could have used something like the INotifyPropertyChanged interface for this, if Unity had implemented it on all of their objects
- I could have Unity register MyMesh as the primary Mesh class globally through an inversion of control (IOC) or IOC container system, but this doesn’t seem to be a thing in Unity at this time
The Mesh changed notification behavior appears to be undocumented. So I’m still blocked, but if someone could answer one of the following, hopefully a solution will materialize:
- Can someone post an example of logging the Mesh changed events in a Renderer, MeshRenderer or ShapeModule so that I can extend it for my own purposes (or post a link to code that does)?
- Short of that, can someone post an example of logging all delegate events/callbacks/etc in Unity either globally or for an object/component so I can see what’s being sent by Mesh and listen for that?
Thanks!