Search Unity

MapMagic 2 - infinite procedural land generator

Discussion in 'Assets and Asset Store' started by Wright, Apr 24, 2020.

  1. Wright

    Wright

    Joined:
    Feb 26, 2013
    Posts:
    2,274
    Do you have some MapMagic specific issue, or looking for general scene optimization advice not related with MM, when using a lot of objects as trees?
     
  2. SSL7

    SSL7

    Joined:
    Mar 23, 2016
    Posts:
    349
    What does the Manual Node in Splines do? Is not listed in the wiki or Splines Manual

    What I m trying to do is having Manual POIs coordinates (like with a third party tool I used and trying to move out of it due to bugs), that interconnect, is this possible with the build-in MM2 splines? And do they work with biomes?

    There is also some more generators that are not explained in wiki:

    Floor, Merge, Push

    Also do you suggest il2cpp or mono builds?
     
    Last edited: Jan 13, 2024
  3. MrCream

    MrCream

    Joined:
    Oct 26, 2020
    Posts:
    7
    i woudlnt say specific to map magic lol im aware of oc culling and lods but the scene is large culling wont bake
     
  4. fati36

    fati36

    Joined:
    Jul 9, 2019
    Posts:
    2
    I was following the tutorial and noticed that orange circle for Lock feature is not appearing. Is there a way to turn on this because right now its becoming hard to align the area.
     

    Attached Files:

  5. Wright

    Wright

    Joined:
    Feb 26, 2013
    Posts:
    2,274
    Might it be that your Lock Radius is 0? These two circles are drawing using the same approach, and there's no way to disable one but not the other. The only case I could reproduce it is to make zero radius.

    Well I guess there's a plenty of tutorials on optimizing open world scenes. IMHO occlusion culling won't be a big help here - trees can't occlude since they are usually see-through, stones won't cover much space, and terrain is not guaranteed to cover areas at all time that leads to floating FPS. Try looking into LODs - and, more important, Impostors.

    It's similar to the Positions node in Objects. Allows to input coordinates of the spline nodes manually. Positions node fit your use case - here you can type POI locations, then use Interlink to connect them. Spline system is not settled down, so probably something's missing in docs.

    I suggest bringing all the main calculations into a separate C++ libraries, and use mono to manage them. Possibly IL2CPP can be fast in some cases, but we have a real life example: MapMagic has the same code written both in C++ and C#, and we can compare the performance. For me IL2CPP is still 5 times slower than proper pure C++.
     
    Greviouss likes this.
  6. SSL7

    SSL7

    Joined:
    Mar 23, 2016
    Posts:
    349
    Thank you for your answer, so are splines work with biomes (I guess not yet?) and if not is it planned with a proper demo scene/documentation? Thank you
     
  7. NestorVG

    NestorVG

    Joined:
    Feb 12, 2019
    Posts:
    32
    Was the feature "tile clusters" (or something called like that) finished? I have been waiting on it for months but I haven't seen it added in the changelogs. It was a feature to share specific information among tile groups, such as monument locations and stuff like that (buildings, towns, etc. that are supposed to be rare and not repeat very often)

    I have been trying to find a way to use a scaled up map with huge tiles to find these locations that have gone through the "rarify" node and then apply those specific locations to the correct tiles, but I haven't managed to do it, and if I apply the same to the small tiles (128-256 units in size) they only count the rarify distance within themselves and the margin, but nothing more.
     
  8. Greviouss

    Greviouss

    Joined:
    May 27, 2016
    Posts:
    170
    I am actively working on a tile transfer between different resolution tiles.
    Ive asked Dennis to help me solve the 2 lines im stuck on, well see, and ill ping you on discord if :)
     
  9. Teren28

    Teren28

    Joined:
    Jan 15, 2024
    Posts:
    5
    Hello, i has a problem. When i build project for android, i has issue with terrain(on screenshot). I tried many ways to fix, but nothing help me. If i turn on Draw Instanced at Terrain Properties, my terrain disappears, and i walking on air.
    At editor all works fine.
    upload_2024-1-16_21-45-32.jpeg
     
  10. Greviouss

    Greviouss

    Joined:
    May 27, 2016
    Posts:
    170
    i know not nearly enough information to help you here,
     
  11. Teren28

    Teren28

    Joined:
    Jan 15, 2024
    Posts:
    5
    I fixed it. I switch from Texture To Heightmap to Set Heights Delay LOD, and map work correct
     
  12. jpileborg

    jpileborg

    Joined:
    Jan 5, 2013
    Posts:
    33
    Is it possible to create a looped world?

    For example you create a 8x8 set of tiles, and when the player moves of the "north" end the player is coming into the south end. Same with east and west of course.
     
  13. Wright

    Wright

    Joined:
    Feb 26, 2013
    Posts:
    2,274
    In most cases splines end up outputting terrain data like maps or object positions, and these work quite well with biomes.

    It's more an investigation rather than a clear plan of what to do. I've tried this and that, but still can't see a non-hacky way to implement it without changing core architecture. It is not released, but I still have a plan to make it - however can't 100% ensure you that I will.

    This sounds promising! Unfortunately can't help you right now, but I'm going to look into your code next weekend. Sorry for this delay.

    Nice find! Thank you for sharing it! Can't say exactly why does this happen - it seems to internal Unity stuff on applying height to terrain. I will add this to FAQ if you don't mind.

    Not out of the box - but I'm thinking of adding such a feature as "loop biome". Still it's just a plan, so no promise here.
     
    jpileborg likes this.
  14. jpileborg

    jpileborg

    Joined:
    Jan 5, 2013
    Posts:
    33
    That's fine, I have already thought about a work-around if it wasn't possible. Thanks.
     
  15. jpileborg

    jpileborg

    Joined:
    Jan 5, 2013
    Posts:
    33
    Another (stupid) question... Making different biomes blend seems rather easy, but only in a single direction (X or Z)?

    Lets say I have a map with 3x3 tiles. Along the three north tiles I want a mountain biome. With the linear blending it's no problem. But in the single center tile I want a meadow. East of it I want a forest, and to the west a swamp. In the south row I want a tropical jungle, a desert, and some sort of steppe.

    Is it possible to blend vastly different biomes in all directions?

    Perhaps use multiple biome blends, so I have one for each row (going east to west), and then another blend to blend the different rows in north to south?

    ---

    [Edit] I think I got a partial solution by reading the Wiki about the biomes set node, which shows an example of the snow plains used in the north and south end of the map, with a mix of the plain and badlands biomes in the middle.

    Unless someone have a straightforward answer or example to show, I'll experiment a little with this.

    And I'm still trying to make a single mountain stretch over multiple tiles (in a straight line) to make a mountain-range. Anyone have an idea about this? :)
     
    Last edited: Jan 21, 2024
  16. SteenPetersen

    SteenPetersen

    Joined:
    Mar 13, 2016
    Posts:
    103
    Hi I am spawning a bunch of stones and I would like them to 'sink' into the ground so they look like they have been there for a long time. Any idea how I would do this?

    Also is there some sort of documentation on writing our own nodes? I can't seem to find any information on it.

    EDIT -- Figured it out, I used the Adjust node to do it. Still curious as to any docs on how to create our own nodes. And infor on how to add aron granberg A* pathfinding if anyone has done that.
     
    Last edited: Jan 20, 2024
  17. Teren28

    Teren28

    Joined:
    Jan 15, 2024
    Posts:
    5
    I'm not sure if this is a completely working method, maybe it will help someone
     
  18. Greviouss

    Greviouss

    Joined:
    May 27, 2016
    Posts:
    170
    this was covered here on the forum in the last 2 weeks.... do some reading and you will find it im sure
     
  19. Greviouss

    Greviouss

    Joined:
    May 27, 2016
    Posts:
    170
    There is no straight forward easy answer to biomes.
     
  20. Greviouss

    Greviouss

    Joined:
    May 27, 2016
    Posts:
    170
    there is some documentation from dennis on this,
    also - check the discord, there are posts there that will get you started.
    also... try reading the existing code to get an idea of how the current generators exist
     
  21. unity_dev3194

    unity_dev3194

    Joined:
    Apr 17, 2017
    Posts:
    79
    @Wright Was the selector node variable exposure issue ever fixed? None of the variables available under the selector node can be exposed, the "variable" menu is grayed out when I right click on the node.
     
  22. apotheosix

    apotheosix

    Joined:
    Apr 7, 2023
    Posts:
    1
    Hi Denis,

    I just bought MapMagic 2 today and it’s been amazing so far. One question I have is about how to achieve random biome generation in an infinite world. I haven’t tried playing with the biome tool yet but from the YouTube video I saw it looks like the biomes have to be preset in the graph so you can’t have it randomly switch between biomes infinitely like Minecraft, for instance. Is there an easy way to accomplish this, making it so the infinite generation randomly selects biomes?
     
  23. Greviouss

    Greviouss

    Joined:
    May 27, 2016
    Posts:
    170
    not really, not without a custom node.
    If you find that easy, then ok yes...
     
  24. NestorVG

    NestorVG

    Joined:
    Feb 12, 2019
    Posts:
    32
    Try the whittaker node, just slap two noises into it and see what it generates. You can also make your own custom whittaker node, find more info about it in: https://gitlab.com/denispahunov/mapmagic/-/wikis/BiomesGenerators/Whittaker

    I think I will need to make my own custom whittaker node at some point as well, I will base it on the "pre-height" and a perlin noise for temperature, I will most likely want to have a custom amount of biomes since I will start having just a few and end up with many of them, some of which will have a very small chance of appearing, like the minecraft mushroom islands :D
     
  25. SteenPetersen

    SteenPetersen

    Joined:
    Mar 13, 2016
    Posts:
    103
    Hello,

    I'm currently facing a perplexing issue while building my game and would greatly appreciate any insights into what might be causing it. Everything appears to be properly connected, and the game runs smoothly in the editor. However, I'm encountering a "NullReferenceException: Object reference not set to an instance of an object" error. This issue arises within the MapMagic.Nodes.GUI.GeneratorDraw.DrawGeneratorOrPortal and other related functions. The error details are as follows:


    Code (CSharp):
    1. NullReferenceException: Object reference not set to an instance of an object
    2. MapMagic.Nodes.GUI.GeneratorDraw.DrawGeneratorOrPortal (MapMagic.Nodes.Generator gen, MapMagic.Nodes.Graph graph, System.Boolean isMini, System.Boolean selected, System.Boolean activeLinks) (at Assets/MapMagic/Nodes/Editor/GeneratorDraw.cs:56)
    3. MapMagic.Nodes.GUI.GraphWindow.DrawGraph () (at Assets/MapMagic/Nodes/Editor/GraphWindow.cs:363)
    4. ... [additional stack trace] ...
    5.  
    If you have any suggestions or experience with similar issues, your assistance would be greatly valued. Thank you in advance for your help.

    NullReferenceException: Object reference not set to an instance of an object MapMagic.Nodes.GUI.GeneratorDraw.DrawGeneratorOrPortal (MapMagic.Nodes.Generator gen, MapMagic.Nodes.Graph graph, System.Boolean isMini, System.Boolean selected, System.Boolean activeLinks) (at Assets/MapMagic/Nodes/Editor/GeneratorDraw.cs:56) MapMagic.Nodes.GUI.GraphWindow.DrawGraph () (at Assets/MapMagic/Nodes/Editor/GraphWindow.cs:363) Den.Tools.GUI.UI.Draw (System.Action drawAction, System.Boolean inInspector, UnityEngine.Rect customRect) (at Assets/MapMagic/Tools/GUI/Editor/UI.cs:259) MapMagic.Nodes.GUI.GraphWindow.OnGUI () (at Assets/MapMagic/Nodes/Editor/GraphWindow.cs:227) UnityEditor.HostView.InvokeOnGUI (UnityEngine.Rect onGUIPosition) (at <964670f15c6b47f9b8f9340732720473>:0) UnityEditor.DockArea.DrawView (UnityEngine.Rect dockAreaRect) (at <964670f15c6b47f9b8f9340732720473>:0) UnityEditor.DockArea.OldOnGUI () (at <964670f15c6b47f9b8f9340732720473>:0) UnityEngine.UIElements.IMGUIContainer.DoOnGUI (UnityEngine.Event evt, UnityEngine.Matrix4x4 parentTransform, UnityEngine.Rect clippingRect, System.Boolean isComputingLayout, UnityEngine.Rect layoutSize, System.Action onGUIHandler, System.Boolean canAffectFocus) (at <c3bffb462a5b404cb5d53d3f0e9b6f49>:0) UnityEngine.UIElements.IMGUIContainer.HandleIMGUIEvent (UnityEngine.Event e, UnityEngine.Matrix4x4 worldTransform, UnityEngine.Rect clippingRect, System.Action onGUIHandler, System.Boolean canAffectFocus) (at <c3bffb462a5b404cb5d53d3f0e9b6f49>:0) UnityEngine.UIElements.IMGUIContainer.DoIMGUIRepaint () (at <c3bffb462a5b404cb5d53d3f0e9b6f49>:0) UnityEngine.UIElements.UIR.RenderChainCommand.ExecuteNonDrawMesh (UnityEngine.UIElements.UIR.DrawParams drawParams, System.Single pixelsPerPoint, System.Exception& immediateException) (at <c3bffb462a5b404cb5d53d3f0e9b6f49>:0) Rethrow as ImmediateModeException UnityEngine.UIElements.UIR.RenderChain.Render () (at <c3bffb462a5b404cb5d53d3f0e9b6f49>:0) UnityEngine.UIElements.UIRRepaintUpdater.Update () (at <c3bffb462a5b404cb5d53d3f0e9b6f49>:0) UnityEngine.UIElements.VisualTreeUpdater.UpdateVisualTreePhase (UnityEngine.UIElements.VisualTreeUpdatePhase phase) (at <c3bffb462a5b404cb5d53d3f0e9b6f49>:0) UnityEngine.UIElements.Panel.UpdateForRepaint () (at <c3bffb462a5b404cb5d53d3f0e9b6f49>:0) UnityEngine.UIElements.Panel.Repaint (UnityEngine.Event e) (at <c3bffb462a5b404cb5d53d3f0e9b6f49>:0) UnityEngine.UIElements.UIElementsUtility.DoDispatch (UnityEngine.UIElements.BaseVisualElementPanel panel) (at <c3bffb462a5b404cb5d53d3f0e9b6f49>:0) UnityEngine.UIElements.UIElementsUtility.UnityEngine.UIElements.IUIElementsUtility.ProcessEvent (System.Int32 instanceID, System.IntPtr nativeEventPtr, System.Boolean& eventHandled) (at <c3bffb462a5b404cb5d53d3f0e9b6f49>:0) UnityEngine.UIElements.UIEventRegistration.ProcessEvent (System.Int32 instanceID, System.IntPtr nativeEventPtr) (at <c3bffb462a5b404cb5d53d3f0e9b6f49>:0) UnityEngine.UIElements.UIEventRegistration+<>c.<.cctor>b__1_2 (System.Int32 i, System.IntPtr ptr) (at <c3bffb462a5b404cb5d53d3f0e9b6f49>:0) UnityEngine.GUIUtility.ProcessEvent (System.Int32 instanceID, System.IntPtr nativeEventPtr, System.Boolean& result) (at <ff6b5db041e141f9a771d6b39c070602>:0) UnityEngine.GUIUtility:processEvent(Int32, IntPtr, Boolean&)
     
  26. Wright

    Wright

    Joined:
    Feb 26, 2013
    Posts:
    2,274
    Could you please email me you graph, your scene and their meta files (no additional assets needed)? I will look I to it this weekend. Any specific steps to reproduce will be be helpful.

    You can assign numerous biomes to biome set node - if the biome is not used on a tile it won't be generated. And to switch between biomes you can use any map, not only gradient - noise, for example.

    Switch Set Range to Min-Max. Transition mode is pure GUI extension, it transforms to min-max internally.

    This might help: Creating the custom node

    Yep, it's a right way to do it.

    You can feed any mask you like to biome set - not only gradient. Other simple form, or noise, or blend of horizontal and vertical gradients. For example, for center meadow simple form - cone with increased contrast will go.
     
    jpileborg likes this.
  27. SteenPetersen

    SteenPetersen

    Joined:
    Mar 13, 2016
    Posts:
    103
    Just sent an email.

    I've observed that disabling the MapMagic GameObject in the scene does not resolve the problem. Additionally, turning off the GPU instancer integration, either alone or in conjunction with disabling the MapMagic GameObject, also fails to rectify the issue.

    Interestingly, I've found that building the project without including that specific scene does not lead to the same problem. This observation might be crucial in pinpointing the root cause of the issue.

    I hope this information helps in troubleshooting the problem further. Please let me know if there's any other detail I can provide.

    --- EDIT


    I've found a workaround for the build errors with MapMagic. By keeping the 'MapMagic Graph' window/pane closed/shutdown during the build process, the errors are avoided. This method allows for successful, error-free builds. So that's something to look into I guess.

    However, I was focused on the errors during the build process, thinking they were causing the differences in how the world appears in the build compared to the editor. However, even after resolving the errors with the workaround, the world still looks significantly different in the build.

    I'm attaching some pictures to illustrate these differences. If anyone has insights or suggestions on what might be causing this discrepancy, your input would be greatly appreciated.




    Now I tried this: What would be causing Unity to make the lighting darker in build than in editor? It's URP. Editor is 2022.2.0b16 : r/Unity3D (reddit.com)

    • Basically they suggest adding a reflection probe to the scene, that didnt help
    • I also upgraded my project to 2022.3.18f1 as there was some suggestion that it was a bug in unity 2021.3 but this didnt help either (I needed to upgrade the project regardless for other reasons so I had hoped it would fix this)

    Ok I figured this out, for some reason the default quality settings of the gakme had been reset to very low, changing that to Ultra, fixed the issue: Edit -> Project settings -> quality

     
    Last edited: Jan 24, 2024
  28. Skyewee

    Skyewee

    Joined:
    Jul 28, 2020
    Posts:
    15
    https://imgur.com/a/iB0FNSH
    Hey, I'm having this problem with the trees node, where the normal option doesn't work. Works fine for objects though. (I don't want to use this for actual trees but things like leaves on the ground)
    Any solution?
     
    Last edited: Jan 24, 2024
  29. SteenPetersen

    SteenPetersen

    Joined:
    Mar 13, 2016
    Posts:
    103
    I am currently reading the Documentation and setting up biome identification, I have been relatively successful with this and from reading about DirectMatrices I have learned quite a bit about how I can identify which biome I am in. For those interested I have the temporary script I made as a spoiler at the bottom of this post.

    I have a question however, as I was testing my script I was curious what would happen when I have 3 or more biomes, and I ran into some issues when I was deciding to make a 'sea' or 'ocean' biome. My thought was to simply mix 'n' amount of biomes together, let's say I wanted 8 biomes in a large world, and then overlay the 'sea' or 'ocean' over that.

    But this was not giving me the results that I expected, and I am finding it non-intuitive. I like the diagram you make here:



    But this doesn't tell me how I would go about having a large amount n=8 biomes and having a sea or ocean at the same time. If anyone, possibly @Wright himself could show me the concept of how one would go about doing that, I would be grateful. then I could properly update the script to work with that and share it here again.


    using UnityEngine;
    using MapMagic.Terrains;

    /// <summary>
    /// BiomeID uses MapMagic's DirectMatrices to determine the current biome the player is in,
    /// based on two different layers (e.g., 'brown' and 'green'). The script optimizes performance
    /// by reducing the frequency of expensive operations and caching relevant data.
    /// </summary>
    public class BiomeID : MonoBehaviour
    {
    public string biomeLayer1 = "green";
    public string biomeLayer2 = "brown";
    public string biomeLayer3 = "ocean";

    private DirectMatricesHolder _currentHolder;
    private readonly float _checkInterval = 2f; // Time in seconds between checks
    private float _nextCheckTime = 0f;

    private TMPro.TextMeshProUGUI _biomeIDText;

    private void Start()
    {
    // this is the text that will display the biomeID in the UI
    _biomeIDText = GameObject.Find("BiomeID").GetComponent<TMPro.TextMeshProUGUI>();

    // Log an error if the biomeIdText is not found
    if (_biomeIDText == null)
    {
    Debug.LogError("BiomeID: biomeIDText not found! has it been renamed or moved?");
    }
    }

    private void Update()
    {
    // Limit the check to certain intervals to optimize performance
    if (!(Time.time >= _nextCheckTime)) return;
    UpdateCurrentHolder();
    _nextCheckTime = Time.time + _checkInterval;
    }

    /// <summary>
    /// Updates the current biome holder and determines the biome based on the player's position.
    /// </summary>
    private void UpdateCurrentHolder()
    {
    var playerPosition = transform.position;
    _currentHolder = FindHolder(playerPosition.x, playerPosition.z);

    if (_currentHolder == null) return;

    float biome1Value = _currentHolder.ValueAtPosition(biomeLayer1, playerPosition);
    float biome2Value = _currentHolder.ValueAtPosition(biomeLayer2, playerPosition);
    float biome3Value = _currentHolder.ValueAtPosition(biomeLayer3, playerPosition);

    Debug.Log("Biome1: " + biome1Value + " Biome2: " + biome2Value + " Biome3: " + biome3Value);

    // Determine which biome the player is currently in based on the biome values
    if (biome1Value > biome2Value && biome1Value > biome3Value)
    {
    _biomeIDText.text = biomeLayer1;
    }
    else if (biome2Value > biome1Value && biome2Value > biome3Value)
    {
    _biomeIDText.text = biomeLayer2;
    }
    else if (biome3Value > biome1Value && biome3Value > biome2Value)
    {
    _biomeIDText.text = biomeLayer3;
    }
    else
    {
    _biomeIDText.text = "unknown";
    }
    }

    /// <summary>
    /// Finds the relevant DirectMatricesHolder based on the player's current world position.
    /// It first checks if the current holder is still valid to minimize the use of FindObjectsOfType.
    /// </summary>
    /// <param name="x">X coordinate of the player's position.</param>
    /// <param name="z">Z coordinate of the player's position.</param>
    /// <returns>The found DirectMatricesHolder or null if not found.</returns>
    private DirectMatricesHolder FindHolder(float x, float z)
    {
    // Check if the current holder still contains the player's position
    if (_currentHolder != null && _currentHolder.ContainsPosition(x, z))
    {
    return _currentHolder;
    }

    // If not, find a new holder that contains the player's position
    DirectMatricesHolder[] holders = GameObject.FindObjectsOfType<DirectMatricesHolder>();
    foreach (DirectMatricesHolder holder in holders)
    {
    if (holder.ContainsPosition(x, z))
    return holder;
    }

    return null;
    }
    }
     
  30. Greviouss

    Greviouss

    Joined:
    May 27, 2016
    Posts:
    170
    yea its not as easy as youd think to make biomes......

    sure random poop on the canvas is easy, but structured biomes that dont look like poop on a canvas requires you to generate custom rules for them to exist by...
     
  31. Wright

    Wright

    Joined:
    Feb 26, 2013
    Posts:
    2,274
    Good find in general, in case someone will have a build result different from editor. Thanks for sharing it!

    Well, Unity terrain trees are thing on it's own. Even if you provide a rotation for some tree types it doesn't guarantee the tree will be rotated. MM might be setting the trees rotated, but Unity still will will draw them without rotation. For example, rotation is not supported for the trees that will work with impostor LODs (aka 'billboard trees'). It's hard to say whether the tree will work as impostor or regular object, and as far as I remember Unity had no clear documentation on this. In my experience a tree prefab with child sub-objects won't switch to impostor. It also might depend on a shader or other factors.

    Biomes Set node blends biomes like Textures output, i.e. it has Normalize node built-in. It blends layers one-by-one from bottom to top, in Photoshop-like manner. Each top layer is applied atop of the previous ones. Here is a more detailed explanation.

    So, if you have a biome with white mask on top it will completely remove all the previous biomes. This is what probably happens with your ocean biome. It's not possible to read the height for applying biome (to fill only lowlands with sea) - just because biome can change the height, and after the height is changed all other biomes should be re-applied. This will cause an infinite loop. The basic concept is that biomes are independent graphs, that work on their own if being applied in MM directly, without Biomes Set. They can share same base height nodes, it can be even brought to Function node to make it instance, but they can't receive information from other biomes.
     
  32. Wright

    Wright

    Joined:
    Feb 26, 2013
    Posts:
    2,274
    Hmm, oddly enough can't see anything with attached files recently. Other emails work, though, test email to myself too.

    Has someone else sent me an email and got no answer at this moment?
     
  33. Greviouss

    Greviouss

    Joined:
    May 27, 2016
    Posts:
    170
    heh
    it would go a really long way if you were semi sort of available in the discord server that the people who need the help are in.
     
  34. Wright

    Wright

    Joined:
    Feb 26, 2013
    Posts:
    2,274
    Semi-available... I'm afraid this will result in uncertainty for the questioner. I'd prefer to be a bit more reliable. Maybe it's not convenient to use email or write here in this thread, but if you do - I will answer (unless abovementioned technical problems occur). It doesn't mean that I always provide a comprehensive answer, but at least will write back in case there isn't any.
     
  35. SteenPetersen

    SteenPetersen

    Joined:
    Mar 13, 2016
    Posts:
    103
    I have been trying for a few days now to integrate digger pro into mapmagic 2, I'm at a point now where I pretty much give up. There is no support for Digger Pro anymore and I keep getting errors. So I Think I'm going to go back to my first idea and make my own, since all I want to do is raise/lower and flatten terrain. I don't need tunnels and caves really.

    I have 2 questions:

    1) How am I supposed to deal with the seams? I edit the terrain and I always get issues at the seams of the terrains? Surely this is something most people want to be able to do with Mapmagic in someway or other, does anyone have some advice to guide me in the correct direction?

    Code (CSharp):
    1. public class TerrainManipulator : MonoBehaviour
    2. {
    3.     public float radius = 2.0f;
    4.     public float strength = 0.1f;
    5.     public LayerMask terrainLayer;
    6.  
    7.     void Update()
    8.     {
    9.         if (Input.GetMouseButtonDown(0))
    10.         {
    11.             RaycastHit hit;
    12.             Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    13.  
    14.             if (Physics.Raycast(ray, out hit, Mathf.Infinity, terrainLayer))
    15.             {
    16.                 ModifyTerrain(hit.point, 0.01f); // Raise terrain
    17.             }
    18.         }
    19.         else if (Input.GetMouseButtonDown(1))
    20.         {
    21.             RaycastHit hit;
    22.             Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    23.  
    24.             if (Physics.Raycast(ray, out hit, Mathf.Infinity, terrainLayer))
    25.             {
    26.                 ModifyTerrain(hit.point, -0.01f); // Lower terrain
    27.             }
    28.         }
    29.     }
    30.  
    31. private void ModifyTerrain(Vector3 position, float value)
    32. {
    33.     Collider[] terrainColliders = Physics.OverlapSphere(position, radius, terrainLayer);
    34.  
    35.     foreach (Collider terrainCollider in terrainColliders)
    36.     {
    37.         Terrain terrain = terrainCollider.GetComponent<Terrain>();
    38.         if (terrain != null)
    39.         {
    40.             TerrainData terrainData = terrain.terrainData;
    41.             Vector3 terrainLocalPos = terrain.transform.InverseTransformPoint(position);
    42.             int mapX = (int)(terrainLocalPos.x / terrainData.size.x * terrainData.heightmapResolution);
    43.             int mapZ = (int)(terrainLocalPos.z / terrainData.size.z * terrainData.heightmapResolution);
    44.  
    45.             int mapRadius = Mathf.RoundToInt(radius / terrainData.size.x * terrainData.heightmapResolution);
    46.  
    47.             int startX = Mathf.Clamp(mapX - mapRadius, 0, terrainData.heightmapResolution - mapRadius * 2);
    48.             int startZ = Mathf.Clamp(mapZ - mapRadius, 0, terrainData.heightmapResolution - mapRadius * 2);
    49.             int width = Mathf.Min(mapRadius * 2, terrainData.heightmapResolution - startX);
    50.             int height = Mathf.Min(mapRadius * 2, terrainData.heightmapResolution - startZ);
    51.  
    52.             float[,] heightMap = terrainData.GetHeights(startX, startZ, width, height);
    53.  
    54.             for (int z = 0; z < heightMap.GetLength(1); z++)
    55.             {
    56.                 for (int x = 0; x < heightMap.GetLength(0); x++)
    57.                 {
    58.                     int worldX = x + startX;
    59.                     int worldZ = z + startZ;
    60.  
    61.                     float distance = Vector2.Distance(new Vector2(worldX, worldZ), new Vector2(mapX, mapZ)) / mapRadius;
    62.                     float falloff = 1 - Mathf.Clamp01(distance);
    63.  
    64.                     heightMap[z, x] += falloff * value * strength;
    65.                 }
    66.             }
    67.  
    68.             terrainData.SetHeights(startX, startZ, heightMap);
    69.         }
    70.     }
    71. }

    2) Is there anyway to get Mapmagic to repaint a specific area of the map (n.b. I'm using microsplat)? as in, when I dig, can I ask it to use a specific texture to make a "hole" or dirt, and then if I lower/raise something that the slopes that could result from that action would then be repainted immediately? I cant find any information on this in the documentation or here in this thread.

    Thank you.
     
  36. MonkeyPuzzle

    MonkeyPuzzle

    Joined:
    Jan 17, 2016
    Posts:
    119
    Hello - I am trying to integrate Map Magic with The Vegetation Engine. Is there a way to tie into the infinite terrain tiles to add an element programmatically?

    Here is a link showing how to add elements with their API to terrains, but I am not sure how I might do this with tiles that are added for infinite terrains. This element allows objects to form to the terrain. It works with the main terrain.

    https://docs.google.com/document/d/...nB_8Tbwloz8/edit?pli=1#heading=h.9dc6bmfp1sut

    Any thoughts are appreciated.
     
  37. Wright

    Wright

    Joined:
    Feb 26, 2013
    Posts:
    2,274
    For both points - take a look at the way MapMagic Brush works. It can edit multiple terrains without creating seams, and it also updates only the part of the terrain. It's editor-only tool though, but it uses editor features to display highlight mostly. The core mechanics should work in playmode.

    To be honest I don't know how this asset works, so can't help much with it. But I will try to support integration and will gladly answer all the specific questions that might arise.
     
  38. SteenPetersen

    SteenPetersen

    Joined:
    Mar 13, 2016
    Posts:
    103
    Thanks this was somewhat useful, I bought the Brush Asset and have played a bit with it, I can see that out of the box you can edit the world at runtime, however it will take me a long time, I think, to make a tool for editting the world. But i'll get there.

    However, I don't quite understand the texturing, I was hoping that as I edit the world, the local textures would update to the rules of the graph they live on, is that not possible? So say I raise the group, that create a slope, the graph wants texture_b on slopes above x, because I raised the group and now a slope exists above x it automatically applied texture_b.

    Also, I can make it all work but it doesnt seem to want to play nice with microsplat, are they not compatible?
     
  39. Wright

    Wright

    Joined:
    Feb 26, 2013
    Posts:
    2,274
    The Brush can do both height and texture modification. It all depends on the nodes you add to the brush graph. For example, you can combine Add preset with Slope or SlopeCavity to make it edit terrain and apply slopes and cavity textures to it. Theoretically you can even move the logic of the main graph that used to create initial terrain (with modifications to handle dynamic change and read-write).

    It cannot write to MicroSplat directly, but as far as I remember MS can automatically update on terrain splatmap change. Like for conventional terrain modification.
     
  40. MonkeyPuzzle

    MonkeyPuzzle

    Joined:
    Jan 17, 2016
    Posts:
    119
    That is great. Thank you. What I am looking for is a way to tie into the infinite terrain system. When a new terrain is added, I am hoping to incorporate the code from TVE to add a child object to the terrain. Is that something that sounds doable, and do you know where I might look to in the code to accomplish that?
     
  41. SteenPetersen

    SteenPetersen

    Joined:
    Mar 13, 2016
    Posts:
    103
    Hi I understand that I can make the brushes have as many features as I want, but Im having issues with updaitng the splatmaps.

    Currently I have altered your code slightly, to get an understanding of how to do this and in my script I call:

    /// <summary>
    /// Casts a ray to determine the terrain hit point and starts terrain modification.
    /// </summary>
    private void ProcessMouseDown()
    {
    var ray = _camera.ScreenPointToRay(Input.mousePosition);

    if (!Physics.Raycast(ray, out var hit, Mathf.Infinity, terrainLayer)) return;
    // Debug.DrawLine(ray.origin, hit.point, Color.green);

    var hitPoint = hit.point;
    brush.trace.StartRunTime(hitPoint, brush.Apply, brush);
    }
    I have only made small alteration so far to the trace.cs script:

    public void StartRunTime (Vector3 pos, Action<Vector3,bool> stampFn, MapMagicBrush brush)
    {
    // #if UNITY_EDITOR
    // if (Event.current.control)
    // { capturedPosition = pos; return; }
    // #endif

    isDrawing = true;
    framePoses.Add(pos);
    stampPoses.Add(pos);
    stampFn(pos,true); //StampBrush(pos);

    //applying changes to terrain on first click
    foreach (Terrain terrain in brush.terrains)
    {
    TerrainCache terrainCache = brush.terrainCaches[terrain];
    terrainCache.ApplyChanges(brush.cacheChange);
    }

    brush.cacheChange.Clear(); //after each apply
    }
    When I am done with the alteration, so on mouse up I am processing the release, syncing height maps and then I am attempting to Update the splat maps and then I have some temporay code to 'Sync' with microsplat, I will clean this up later. (Jason from microsplat said I'd need to sync, after any modification to the splatmaps)

    /// <summary>
    /// Releases the brush and updates all terrains' heightmaps.
    /// </summary>
    private void ProcessMouseUp()
    {
    brush.trace.Release(brush);
    Debug.Log("Mouse up");


    foreach (Terrain terrain in brush.terrains)
    {
    terrain.terrainData.SyncHeightmap();
    UpdateSplatmapsForTerrain(terrain);


    MicroSplatTerrain msTerrain = terrain.GetComponent<MicroSplatTerrain>();

    if (msTerrain != null)
    {
    msTerrain.Sync(); // This tells MicroSplat to update the textures based on current splatmaps
    }
    else
    {
    Debug.LogError("MicroSplatTerrain component not found on the terrain GameObject.");
    }

    }
    }
    Here is my Update UpdateSplatmapsForTerrain method, I don't know if I need to recreate the rules from the graph here in code, ideally id just like mapmagic to repaint the terrain at the location of the modification.

    private void UpdateSplatmapsForTerrain(Terrain terrain)
    {
    TerrainData terrainData = terrain.terrainData;
    int alphamapWidth = terrainData.alphamapWidth;
    int alphamapHeight = terrainData.alphamapHeight;
    float[,,] splatmapData = new float[alphamapWidth, alphamapHeight, terrainData.alphamapLayers];

    float terrainWidth = terrainData.size.x;
    float terrainHeight = terrainData.size.z;
    float terrainPosX = terrain.transform.position.x;
    float terrainPosZ = terrain.transform.position.z;

    for (int y = 0; y < alphamapHeight; y++)
    {
    for (int x = 0; x < alphamapWidth; x++)
    {
    // Normalize x/y coordinates to range 0-1
    float y_01 = (float)y / (float)alphamapHeight;
    float x_01 = (float)x / (float)alphamapWidth;

    // Calculate the normalized terrain coordinates that map to the x,y coordinates
    float normX = x_01 * terrainWidth + terrainPosX;
    float normZ = y_01 * terrainHeight + terrainPosZ;

    // Get the steepness of the terrain at this point
    float slope = terrainData.GetSteepness(x_01, y_01);

    // Initialize texture mix array with default values
    float[] textureMix = new float[terrainData.alphamapLayers];
    if (slope < 15)
    {
    textureMix[0] = 1; // Texture 0 for flat areas
    }
    else if (slope >= 15 && slope <= 30)
    {
    textureMix[1] = 1; // Texture 1 for moderate slopes
    }
    else
    {
    textureMix[2] = 1; // Texture 2 for steep slopes
    }

    // Normalize texture mix array
    float total = 0;
    for (int i = 0; i < textureMix.Length; i++)
    {
    total += textureMix;
    }
    for (int i = 0; i < textureMix.Length; i++)
    {
    textureMix /= total;
    splatmapData[x, y, i] = textureMix;
    }
    }
    }

    // Apply the modified splatmap data to the terrain
    terrainData.SetAlphamaps(0, 0, splatmapData);
    terrain.Flush();
    }
    However, all of this is not making any alterations to the textures. I am a bit lost.
     
  42. SteenPetersen

    SteenPetersen

    Joined:
    Mar 13, 2016
    Posts:
    103
    I all of a sudden started getting this issue as well, never had this issue before and now I am getting the same issue, every time I turn on 'Splats' or 'Both' I get this error, twice.

    - Deleting library folder did NOT help.
    - Creating a brand new Material from scratch DID help
     
    Last edited: Feb 4, 2024
  43. SteenPetersen

    SteenPetersen

    Joined:
    Mar 13, 2016
    Posts:
    103
    I am still playing around with the textures and getting it to draw now, but the textures are not coming out right where can I edit how the texture is drawn? I like the pixelated look, its what I'm going for, but the pixels are WAY too big. I have tried altering texture size, and the microsplat material, the Graph, the terrain layer object but it keeps drawing it this way. Any hint as to what I should look at?

    upload_2024-2-4_18-26-21.png

    Also I don't get how this updates, I changed the terrainlayer three places and it still paints with the gray color, am I missing something? Could really use some better documentation on how to use the Brush asset.
     
    Last edited: Feb 5, 2024
  44. SteenPetersen

    SteenPetersen

    Joined:
    Mar 13, 2016
    Posts:
    103
    Here is an image of the settings I change and still it pains with gray:

    upload_2024-2-5_9-11-28.png
     

    Attached Files:

  45. Greviouss

    Greviouss

    Joined:
    May 27, 2016
    Posts:
    170
    get the base microsplat asset and make your life easier
     
  46. SteenPetersen

    SteenPetersen

    Joined:
    Mar 13, 2016
    Posts:
    103
    I use the microsplat node and Microsplat, I don't have any features activated from microsplat at all, just a basic microsplat material as vanilla as can be.

    _____________________

    Here is my Brush Graph:

    I have tested in on Both microsplat terrain but also on a normal unity terrain, It raises the ground, but does not paint any slopes. Am I missing something? I tried to replicate the slope node exactly, I even tried to bring in a new 'Spot' node so that it literally was just the same two nodes in one.
     
    Last edited: Feb 6, 2024
  47. Wright

    Wright

    Joined:
    Feb 26, 2013
    Posts:
    2,274
    The brush first reads terrain, then makes calculations. So two of your Height Read nodes read the same flat terrain, and thus it's painted as flat, without slopes.

    Instead try used the modified height:
    upload_2024-2-6_20-1-59.png
     
    SteenPetersen and hopeful like this.
  48. SteenPetersen

    SteenPetersen

    Joined:
    Mar 13, 2016
    Posts:
    103
    Thank you Denis for that, you are correct and I had luckily figured that one out as well and it makes sense to me, I'm now trying to make the same Brush but where it will paint texture 1 on slopes from say 15 to 'Incline' and then texture 2 from 'Incline' to 90. There is issues however because it of course also has to be able to paint the original terrainLayer if it creates spaces that during an edit becomes above 15 but in a subsequent edit became below 15.

    But before being able to test that properly I am running into an issue with MicroSplat, which I have taken the liberty of writing up extensively as I have been working with it for hours and am at a loss, perhaps you can look into this an see if there is something wrong with the integration of these two assets. I have made the write up on my confluence so I have exported the detailed description of the problem and precise steps to reproduce it as a PDF (Attached to this message).

    Any help or insight would be greatly appreciated.
     

    Attached Files:

    Last edited: Feb 7, 2024
  49. Wright

    Wright

    Joined:
    Feb 26, 2013
    Posts:
    2,274
    To be honest I'm surprised it working, at least at some extend. Theoretically in brush graph you've got to output standard texture layers the way usual brushes do, and MS will then convert to it's own format on change.

    Just qurious, what will happen if you try to use the same graph as MM graph, not brush? Will this issue persist? And what if to try usual, non pixelated look?
     
  50. Greviouss

    Greviouss

    Joined:
    May 27, 2016
    Posts:
    170
    @Wright - is there a way to skip the draft draw when you go to draw a full hd tile?