Search Unity

Bug VFXGraph.SetMesh crashes using mesh from script

Discussion in 'Visual Effect Graph' started by patrickjansendesign, Dec 7, 2022.

  1. patrickjansendesign

    patrickjansendesign

    Joined:
    Jan 21, 2020
    Posts:
    48
    I created a VFX with a changeable property "Mesh" making particles spawn from a common cylinder mesh shape. Works ok

    Then I added a c# script to test changing the Mesh input in the VFX by setting a customizable "TST" (mesh) variable and trigger the change with a button click. I tested by selecting a common sphere mesh and on button click the VFX updates fine. So far so good

    Then I added code so it would use a mesh from code instead of an existing asset. So I tried defining a mesh with a simple cube vertices.

    As soon as i test this with a button click, Unity crashes. Without exceptions.

    Anyone any idea why? Below is the code i used for the Mesh;


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.VFX;
    5.  
    6. public class changemesh : MonoBehaviour
    7. {
    8.     public Mesh TST;
    9.     public VisualEffect VFXGraph;
    10.  
    11.     void Start(){
    12.     }
    13.  
    14.     void Update(){
    15.     }
    16.  
    17.     public void buttonclick1(){
    18.         change1();
    19.     }
    20.     public void buttonclick2(){
    21.         init();
    22.         change2();
    23.     }
    24.  
    25.     Mesh manualmesh;
    26.     void init(){
    27.         manualmesh = new Mesh();
    28.         Vector3[] Vcube = {
    29.             new Vector3 (0, 0, 0),
    30.             new Vector3 (1, 0, 0),
    31.             new Vector3 (1, 1, 0),
    32.             new Vector3 (0, 1, 0),
    33.             new Vector3 (0, 1, 1),
    34.             new Vector3 (1, 1, 1),
    35.             new Vector3 (1, 0, 1),
    36.             new Vector3 (0, 0, 1),
    37.         };
    38.         manualmesh.vertices = Vcube;
    39.     }
    40.  
    41.     void change1(){
    42.         VFXGraph.SetMesh("Mesh", TST);
    43.     }
    44.     void change2(){
    45.         VFXGraph.SetMesh("Mesh", manualmesh);
    46.     }
    47. }
    48.  
     
  2. PaulDemeulenaere

    PaulDemeulenaere

    Unity Technologies

    Joined:
    Sep 29, 2016
    Posts:
    149
    Hello,

    Thanks for pointing this out, we successfully reproduced your issue and open a ticket (soon available).

    Actually, there is a simple workaround, the problem is relative to empty index buffer and indirect draw, you can simply workaround the crash doing:

    Code (CSharp):
    1. Mesh manualmesh;
    2. void init(){
    3.     manualmesh = new Mesh();
    4.     Vector3[] Vcube = {
    5.         new Vector3 (0, 0, 0),
    6.         new Vector3 (1, 0, 0),
    7.         new Vector3 (1, 1, 0),
    8.         new Vector3 (0, 1, 0),
    9.         new Vector3 (0, 1, 1),
    10.         new Vector3 (1, 1, 1),
    11.         new Vector3 (1, 0, 1),
    12.         new Vector3 (0, 0, 1),
    13.     };
    14.     manualmesh.vertices = Vcube;
    15.  
    16.     //This assignement workaround the crash
    17.     manualmesh.triangles = new int[] {
    18.         0, 2, 1,
    19.         0, 3, 2,
    20.         2, 3, 4,
    21.         2, 4, 5,
    22.         1, 2, 5,
    23.         1, 5, 6,
    24.         0, 7, 4,
    25.         0, 4, 3,
    26.         5, 4, 7,
    27.         5, 7, 6,
    28.         0, 6, 7,
    29.         0, 1, 6
    30.     };
    31. }
    I hope this information helps.
     
    Last edited: Dec 8, 2022
  3. patrickjansendesign

    patrickjansendesign

    Joined:
    Jan 21, 2020
    Posts:
    48
    Yeah triangles did the trick, tnx for the tip.

    I ran into a new problem to solve

    The mesh I use is also an existing gameobject and the VFX now make particles go into some predefined direction (horizontal) after spawning from that gameobject. But the parent of the gameobject has script which makes it rotate around its axis. So that gameobject's mesh obviously also visually spins around

    - If i put the VFX also inside that parent, the particles' movement also inherits the spin effect .... but instead they should just move as if there's no rotational movement going on.

    - If I put the VFX outside, then I need to recalculate the mesh vertice positions according to the parent transform rotation. I now manage to do that and push a fresh recalculated mesh to the VFX "Mesh" property but it seems that it takes half a second to calculate (37000+ vertices) and I actually need to do this on every frame so that will probably kill playback.

    - Or using a Transform property in the VFX and hooked up to the parent, I can read the rotation values for the parent, or alternatively using a small c# I can push the euler equivalents into a Vector3 property in the VFX. But I haven't been able to use either to recalculate the particle spawn positions accordingly. I don't know how. This probably should be the recommended solution though, right???
     
  4. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,306
    I am not sure how your setup works, but surely recalculating mesh every frame does sound like bad idea :D
    Even if you had to do that, then you would need some faster API, like jobs or compute shader.

    Also can you explain:
    Mesh is not game object, it's not even tied directly to it's transform component, so how it can affect the rotation?
    You should be able to transform particles inside the graph or in the worst case you can keep the vfx unparented and write simple c# script to copy transform values.
     
  5. patrickjansendesign

    patrickjansendesign

    Joined:
    Jan 21, 2020
    Posts:
    48
    right, when seeing the lag in playback on a single recalculate vertices i imagined this was a bad ide

    i know the mesh is not a game object.

    To elaborate, i have a rock-meteor prefab made in blender. That meteor prefab is what i mean with 'the gameobject'. It's placed within an empty parent gameobject and adjusted/positioned/scaled to my needs. That parent contains a c# script making itself spin around an axis

    The VFX uses the rock-prefab mesh to generate an effect where particles are spawned on the meteor-surface and sent into a very specific direction of my choice.

    The parent's rotation script messes up things because either

    A - [if VFX placed within this parent] the direction of my choice is influenced. (so I need to either recalculate this rotation into the calculated velocity of the particles, or)

    or

    B - [if VFX placed outside this parent] the location of where particles are spawn doesn't match the meteor-surface since the prefab-parent spins around.

    Does it make sense?
     
  6. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,306
    So you spawn particle on mesh surface and then you set velocity into very specific direction - is it the same for all particles? If yes, then why you can't set simulation space to world space, and work with world space velocity? Or if you want to rotate them with velocity (I doubt you want that) you can keep everything in local space what is even simpler.

    I mean does it help? It should keep rotation and position of parent, but simulate in world space and you can apply the same velocity for all of them:
    upload_2022-12-8_18-19-37.png

    Actually, @PaulDemeulenaere why there is no option to plug the mesh transform for spawned particles like circle or sphere has?
    // edit: nevermind, I see in docs what's new (gif) that skinned mesh has this feature in 2022.2, so I assume standard mesh too.
     
    Last edited: Dec 8, 2022
  7. patrickjansendesign

    patrickjansendesign

    Joined:
    Jan 21, 2020
    Posts:
    48
    no, particles don't move the same but to simplify it i would describe it as "all in the direction of a specific point"

    the meteor's parent is also moving fast through game space and the particles should more or less move together with the meteor (but move away according to how i need them to move locally) and not in world space because the camera follows the meteor and if the particles spawned and moved in world space they would instantly be left far behind. I tried this already.

    it seems simple but i'm finding it hard to solve
     
  8. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,306
    So how do you get direction? I am kind of confused by this description.
    You can do what I described, but just calculate/pass meteor velocity and spawn these particles with it + some small drag so they are left behind - what actually happens in reality.
     
  9. patrickjansendesign

    patrickjansendesign

    Joined:
    Jan 21, 2020
    Posts:
    48
    particles velocity/directions are done with a combination of a couple of nodes but I think that won't matter.
    Imagine it like this;

    - The "parent" of an instance of my meteor prefab (containing the mesh) moves at variable high velocity in the game space, while it also simultaneously spins around its axis.

    - Right behind/above it the camera follows using a c# script

    - If I spawn particles in world space, because of the high velocity each frame/spawn particles will already be many many many units behind the camera. But the particles need to spawn on the meteor surface and then slowly move away from the meteor instead. So they move short distances, locally (and huge distances in world space)

    Does that make sense?
    Maybe i'm missing something about your suggestion?
     
  10. patrickjansendesign

    patrickjansendesign

    Joined:
    Jan 21, 2020
    Posts:
    48
    With a property binder i push the parent rotation into a vector3 in the VFX. I saw someone suggesting putting the [current position] node into a [transform position] node and use the vector3 for the angles, and i think it seems to be working. Gonna test it out a bit more.
     
  11. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,306
    I think this is what I suggested. Obviously there is no one and only solution, but for me mine sounds reasonable, so I will break it a little:
    1. Create your meteor object with vfx graph
    2. Set particle system to be simulated in world space and spawn particles on the surface of the rock
    3. You need to use the transformation from the image I posted above - the result should be meteor correctly spawning particles on the surface, but they are going to stay in spawn position far behind the meteor
    4. Apply velocity to particles equal to meteor velocity - you probably know velocity of meteor and if not you can just substract position in previous frame and current frame and divide by time detla. At this point your meteor should spawn more and more particles around, but they are going to follow the meteor, until it turns obviously.
    5. In Update context add some minimal drag or turbulence or whatever else you want to make particles slow down a bit relative to meteor. You can also add some random (or meteor surface normal aligned) velocity to particles when initialized.
     
  12. patrickjansendesign

    patrickjansendesign

    Joined:
    Jan 21, 2020
    Posts:
    48
    Right, recalculating the meteor movement in world space into the VFX set up in world space should do the trick too. I get it. Still need to check if the [transform position] i mentioned above indeed works correctly but when I set up the nodes the first changes made it seem as if it worked fine. Well, i have 2 solutions to choose from now hehe. Tnx for the feedback, much appreciated.