Digging Holes in the Ground and saving the Terrain

[I still didn’t let Object Pooling go. It’s just that I don’t know how to do it myself]

Alright moving on to a new topic. This one will be quite similar to other topics, so hopefully it won’t be much of a hassle to figure it out

If you can’t guess already, I’m talking about farming. Essentially, what I seek here, is a solution to create holes in the terrain during runtime (I’m not sure if it helps or not to mention that I’m currently using GAIA 2021 Pro), at a specific height, and be able to save that shape of the terrain

Saving? I think I can probably try figure this out on my own, but how do you dig holes in the ground through code?

It must also not be allowed where there’s a Nav Mesh Blocker (the last thing I want, is for my players to dig holes underwater)

I recently heard of “MicroSplat”, and was thinking of using this asset (not marketing anything here. To save you the click, it’s the “MicroSplat - Terrain Holes”) to do the digging into the ground, although I also have Synty’s Polygon Farm pack, and it seems to have multiple types of soil that might be enough for this task. I don’t know yet

We’re going to turn this into a Talk, as it is far far far far far away from course content, and relies entirely on paid assets. I don’t have the asset or the time, but if another student days, they may be able to help.

Fair enough. I’m trying to figure it out anyway :slight_smile: - I might even try creative solutions around it, but yeah let’s see what happens

Believe it or not, I never used the MicroSplat Shader that I bought for $5 :stuck_out_tongue: - I ended up writing my own Digging Script. First thing it did, was destroy everything, so I quickly gave up lol… Anyway, I’ll leave a copy of the early prototype here, if anyone wants to use it or modify it as they wish:

using UnityEngine;

public class TerrainDigger : MonoBehaviour 
{
    public Terrain terrain;
    public float digDepth = 1f;
    public float digRadius = 2f;

    private float[,] initialHeights;

    void Start() 
    {
        SaveInitialHeights();
    }

    void Update() 
    {
        if (Input.GetMouseButtonDown(0)) 
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out RaycastHit hit)) 
            {
                DigHole(hit.point);
            }
        }
    }

    void OnApplicationQuit() 
    {
        RestoreInitialHeights();
    }

    void SaveInitialHeights() 
    {
        TerrainData terrainData = terrain.terrainData;
        initialHeights = terrainData.GetHeights(0, 0, terrainData.heightmapResolution, terrainData.heightmapResolution);
    }

    void RestoreInitialHeights() 
    {
        TerrainData terrainData = terrain.terrainData;
        terrainData.SetHeights(0, 0, initialHeights);
    }

    void DigHole(Vector3 position) 
    {
        TerrainData terrainData = terrain.terrainData;
        Vector3 terrainPosition = position - terrain.transform.position;
        int x = (int)((terrainPosition.x / terrainData.size.x) * terrainData.heightmapResolution);
        int z = (int)((terrainPosition.z / terrainData.size.z) * terrainData.heightmapResolution);
        int radius = Mathf.RoundToInt(digRadius / terrainData.size.x * terrainData.heightmapResolution);

        float[,] heights = terrainData.GetHeights(x - radius, z - radius, radius * 2, radius * 2);
        
        for (int i = 0; i < heights.GetLength(0); i++) 
        {
            for (int j = 0; j < heights.GetLength(1); j++) 
            {
                heights[i, j] -= digDepth / terrainData.size.y;
            }
        }
        terrainData.SetHeights(x - radius, z - radius, heights);
    }
}

To use it, create an empty gameObject in your scene, place the script on it, adjust the values and assign it your terrain, and enjoy. It’s an early script though, so you’ll have to modify it on your own to your own needs

Because whatever you do to the terrain in the game remains in the scene as well (BE CAREFUL WITH THAT ONE), I also integrated a mini-saving script, so the Terrain returns to its original form when you return to edit mode. If you want to save and restore it in the game, you’ll have to use Brian’s JSON Saving System (or the Binary Saving System, whichever you’re using) for that

And now I got a mini taste of voxel-based work in the engine :stuck_out_tongue:

Anyway, I will go back to finding ways to integrate this script into my workflow. Enjoy the little gift (whoever reads this, that is)

OK this whole prototype is an absolute nightmare. I think I’ll do something insanely dumb, and use my Construction System as a portal to put soil and stuff around as well, since it can snap and seems like a decent object placement system

And for that portal, you’ll need a spade, rake or hoe (I still don’t fully remember what does what) to open it (already made them all anyway), and place stuff around

And just like how I do crafting, once it’s placed, it’ll open a menu where it can give you choices of what you want to farm, and save it and do all that jizz jazz over time

One potential problem I see, is how to get that stuff to change when the time hits. I have multi-sized food products that’ll need to change over time, but I think I can probably figure it out down the line

In the end, I’ll figure out how to introduce food eating into the game. I’m dead sure we did this before, but yeah I’ll have a second look down the line

Oh well, let’s start by deleting whatever I did so far as a starting point

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.

Privacy & Terms