Search Unity

Bug No UV change after fixing UV map

Discussion in 'General Graphics' started by fomafomitch, Dec 23, 2022.

  1. fomafomitch

    fomafomitch

    Joined:
    Nov 22, 2020
    Posts:
    89
    Hello,

    I have a script that create mesh for an hexmap. Every cell (that contain 6 vertices) store data using UV1, UV2, UV3. There is a lot of data I will not explain all of them but what is important is that when cells change some UVs data it is visible in their shader :

    ezgif.com-gif-maker (8).gif


    But my vertices weren't "UVmap" so I cannot use some shader effect on it. Anyway after a lot of research I found this script that is doing perfectly what I need :
    https://github.com/kurtdekker/makegeo/blob/master/makegeo/Assets/setuvtoworld/SetUVToWorld.cs

    But the problem is : when I use SetUVToWorld.cs on a MeshRenderer, every datas on UV1, UV2, UV3 is "set in stone" and cannot change anymore. I like this script but I lost my ability to alterate the mesh.

    In the next video you can see a change of texture thanks to SetUVToWorld.cs + using another shader. But after that I can't alterate anything :
    ezgif.com-gif-maker (9).gif

    Code for my HexMesh that add UV1 UV2 UV3 vectors :

    Code (CSharp):
    1.  
    2. [RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
    3. public class HexMesh : MonoBehaviour {
    4.    
    5.     public HexFeatureManager features;
    6.  
    7.     [NonSerialized] List<Vector3> vertices, terrainTypes;
    8.     [NonSerialized] List<Vector3> extraData_Fog_Terrain_Transition_LayerOver;
    9.     [NonSerialized] List<Vector3> extraData_ColorCoeff_Height_other;
    10.     [NonSerialized] List<Color> colors;
    11.     [NonSerialized] List<int> triangles;
    12.  
    13.     Mesh hexMesh;
    14.     MeshCollider meshCollider;
    15.  
    16.     void Awake () {
    17.         GetComponent<MeshFilter>().mesh = hexMesh = new Mesh();
    18.         meshCollider = gameObject.AddComponent<MeshCollider>();
    19.         hexMesh.name = "Hex_Mesh";
    20.     }
    21.  
    22.     public void Clear()
    23.     {
    24.         hexMesh.Clear();
    25.         vertices = ListPool<Vector3>.Get();
    26.         colors = ListPool<Color>.Get();
    27.         terrainTypes = ListPool<Vector3>.Get();
    28.         extraData_Fog_Terrain_Transition_LayerOver = ListPool<Vector3>.Get();
    29.         extraData_ColorCoeff_Height_other = ListPool<Vector3>.Get();
    30.         triangles = ListPool<int>.Get();
    31.     }
    32.  
    33.     public void Apply()
    34.     {
    35.         hexMesh.SetVertices(vertices);
    36.         ListPool<Vector3>.Add(vertices);
    37.  
    38.         hexMesh.SetColors(colors);
    39.         ListPool<Color>.Add(colors);
    40.  
    41.         hexMesh.SetUVs(1, terrainTypes);
    42.         ListPool<Vector3>.Add(terrainTypes);
    43.  
    44.         hexMesh.SetUVs(2, extraData_Fog_Terrain_Transition_LayerOver);
    45.         ListPool<Vector3>.Add(extraData_Fog_Terrain_Transition_LayerOver);
    46.  
    47.         hexMesh.SetUVs(3, extraData_ColorCoeff_Height_other);
    48.         ListPool<Vector3>.Add(extraData_ColorCoeff_Height_other);
    49.  
    50.         hexMesh.SetTriangles(triangles, 0);
    51.         ListPool<int>.Add(triangles);
    52.  
    53.         meshCollider.sharedMesh = hexMesh;
    54.     }
    55. }
    Function Apply() is called by the chunk to update mesh :

    Code (CSharp):
    1.  
    2.     //HexGridChunk.CS
    3.  
    4.     public void Triangulate()
    5.     {
    6.         terrain.Clear();
    7.         for (int i = 0; i < cells.Length; i++)
    8.         {
    9.             Triangulate(cells[i]);
    10.         }
    11.         terrain.Apply();
    12.     }
    13.    
    14.  
    Code (CSharp):
    1. // @kurtdekker
    2. public class SetUVToWorld : MonoBehaviour
    3. {
    4.     // set this if you are putting it on a parent object, otherwise
    5.     // this script operates only on the current GameObject.
    6.     public    bool        DriveToAllChildren;
    7.  
    8.     public    Material    MaterialToUse;
    9.  
    10.     public    bool        PreserveColor;
    11.  
    12.     public    bool        IncludeRotation;
    13.  
    14.     void Reset()
    15.     {
    16.         IncludeRotation = true;
    17.         MaterialToUse = null;
    18.     }
    19.  
    20.     public static void AddToAllMeshRenderersWithMeshFilters(
    21.         GameObject go,
    22.         bool _PreserveColor = false,
    23.         Material _MaterialToUse = null)
    24.     {
    25.         MeshRenderer[] rndrrs = go.GetComponentsInChildren<MeshRenderer> ();
    26.         foreach( var mr in rndrrs)
    27.         {
    28.             MeshFilter mf = mr.GetComponent<MeshFilter> ();
    29.             if (mf != null)
    30.             {
    31.                 var uvsetter = mr.gameObject.AddComponent<SetUVToWorld> ();
    32.                 uvsetter.PreserveColor = _PreserveColor;
    33.                 uvsetter.MaterialToUse = _MaterialToUse;
    34.             }
    35.         }
    36.     }
    37.  
    38.     void Start()
    39.     {
    40.         // be careful: we are intentionally adding instances of this
    41.         // script that don't have the DriveToAllChildren bit set, in
    42.         // order to benefit from setting things once.
    43.         if (DriveToAllChildren)
    44.         {
    45.             AddToAllMeshRenderersWithMeshFilters(
    46.                 gameObject, PreserveColor, MaterialToUse);
    47.             return;
    48.         }
    49.  
    50.         MeshFilter mf = GetComponent<MeshFilter> ();
    51.         if (mf)
    52.         {
    53.             Vector2[] uvs = mf.mesh.uv;
    54.             Vector3[] verts = mf.mesh.vertices;
    55.             int[] tris = mf.mesh.triangles;
    56.  
    57.             if (uvs.Length != verts.Length)
    58.             {
    59.                 uvs = new Vector2[ verts.Length];
    60.             }
    61.  
    62.             for (int i = 0; i < verts.Length; i++)
    63.             {
    64.                 verts [i] = transform.TransformPoint (verts [i]);
    65.                 if (!IncludeRotation)
    66.                 {
    67.                     verts [i] = Quaternion.Inverse (transform.rotation) * verts [i];
    68.                 }
    69.             }
    70.  
    71.             for ( int i = 0; i < tris.Length; i += 3)
    72.             {
    73.                 Vector3 norm = Vector3.Cross (
    74.                     verts [tris [i + 1]] - verts [tris [i + 0]],
    75.                     verts [tris [i + 1]] - verts [tris [i + 2]]).normalized;
    76.  
    77.                 float dotX = Mathf.Abs (Vector3.Dot (norm, Vector3.right));
    78.                 float dotY = Mathf.Abs (Vector3.Dot (norm, Vector3.up));
    79.                 float dotZ = Mathf.Abs (Vector3.Dot (norm, Vector3.forward));
    80.  
    81.                 if (dotX > dotY && dotX > dotZ)
    82.                 {
    83.                     for ( int j = 0; j < 3; j++)
    84.                     {
    85.                         uvs [tris[i + j]] = new Vector2 (verts [tris[i + j]].z, verts [tris[i + j]].y);
    86.                     }
    87.                 }
    88.                 else
    89.                 {
    90.                     if (dotY > dotX && dotY > dotZ)
    91.                     {
    92.                         for ( int j = 0; j < 3; j++)
    93.                         {
    94.                             uvs [tris[i + j]] = new Vector2 (verts [tris[i + j]].x, verts [tris[i + j]].z);
    95.                         }
    96.                     }
    97.                     else
    98.                     {
    99.                         for ( int j = 0; j < 3; j++)
    100.                         {
    101.                             uvs [tris[i + j]] = new Vector2 (verts [tris[i + j]].x, verts [tris[i + j]].y);
    102.                         }
    103.                     }
    104.                 }
    105.             }
    106.             mf.mesh.uv = uvs;
    107.  
    108.             if (MaterialToUse)
    109.             {
    110.                 Dictionary<Color, Material> ColorDictToSaveDrawcalls = new Dictionary<Color, Material>();
    111.  
    112.                 Renderer rndrr = GetComponent<Renderer>();
    113.                 if (rndrr)
    114.                 {
    115.                     Material[] allNewMaterials = new Material[ rndrr.materials.Length];
    116.  
    117.                     for (int i = 0; i < allNewMaterials.Length; i++)
    118.                     {
    119.                         Color preservedColor = Color.white;
    120.  
    121.                         Material originalMaterial = rndrr.materials[i];
    122.  
    123.                         var instancedMaterial = MaterialToUse;
    124.  
    125.                         if (originalMaterial)
    126.                         {
    127.                             if (PreserveColor)
    128.                             {
    129.                                 preservedColor = originalMaterial.color;
    130.  
    131.                                 if (ColorDictToSaveDrawcalls.ContainsKey( preservedColor))
    132.                                 {
    133.                                     instancedMaterial = ColorDictToSaveDrawcalls[preservedColor];
    134.                                 }
    135.                                 else
    136.                                 {
    137.                                     instancedMaterial = new Material( MaterialToUse);
    138.                                     instancedMaterial.color = preservedColor;
    139.                                     ColorDictToSaveDrawcalls[preservedColor] = instancedMaterial;
    140.                                 }
    141.                             }
    142.                         }
    143.  
    144.                         allNewMaterials[i] = instancedMaterial;
    145.                     }
    146.  
    147.                     rndrr.materials = allNewMaterials;
    148.                 }
    149.             }
    150.         }
    151.         else
    152.         {
    153.             Debug.LogError (
    154.                 GetType() + ": there is no MeshFilter on GameObject '" + name + "'!");
    155.         }
    156.     }
    157. }
    I love SetUvWorld script but I don't understant why it remove my script capacity to change their UV1 UV2 UV3 ?