Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Using Methods from ProBuilder Editor in my scripts

Discussion in 'World Building' started by LoneSurvivor82, Oct 16, 2020.

  1. LoneSurvivor82

    LoneSurvivor82

    Joined:
    Aug 17, 2019
    Posts:
    41
    Hi everybody,

    I am using some methods from the UnityEditor.ProBuilder-Assembly in my code, namely Optimize and RebuildColliders because I am doing some mesh-manipulation on runtime:

    Code (CSharp):
    1.     using UnityEditor.ProBuilder;
    2.     ...
    3.    
    4.     public void Awake()
    5.         {
    6.             pb = GetComponent<ProBuilderMesh>();
    7.         }
    8.  
    and later on:

    Code (CSharp):
    1. protected void FinishMesh()
    2.     {
    3.         pb.ToMesh();
    4.         pb.Refresh();
    5.         pb.Optimize();
    6.         pb.RebuildColliders();
    7.         Collider collider = GetComponent<Collider>();
    8.         collider.enabled = false;
    9.         collider.enabled = true;
    10.     }
    This works when I am in editor-mode, so the game compiles and I can start it.

    But if I try to build the game, it fails with the following error:

    error CS0234: The type or namespace name 'ProBuilder' does not exist in the namespace 'UnityEditor' (are you missing an assembly reference?)

    Is there a way to use the code inside these editor-classes without copying and duplicating it into a new class inside my own namespace?

    Thank you very much
    Ricky
     
  2. LoneSurvivor82

    LoneSurvivor82

    Joined:
    Aug 17, 2019
    Posts:
    41
    I found out, that I can avoid pb.RebuildColliders(); by calling pb.Refresh(RefreshMask.Collisions); instead of pb.RebuildColliders(); which is a step forward. But I'm still riddling how to get rid of pb.Optimize();


    Code (CSharp):
    1. protected void FinishMesh()
    2.     {
    3.         pb.ToMesh();
    4.         pb.Refresh();
    5.        
    6.         pb.Optimize();
    7.  
    8.         pb.Refresh(RefreshMask.Collisions);
    9.  
    10.         Collider collider = GetComponent<Collider>();
    11.         collider.enabled = false;
    12.         collider.enabled = true;
    13.     }
     
  3. LoneSurvivor82

    LoneSurvivor82

    Joined:
    Aug 17, 2019
    Posts:
    41
    Okay, after debugging what the method actually does and finding out that a lot of false if-statement aren't called, I could strip it down to the following which let me get rid of the UnityEditor-using:

    Code (CSharp):
    1. protected void FinishMesh()
    2.     {
    3.         pb.ToMesh();
    4.         pb.Refresh();
    5.  
    6.         MeshUtility.CollapseSharedVertices(gameObject.GetComponent<MeshFilter>().sharedMesh);
    7.  
    8.         pb.Refresh(RefreshMask.Collisions);
    9.  
    10.         Collider collider = GetComponent<Collider>();
    11.         collider.enabled = false;
    12.         collider.enabled = true;
    13.     }
     
    kaarrrllll likes this.
  4. kaarrrllll

    kaarrrllll

    Unity Technologies

    Joined:
    Aug 24, 2017
    Posts:
    552
    Just to clarify, `Optimize` does not need to be called at runtime. That function does various editor-only post-processing operations that either aren't possible or aren't necessary at runtime.
     
    LoneSurvivor82 likes this.
  5. LoneSurvivor82

    LoneSurvivor82

    Joined:
    Aug 17, 2019
    Posts:
    41
    Hi Kaarrrllll,

    thanks for your feedback (secretly I hoped, you would read my post ;)).

    I just started to work with unity 3D (I'm a barely beginner), my previous Unity experience was with 2D only.

    Please let my explain why I needed to use Optimize and RebuildColliders in the first approach:

    For my maze-game I created a 2x2x4 units cuboid with ProBuilder which should be used as a wall-block. The maze-field consists of a matrix of random walls and walkable non-walls-fields (both the same size). So in the easy way, every wall-tile could be one instance of that cuboid. That easy creates a lot of objects if the maze is larger.

    So my intention to reduce the amount of gameobjects was to calculate connected wall tiles and instead of creating for e.g. five unique cuboids for a wall with a length of five meters, I create only one and extrude a defined face to get a five-fields long cuboid. For non-textured walls a simple scale by fyve would be sufficent but as the game-setting is an ancient egypt pyramid, there should be some hierogplyhs on the walls. And to strech them was no option because I want to randomize the texture on every unit of the wall.

    For this, I had to call Optimize because without, the textures wouldn't appear on the extended wall.

    And I had to call RebuildColliders because without, the wall would be non-solid on the extended part and my player-character can walk through it.

    But maybe it's a dumb idea of mine to extend gameobjects on runtime. So I am eager to learn if there is (and I am sure, it is) a better way to implement this :)

    Best wishes and thank you very much
    Ricky
     
  6. kaarrrllll

    kaarrrllll

    Unity Technologies

    Joined:
    Aug 24, 2017
    Posts:
    552
    I see. So if the problem is textures and colliders not updating, you will just need to pass those attributes in the `mesh.Refresh(RefreshMask.UV | RefreshMask.Collisions)` call. Or in most cases you can omit the RefreshMask argument and Refresh will by default run as if all flags were passed.