Search Unity

Multiplatform Runtime Level Editor

Discussion in 'Assets and Asset Store' started by FreebordMAD, Jun 10, 2014.

  1. FreebordMAD

    FreebordMAD

    Joined:
    Mar 15, 2013
    Posts:
    633
    You should modify the object map on runtime, then you could re-instantiate the level editor main class.
    See "Step 3: Add LE_Object To The Object Map" on the page below
    http://www.freebord-game.com/index....time-level-editor/documentation/level-objects
     
  2. aosaGG

    aosaGG

    Joined:
    May 20, 2021
    Posts:
    1
    hi, i whould like to know how it whould be posble to save a string in the object, like the colour but with an url, for a specific gamebject that loads a web custom image
     
  3. FlightFight

    FlightFight

    Joined:
    May 29, 2017
    Posts:
    27
    Hi Vagelis, can you give us any hints on how you fixed the gizmo? I'm using HDRP 14.
     
  4. vagelis199

    vagelis199

    Joined:
    Jul 27, 2012
    Posts:
    183
    The most essential thing you can do is find the material corresponding to the gizmo and change it. But there are more things you have to do to completely make the Asset work in HDRP. (Mostly related to materials and Camera rendering issues)
     
    FlightFight likes this.
  5. fenix012585

    fenix012585

    Joined:
    Dec 26, 2022
    Posts:
    8
    Hello,
    I am really struggling to grasp creating a basic terrain editor and object editor scene. I have been going through the docs, but I don't see an actual how to and I lack a level of knowledge where the documentation would help. Do you have a more basic list of steps?

    Thank you!
     
  6. FreebordMAD

    FreebordMAD

    Joined:
    Mar 15, 2013
    Posts:
    633
    The basic way to do it is to pick one of the example scenes and to modify it to what you need. Did you try to create a new scene from scratch?

    If you are modifying any of the existing examples, which step gives you trouble?
     
  7. fenix012585

    fenix012585

    Joined:
    Dec 26, 2022
    Posts:
    8

    I've tried both ways. Modifying the exampleGame Editor seems like the best course of action for me, but I keep getting a critical console error... "Float array size wrong (layers should be 0) whenever I try to load a saved map.

    The scene I am using is in the build settings.

    If I create and load a blank terrain everything is fine. This happens after making changes to or painting a texture like grass on the map.
     
    Last edited: Aug 25, 2023
  8. fenix012585

    fenix012585

    Joined:
    Dec 26, 2022
    Posts:
    8
    On a second issue, Do you plan on upgrading the editor to Unity LTS 2022? several of the TerrainData.splatPrototypes are showing obsolete now.

    And what is the best method to convert the mouse selector projector to URP?
     
    Last edited: Aug 24, 2023
  9. FreebordMAD

    FreebordMAD

    Joined:
    Mar 15, 2013
    Posts:
    633
    Does this error also show in the template scenes or only in your scene?

    It sounds like your TerrainTextureConfig used to load the level might differ from the config that is used to save the level. Can you please make some screenshots?
    http://www.freebord-game.com/index....e-level-editor/documentation/terrain-textures

    I usually fix blocking issues in newer Unity versions and do not fix obsolete errors right away. Unity frequently changes their system, considering the amount of code in the MRLE I would need to almost fully rewrite it to fix the obsolete warnings.

    What exactly is the issue?
     
  10. fenix012585

    fenix012585

    Joined:
    Dec 26, 2022
    Posts:
    8
    Of Course. I also attached a quick screencapture of the issue happening.
    For reference, this is no custom code or modifications to the demo scene/config at all.
    I did a fresh install with nothing but this asset.

    Screengrab:



     
  11. fenix012585

    fenix012585

    Joined:
    Dec 26, 2022
    Posts:
    8
    I totally understand. I'm just happy to hear you update as things break :).

    As for the issue with the projector, URP just dosn't support them at all. I am not sure what to even research in order to start fixing this.

    Any assistance in getting this to work as well as resolving the above issues is amazing.

    Thank you.
     
  12. FPVFreerider

    FPVFreerider

    Joined:
    Jun 8, 2015
    Posts:
    8
    I recently needed to migrate my project to Unity 2022 LTS (from 2021 LTS).
    I am getting the same issue as fenix012585 describes.

    When creating a new map from scratch, the behavior is actually quite similar to what I described in post #716, a few years ago earlier in this thread.
    Luckily, you were able to solve that issue quickly the last time.

    Here is a description of what happens when I create a new level:
    When I click "Create Terrain" in the level editor, a terrain is created, but the base texture is not applied. (Instead there is only a checkered pattern on the terrain).
    If I then go the Paint Terrain tab in the level editor, it shows no texture being used.
    If I then add a texture, that texture -is- applied to the terrain.
    (I can then continue to add several more textures - that works as usual).

    However, if I save the level and then try to load it (or, try to load another previously created level), it immediately throws the error:
    Exception: Float array size wrong (layers should be 0)
    ....and the level is not loaded.

    Hope you are able to look into this.
    (As before, I have been using MRLE for several years, and have made changes to the code here and there, so it will not be possible for me to just update the package. Hopefully, it will be possible for you to post a code snippet that can be pasted into the existing code).
    I would also like to know if you have a paypal account or similar, that I could send a donation to?
     
  13. FPVFreerider

    FPVFreerider

    Joined:
    Jun 8, 2015
    Posts:
    8
    Exception: Float array size wrong (layers should be 0)

    UnityEngine.TerrainData.SetAlphamaps (System.Int32 x, System.Int32 y, System.Single[,,] map) (at <4e4ef5a58cf34e32b28ca9d419b44b7c>:0)

    LE_LevelEditor.Core.LE_SaveLoad.LoadTerrainAlphamaps (System.IO.BinaryReader p_stream, UnityEngine.TerrainData p_terrainData, UnityEngine.Texture2D[] p_terrainTextures, UnityEngine.Vector2[] p_terrainTextureSizes, UnityEngine.Vector2[] p_terrainTextureOffsets) (at Assets/LapinerTools/LevelEditor/Scripts/Core/LE_SaveLoad.cs:739)

    LE_LevelEditor.Core.LE_SaveLoad.LoadTerrainData (System.IO.BinaryReader p_stream, UnityEngine.Texture2D[] p_terrainTextures, UnityEngine.Vector2[] p_terrainTextureSizes, UnityEngine.Vector2[] p_terrainTextureOffsets) (at Assets/LapinerTools/LevelEditor/Scripts/Core/LE_SaveLoad.cs:630)

    LE_LevelEditor.Core.LE_SaveLoad.LoadLevelDataFromByteArray (System.Byte[] p_byteArray, System.Int32 p_terrainLayer, UnityEngine.Texture2D[] p_terrainTextures, UnityEngine.Vector2[] p_terrainTextureSizes, UnityEngine.Vector2[] p_terrainTextureOffsets) (at Assets/LapinerTools/LevelEditor/Scripts/Core/LE_SaveLoad.cs:257)

    LE_LevelEditor.Logic.LE_LogicLevel.<GetLoadEvent>b__14_0 (System.Byte[] p_savedLevelData) (at Assets/LapinerTools/LevelEditor/Scripts/Logic/LE_LogicLevel.cs:142)

    LE_LevelEditor.Example.ExampleGame_Editor+<LateLoad>d__12.MoveNext () (at Assets/LapinerTools/LevelEditor/Example/Scripts/ExampleGame_Editor.cs:217)

    UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at <10871f9e312b442cb78b9b97db88fdcb>:0)
     
  14. FreebordMAD

    FreebordMAD

    Joined:
    Mar 15, 2013
    Posts:
    633
    @fenix012585 , @FPVFreerider - thanks for the reports, seems something is broken in the new Unity version so maybe they finally deprecated something completely, e.g. the TerrainData.splatPrototypes. I need some time to fix this though, but I will make sure to download Unity 2022 LTS (for me this is 2022.3.8f1) today => @fenix012585 yours seems to be already a little outdated, do you plan to upgrade?

    It depends on what kind of URP you have, but in the end I guess decals have completely replaced projectors. An entry point for research could be e.g.:
    https://docs.unity3d.com/Packages/c...ersal@12.0/manual/renderer-feature-decal.html

    [Update:] same behavior for me in 2022 LTS => I'm trying to figure out why, ... it was the deprecated splat prototypes...
     
    Last edited: Sep 5, 2023
  15. fenix012585

    fenix012585

    Joined:
    Dec 26, 2022
    Posts:
    8
    It looks like that update just landed for me. I am updating it as I am typing this out.

    Decals, gotcha... I'll start looking in to those.

    Thank you again :)
     
  16. FreebordMAD

    FreebordMAD

    Joined:
    Mar 15, 2013
    Posts:
    633
    Super awesome, so now Unity guys and gals will not delete APIs that are obsolete, but stopped working anymore...
    For everybody searching this like me and not finding anything TerrainData.splatPrototypes is deprecated since around 2019, but it was always working and producing decent results by filling TerrainLayer.terrainLayers somewhere in the background. Now in 2022 LTS this logic is broken. Setting anything in TerrainData.splatPrototypes will not fill the TerrrainLayer.terrainLayers anymore, thus if you call TerrainData.SetAlphamaps the terrain data will not expect that your terrain data has any alpha layers at all and assume that you should pass 0 entries. So you get
    Exception: Float array size wrong (layers should be 0)
    UnityEngine.TerrainData.SetAlphamaps


    My fix is quite simple, I left the old code there as well for people to see the difference between splatPrototypes and terrainLayers.

    @fenix012585, @FPVFreerider just replace in the class LE_SaveLoad the method LoadTerrainAlphamaps with the code below.
    Code (CSharp):
    1.         private static void LoadTerrainAlphamaps(BinaryReader p_stream, TerrainData p_terrainData, Texture2D[] p_terrainTextures, Vector2[] p_terrainTextureSizes, Vector2[] p_terrainTextureOffsets)
    2.         {
    3.             // general alphamap data
    4.             p_terrainData.alphamapResolution = p_stream.ReadInt32();
    5.             int alphamapWidth = p_stream.ReadInt32();
    6.             int alphamapHeight = p_stream.ReadInt32();
    7.             int alphamapLayers = p_stream.ReadInt32();
    8.  
    9.             // link textures from indices for each alphamap layer
    10.             TerrainLayer[] layers = new TerrainLayer[alphamapLayers];
    11.             //SplatPrototype[] splats = new SplatPrototype[alphamapLayers];
    12.             for (int i = 0; i < alphamapLayers; i++)
    13.             {
    14.                 layers[i] = new TerrainLayer();
    15.                 //splats[i] = new SplatPrototype();
    16.                 int terrainTextureIndex = p_stream.ReadInt32();
    17.                 if (terrainTextureIndex == -1)
    18.                 {
    19.                     Debug.LogError("LE_SaveLoad: LoadTerrainAlphamaps: terrain used a texture that was not contained in the " +
    20.                                    "texture array passed to SaveCurrentLevelDataToByteArray! A texture coult not be indexed " +
    21.                                    "when the level was saved and will not be loaded!");
    22.                 }
    23.                 else if (terrainTextureIndex < 0 || terrainTextureIndex >= p_terrainTextures.Length)
    24.                 {
    25.                     Debug.LogError("LE_SaveLoad: LoadTerrainAlphamaps: the passed texture set seems to differ from the " +
    26.                                    "texture set passed to SaveCurrentLevelDataToByteArray! Texture index '"+terrainTextureIndex+"' " +
    27.                                    "is out of bounds! Texture will not be loaded!");
    28.                 }
    29.                 else
    30.                 {
    31.                     layers[i].diffuseTexture = p_terrainTextures[terrainTextureIndex];
    32.                     layers[i].tileSize = p_terrainTextureSizes[terrainTextureIndex];
    33.                     layers[i].tileOffset = p_terrainTextureOffsets[terrainTextureIndex];
    34.                     //splats[i].texture = p_terrainTextures[terrainTextureIndex];
    35.                     //splats[i].tileSize = p_terrainTextureSizes[terrainTextureIndex];
    36.                     //splats[i].tileOffset = p_terrainTextureOffsets[terrainTextureIndex];
    37.                 }
    38.             }
    39.             p_terrainData.terrainLayers = layers;
    40.             //p_terrainData.splatPrototypes = splats;
    41.             // alphamaps
    42.             float[,,] alphamaps = new float[alphamapWidth, alphamapHeight, alphamapLayers];
    43.             for (int x = 0; x < alphamapWidth; x++)
    44.             {
    45.                 for (int y = 0; y < alphamapHeight; y++)
    46.                 {
    47.                     for (int z = 0; z < alphamapLayers; z++)
    48.                     {
    49.                         alphamaps[x,y,z] = p_stream.ReadSingle();
    50.                     }
    51.                 }
    52.             }
    53.             p_terrainData.SetAlphamaps(0, 0, alphamaps);
    54.         }
    I will check the issue with creating the terrain in the first place now.
    I'm also looking forward to dig out my 15 years old laptop and trying to update the MRLE from there o_O

    [UPDATE]

    In LE_LogicTerrain class replace functions RemoveTerrainTexture, CreateOrRecycleTerrain and GetUnusedTerrainTextures

    Code (CSharp):
    1.  
    2.         public void RemoveTerrainTexture(Texture2D p_texture)
    3.         {
    4.             if (m_confT.TerrainTextureConfig != null)
    5.             {
    6.                 if (m_GUI3dTerrain != null && m_GUI3dTerrain.TerrainManager != null && m_GUI3dTerrain.TerrainManager.TerrainData != null)
    7.                 {
    8. #if UNITY_2019_2_OR_NEWER
    9.                     TerrainLayer[] layersOld = m_GUI3dTerrain.TerrainManager.TerrainData.terrainLayers;
    10.                     if (layersOld.Length > 0)
    11.                     {
    12.                         bool isTexFound = false;
    13.                         TerrainLayer[] layersNew = new TerrainLayer[layersOld.Length-1];
    14.                         for (int i = 0; i < layersOld.Length; i++)
    15.                         {
    16.                             if (!isTexFound && layersOld[i] != null && layersOld[i].diffuseTexture == p_texture)
    17.                             {
    18.                                 isTexFound = true;
    19.                             }
    20.                             else
    21.                             {
    22.                                 layersNew[isTexFound ? i-1 : i] = layersOld[i];
    23.                             }
    24.                         }
    25.                         if (isTexFound)
    26.                         {
    27.                             m_GUI3dTerrain.TerrainManager.TerrainData.terrainLayers = layersNew;
    28.                             m_doRebuildTerrainTab = true;
    29.                             // notify listeners that the level data was changed
    30.                             if (LE_EventInterface.OnChangeLevelData != null)
    31.                             {
    32.                                 LE_EventInterface.OnChangeLevelData(this, new LE_LevelDataChangedEvent(LE_ELevelDataChangeType.TERRAIN_TEXTURES));
    33.                             }
    34.                         }
    35.                         else
    36.                         {
    37.                             Debug.LogError("LE_LogicTerrain: RemoveTerrainTexture: given texture is not a splat texture of the terrain!");
    38.                         }
    39.                     }
    40.                     else
    41.                     {
    42.                         Debug.LogError("LE_LogicTerrain: RemoveTerrainTexture: terrain has no splat textures set!");
    43.                     }
    44. #else
    45.                     SplatPrototype[] splatTexturesOld = m_GUI3dTerrain.TerrainManager.TerrainData.splatPrototypes;
    46.                     if (splatTexturesOld.Length > 0)
    47.                     {
    48.                         bool isTexFound = false;
    49.                         SplatPrototype[] splatTexturesNew = new SplatPrototype[splatTexturesOld.Length-1];
    50.                         for (int i = 0; i < splatTexturesOld.Length; i++)
    51.                         {
    52.                             if (!isTexFound && splatTexturesOld[i] != null && splatTexturesOld[i].texture == p_texture)
    53.                             {
    54.                                 isTexFound = true;
    55.                             }
    56.                             else
    57.                             {
    58.                                 splatTexturesNew[isTexFound ? i-1 : i] = splatTexturesOld[i];
    59.                             }
    60.                         }
    61.                         if (isTexFound)
    62.                         {
    63.                             m_GUI3dTerrain.TerrainManager.TerrainData.splatPrototypes = splatTexturesNew;
    64.                             m_doRebuildTerrainTab = true;
    65.                             // notify listeners that the level data was changed
    66.                             if (LE_EventInterface.OnChangeLevelData != null)
    67.                             {
    68.                                 LE_EventInterface.OnChangeLevelData(this, new LE_LevelDataChangedEvent(LE_ELevelDataChangeType.TERRAIN_TEXTURES));
    69.                             }
    70.                         }
    71.                         else
    72.                         {
    73.                             Debug.LogError("LE_LogicTerrain: RemoveTerrainTexture: given texture is not a splat texture of the terrain!");
    74.                         }
    75.                     }
    76.                     else
    77.                     {
    78.                         Debug.LogError("LE_LogicTerrain: RemoveTerrainTexture: terrain has no splat textures set!");
    79.                     }
    80. #endif
    81.                 }
    82.             }
    83.             else
    84.             {
    85.                 Debug.LogError("LE_LogicTerrain: RemoveTerrainTexture: LE_ConfigTerrain has no TerrainTextureConfig set!");
    86.             }
    87.         }
    88.  
    89.  
    90.  
    91.         private static void CreateOrRecycleTerrain(TerrainData p_terrainData, int p_terrainLayer, LE_ConfigTerrain p_confT, int p_terrainBaseTextureIndex)
    92.         {
    93.             if (p_terrainData == null)
    94.             {
    95.                 Debug.LogError("LE_LogicTerrain: CreateOrRecycleTerrain: passed terrain data was null!");
    96.                 return;
    97.             }
    98.          
    99.             Vector3 size = p_terrainData.size;
    100.             float maxSize = Mathf.Max(size.x, size.z);
    101.             // set heightmap resolution depending on selected terrain size
    102.             int heightmapResolution = p_confT.HeightmapResolutions[0];
    103.             for (int i = 1; i < p_confT.HeightmapResolutionSizes.Length; i++)
    104.             {
    105.                 if (maxSize >= p_confT.HeightmapResolutionSizes[i-1])
    106.                 {
    107.                     heightmapResolution = p_confT.HeightmapResolutions[i];
    108.                 }
    109.                 else
    110.                 {
    111.                     break;
    112.                 }
    113.             }
    114.             p_terrainData.heightmapResolution = heightmapResolution;
    115.             // set alphamap resolution depending on selected terrain size
    116.             int alphamapResolution = p_confT.AlphamapResolutions[0];
    117.             for (int i = 1; i < p_confT.AlphamapResolutionSizes.Length; i++)
    118.             {
    119.                 if (maxSize >= p_confT.AlphamapResolutionSizes[i-1])
    120.                 {
    121.                     alphamapResolution = p_confT.AlphamapResolutions[i];
    122.                 }
    123.                 else
    124.                 {
    125.                     break;
    126.                 }
    127.             }
    128.             p_terrainData.alphamapResolution = alphamapResolution;
    129.             // restore size since it is changed when resolution is set
    130.             p_terrainData.size = size;
    131. #if UNITY_2019_2_OR_NEWER
    132.             // set base texture in terrain data
    133.             TerrainLayer[] baseTextureSet = new TerrainLayer[1];
    134.             baseTextureSet[0] = new TerrainLayer();
    135.             baseTextureSet[0].diffuseTexture = p_confT.TerrainTextureConfig.TERRAIN_TEXTURES[p_terrainBaseTextureIndex];
    136.             baseTextureSet[0].tileSize = p_confT.TerrainTextureConfig.TERRAIN_TEXTURE_SIZES[p_terrainBaseTextureIndex];
    137.             baseTextureSet[0].tileOffset = p_confT.TerrainTextureConfig.TERRAIN_TEXTURE_OFFSETS[p_terrainBaseTextureIndex];
    138.             p_terrainData.terrainLayers = baseTextureSet;
    139.             // fully cover terrain with the initial texture - was default before Unity 2019.2 (tested with 2019.2.6f)
    140.             float[,,] alphamap = new float[p_terrainData.alphamapWidth, p_terrainData.alphamapHeight, p_terrainData.alphamapTextureCount];
    141.             for (int x=0; x < p_terrainData.alphamapWidth; x++)
    142.             {
    143.                 for (int y=0; y < p_terrainData.alphamapHeight; y++)
    144.                 {
    145.                     for (int z=0; z < p_terrainData.alphamapTextureCount; z++)
    146.                     {
    147.                         alphamap[x, y, z] = 1f;
    148.                     }
    149.                 }
    150.             }
    151.             p_terrainData.SetAlphamaps(0, 0, alphamap);
    152. #else
    153.             // set base texture in terrain data
    154.             SplatPrototype[] baseTextureSet = new SplatPrototype[1];
    155.             baseTextureSet[0] = new SplatPrototype();
    156.             baseTextureSet[0].texture = p_confT.TerrainTextureConfig.TERRAIN_TEXTURES[p_terrainBaseTextureIndex];
    157.             baseTextureSet[0].tileSize = p_confT.TerrainTextureConfig.TERRAIN_TEXTURE_SIZES[p_terrainBaseTextureIndex];
    158.             baseTextureSet[0].tileOffset = p_confT.TerrainTextureConfig.TERRAIN_TEXTURE_OFFSETS[p_terrainBaseTextureIndex];
    159.             p_terrainData.splatPrototypes = baseTextureSet;
    160. #endif
    161.             // create terrain GO
    162.             GameObject terrainGO = CreateOrRecycleTerrain(p_terrainData, p_terrainLayer);
    163.          
    164.             // notify listeners that a terrain was created
    165.             if (LE_EventInterface.OnTerrainCreated != null)
    166.             {
    167.                 LE_EventInterface.OnTerrainCreated(terrainGO, new LE_TerrainCreatedEvent(terrainGO));
    168.             }
    169.         }
    170.  
    171.  
    172.  
    173.         private Texture2D[] GetUnusedTerrainTextures()
    174.         {
    175.             if (m_confT.TerrainTextureConfig != null)
    176.             {
    177.                 if (m_GUI3dTerrain != null && m_GUI3dTerrain.TerrainManager != null && m_GUI3dTerrain.TerrainManager.TerrainData != null)
    178.                 {
    179.                     Texture2D[] configTextures = m_confT.TerrainTextureConfig.TERRAIN_TEXTURES;
    180.                     List<Texture2D> unusedTexturesList = new List<Texture2D>();
    181. #if UNITY_2019_2_OR_NEWER
    182.                     TerrainLayer[] layers = m_GUI3dTerrain.TerrainManager.TerrainData.terrainLayers;
    183.                     for (int i = 0; i < configTextures.Length; i++)
    184.                     {
    185.                         bool isUsed = false;
    186.                         for (int j = 0; j < layers.Length; j++)
    187.                         {
    188.                             if (layers[j].diffuseTexture == configTextures[i])
    189.                             {
    190.                                 isUsed = true;
    191.                                 break;
    192.                             }
    193.                         }
    194.                         if (!isUsed)
    195.                         {
    196.                             unusedTexturesList.Add(configTextures[i]);
    197.                         }
    198.                     }
    199. #else
    200.                     SplatPrototype[] usedSplatTextures = m_GUI3dTerrain.TerrainManager.TerrainData.splatPrototypes;
    201.                     for (int i = 0; i < configTextures.Length; i++)
    202.                     {
    203.                         bool isUsed = false;
    204.                         for (int j = 0; j < usedSplatTextures.Length; j++)
    205.                         {
    206.                             if (usedSplatTextures[j].texture == configTextures[i])
    207.                             {
    208.                                 isUsed = true;
    209.                                 break;
    210.                             }
    211.                         }
    212.                         if (!isUsed)
    213.                         {
    214.                             unusedTexturesList.Add(configTextures[i]);
    215.                         }
    216.                     }
    217. #endif
    218.                     return unusedTexturesList.ToArray();
    219.                 }
    220.                 else
    221.                 {
    222.                     return m_confT.TerrainTextureConfig.TERRAIN_TEXTURES;
    223.                 }
    224.             }
    225.             else
    226.             {
    227.                 Debug.LogError("LE_LogicTerrain: GetUnusedTerrainTextures: LE_ConfigTerrain has no TerrainTextureConfig set!");
    228.                 return new Texture2D[0];
    229.             }
    230.         }
    231.  
    In LE_TerrainManager class replace function PaintTexture
    Code (CSharp):
    1.  
    2.         public void PaintTexture(int p_splatPrototypeIndex, float p_delta, float p_targetValue, Texture2D p_alphaBrushTexture, float p_relativeBrushSize, Vector2 p_relativeLocalLocation)
    3.         {
    4. #if UNITY_2019_2_OR_NEWER
    5.             if (p_splatPrototypeIndex < 0 || p_splatPrototypeIndex >= m_terrainData.terrainLayers.Length)
    6.             {
    7.                 Debug.LogError("LE_TerrainManager: PaintTexture: terrain layer index '"+p_splatPrototypeIndex+"' is out of bounds [0,"+m_terrainData.terrainLayers.Length+"]");
    8.                 return;
    9.             }
    10. #else
    11.             if (p_splatPrototypeIndex < 0 || p_splatPrototypeIndex >= m_terrainData.splatPrototypes.Length)
    12.             {
    13.                 Debug.LogError("LE_TerrainManager: PaintTexture: splat prototype index '"+p_splatPrototypeIndex+"' is out of bounds [0,"+m_terrainData.splatPrototypes.Length+"]");
    14.                 return;
    15.             }
    16. #endif
    17.             float[,,] alphaMaps;
    18.             int minX, maxX, minY, maxY;
    19.             float relBrushMinX, relBrushMinY, alphamapMaxX, alphamapMaxY;
    20.             alphamapMaxX = m_terrainData.alphamapWidth - 1;
    21.             alphamapMaxY = m_terrainData.alphamapHeight - 1;
    22.             GetAffectedAreaInternal(p_alphaBrushTexture, p_relativeBrushSize, p_relativeLocalLocation, alphamapMaxX, alphamapMaxY,
    23.                                     out minX, out maxX, out minY, out maxY, out relBrushMinX, out relBrushMinY);
    24.             // get the current alphamaps array
    25.             alphaMaps = m_terrainData.GetAlphamaps(minY, minX, maxY-minY+1, maxX-minX+1);
    26.  
    27.             // inform listeners of the affected alphamaps array with its values before the change
    28.             if (OnBeforeChangeAlphamaps != null)
    29.             {
    30.                 OnBeforeChangeAlphamaps(new AlphamapData(minY, minX, alphaMaps));
    31.             }
    32.  
    33.             // apply alpha change to every affected alpha map entry
    34.             // according to given p_delta and the alpha value in p_alphaBrushTexture
    35.             // alpha is always changed towards p_targetValue
    36.             int iterateToX = Mathf.Min(maxX-minX, alphaMaps.GetLength(0)-1);
    37.             int iterateToY = Mathf.Min(maxY-minY, alphaMaps.GetLength(1)-1);
    38.             int iterateToZ = alphaMaps.GetLength(2)-1;
    39.             float brushValue, alphaMapValue, signDiff;
    40.             for (int indexX = 0; indexX <= iterateToX; indexX++)
    41.             {
    42.                 for (int indexY = 0; indexY <= iterateToY; indexY++)
    43.                 {
    44.                     alphaMapValue = alphaMaps[indexX,indexY,p_splatPrototypeIndex];
    45.                     if (Mathf.Abs(alphaMapValue - p_targetValue) > 0.0001f)
    46.                     {
    47.                         signDiff = Mathf.Sign(p_targetValue - alphaMapValue);
    48.                         brushValue = p_delta * signDiff * p_alphaBrushTexture.GetPixelBilinear(
    49.                             (((float)(indexY+minY) / alphamapMaxY) - relBrushMinY) / p_relativeBrushSize,
    50.                             (((float)(indexX+minX) / alphamapMaxX) - relBrushMinX) / p_relativeBrushSize).a;
    51.  
    52.                         // apply change in the selected layer
    53.                         if (signDiff != Mathf.Sign(p_targetValue - (alphaMapValue + brushValue)))
    54.                         {
    55.                             alphaMapValue = p_targetValue;
    56.                         }
    57.                         else
    58.                         {
    59.                             alphaMapValue += brushValue;
    60.                         }
    61.                         alphaMaps[indexX,indexY,p_splatPrototypeIndex] = alphaMapValue;
    62.                         // normilize the other layers
    63.                         float alphaMapsSum = 0;
    64.                         // calculate the sum of the other layers
    65.                         for (int indexZ = 0; indexZ <= iterateToZ; indexZ++)
    66.                         {
    67.                             if (indexZ != p_splatPrototypeIndex)
    68.                             {
    69.                                 alphaMapsSum += alphaMaps[indexX,indexY,indexZ];
    70.                             }
    71.                         }
    72.                         // if the other layers have values, then reduce those to get a normalized result
    73.                         if (alphaMapsSum != 0)
    74.                         {
    75.                             float normalizer = (1f - alphaMapValue) / alphaMapsSum;
    76.                             for (int indexZ = 0; indexZ <= iterateToZ; indexZ++)
    77.                             {
    78.                                 if (indexZ != p_splatPrototypeIndex)
    79.                                 {
    80.                                     alphaMaps[indexX,indexY,indexZ] *= normalizer;
    81.                                 }
    82.                             }
    83.                         }
    84.                         // if the other layers have no values, but the target layers is not normalized, then...
    85.                         else if (alphaMapValue != 1)
    86.                         {
    87.                             if (p_splatPrototypeIndex != 0)
    88.                             {
    89.                                 // fill up the base layer with the missing amount to normalization
    90.                                 alphaMaps[indexX,indexY,0] = 1f - alphaMapValue;
    91.                             }
    92.                             else
    93.                             {
    94.                                 // and do not allow to decrease the base layer opacity
    95.                                 alphaMaps[indexX,indexY,0] = 1f;
    96.                             }
    97.                         }
    98.                     }
    99.                 }  
    100.             }
    101.  
    102.             // apply the changed alpha maps
    103.             m_terrainData.SetAlphamaps(minY, minX, alphaMaps);
    104.  
    105.             // inform listeners of the affected alphamaps array with its values after the change
    106.             if (OnAfterChangeAlphamaps != null)
    107.             {
    108.                 OnAfterChangeAlphamaps(new AlphamapData(minY, minX, alphaMaps));
    109.             }
    110.  
    111.             // notify listeners that the level data was changed
    112.             if (LE_EventInterface.OnChangeLevelData != null)
    113.             {
    114.                 LE_EventInterface.OnChangeLevelData(this, new LE_LevelDataChangedEvent(LE_ELevelDataChangeType.TERRAIN_ALPHAMAPS));
    115.             }
    116.         }
     
    Last edited: Sep 6, 2023
  17. FPVFreerider

    FPVFreerider

    Joined:
    Jun 8, 2015
    Posts:
    8
    Thanks! I'm glad you were able to quickly find a solution for the level loading. I tried your new code now and it works fine. Hope you will be able to find a solution for the terrain creation too without too much trouble.
     
  18. fenix012585

    fenix012585

    Joined:
    Dec 26, 2022
    Posts:
    8

    Hello, Yes! this fix worked for me to save/load the terrain as well. I look forward to future updates as well.
    Thank you again!
     
  19. FreebordMAD

    FreebordMAD

    Joined:
    Mar 15, 2013
    Posts:
    633
    @FPVFreerider , @fenix012585, I updated my post above. You need to replace a few more functions in LE_LogicTerrain and LE_TerrainManager. Everything should work now, there are a few more look ups in LE_SaveLoad, but they should work even with the old SplatPrototype calls. I will remove all deprecated references and push an update in the next few weeks.

    It would be great to know if it works for you now.
     
  20. FPVFreerider

    FPVFreerider

    Joined:
    Jun 8, 2015
    Posts:
    8
    I replaced the additional functions, and have been trying it tonight. I can happily confirm that everything is working here. (I am using Unity 2022.3.8f LTS) Thank you for the great support!
     
    FreebordMAD likes this.
  21. orville_redenbacher

    orville_redenbacher

    Joined:
    Sep 9, 2018
    Posts:
    34
    Can also confirm the posted functions work great in the latest 2022 LTS!
     
    FreebordMAD likes this.
  22. fenix012585

    fenix012585

    Joined:
    Dec 26, 2022
    Posts:
    8
    Hey, sorry for taking so long to respond, I had a hectic couple of days. The additional changes work as well and I look forward to any future updates.

    Thank you again!
     
    FreebordMAD likes this.
  23. mathi4975

    mathi4975

    Joined:
    Aug 14, 2018
    Posts:
    7
    Hi, I am trying to do this to allow user to select the type of player like male or female. I try going through the code but not able to figure out how to do it. Could you pls guide me along? Thanks alot.
     
  24. mathi4975

    mathi4975

    Joined:
    Aug 14, 2018
    Posts:
    7
    Hi, any update, help or kind support?
     
  25. mathi4975

    mathi4975

    Joined:
    Aug 14, 2018
    Posts:
    7
    Hi Could you please guide how is the environment in LE_ExampleDungeonEditorGame done? I tried going though but not able to find how is is spawned. Thanks.
     
  26. iAdam_G

    iAdam_G

    Joined:
    Jul 26, 2023
    Posts:
    1
    Hi everyone. Does this asset still work - especially on latest LTS? Any updates? Looks great but lack of updates is worrying.