Why does it not Save?

I tried everything i found online (permissions, start as admin, deactivating antivirus, restarting, other locations, just “test” instead of data)

Somehow, it can create a folder, but not write a json to it. I try to add the code that is mentioned here.

UnauthorizedAccessException: Access to the path ‘C:\Users\Marvin\AppData\LocalLow\DefaultCompany\BlockGameClone\NoiseMap_Region_0_0’ is denied.
System.IO.FileStream…ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.Int32 bufferSize, System.Boolean anonymous, System.IO.FileOptions options) (at <8d5ef054c27c4b94bf100f8d26466ac6>:0)
System.IO.FileStream…ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.Int32 bufferSize, System.IO.FileOptions options) (at <8d5ef054c27c4b94bf100f8d26466ac6>:0)
(wrapper remoting-invoke-with-check) System.IO.FileStream…ctor(string,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare,int,System.IO.FileOptions)
System.IO.StreamWriter…ctor (System.String path, System.Boolean append, System.Text.Encoding encoding, System.Int32 bufferSize) (at <8d5ef054c27c4b94bf100f8d26466ac6>:0)
System.IO.StreamWriter…ctor (System.String path) (at <8d5ef054c27c4b94bf100f8d26466ac6>:0)
(wrapper remoting-invoke-with-check) System.IO.StreamWriter…ctor(string)
System.IO.File.WriteAllText (System.String path, System.String contents) (at <8d5ef054c27c4b94bf100f8d26466ac6>:0)
ChunkSaver.SavePerlinData (System.Single[,] noiseData, UnityEngine.Vector2Int noisePos) (at Assets/Scripts/ChunkSaver.cs:50)
WorldGenerator.GenerateBetaChunkNoiseData (UnityEngine.Vector3Int chunkPos) (at Assets/Scripts/WorldGenerator.cs:188)
WorldGenerator.GenerateBetaChunk (UnityEngine.Vector3Int chunkPos) (at Assets/Scripts/WorldGenerator.cs:99)
WorldGenerator.GenerateWorld () (at Assets/Scripts/WorldGenerator.cs:58)
WorldGenerator.Start () (at Assets/Scripts/WorldGenerator.cs:28)

ChunkSaver.cs

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;

public class ChunkSaver : MonoBehaviour
{

    public static ChunkSaver Instance;

    private void Awake()
    {
        Instance = this;
    }

    public string chunkDataSavePath = "/ChunkData_Region_";
    public string perlinNoiseMap = "/NoiseMap_Region_";

    public string worldName;

    private void Start()
    {
        worldName = GameController.Instance.worldName;
    }

    public void SaveChunkData(int[,,] blockData, Vector3Int chunkPos)
    {

        ChunkData chunkData = new ChunkData();

        chunkData.chunkPos = chunkPos;
        chunkData.chunkBlocks = blockData;

        string chunkSaveData = JsonUtility.ToJson(chunkData);
        DoesPathExistAndCreateIfDont(Application.persistentDataPath + "/" + worldName + "/" + chunkDataSavePath + chunkPos.x.ToString() + "_" + chunkPos.y.ToString() + "_" + chunkPos.z.ToString());
        File.WriteAllText(Application.persistentDataPath + "/" + worldName + "/" + chunkDataSavePath + chunkPos.x.ToString() + "_" + chunkPos.y.ToString() + "_" + chunkPos.z.ToString(), chunkSaveData);

    }

    public void SavePerlinData(float[,] noiseData, Vector2Int noisePos)
    {

        PerlinNoiseData noiseObject= new PerlinNoiseData();

        noiseObject.noisePos = noisePos;
        noiseObject.noiseData = noiseData;

        string noiseSaveData = JsonUtility.ToJson(noiseData);
        DoesPathExistAndCreateIfDont(Application.persistentDataPath + "/" + worldName + "/" + perlinNoiseMap + noisePos.x.ToString() + "_" + noisePos.y.ToString());
        File.WriteAllText(Application.persistentDataPath + "/" + worldName + "/" + perlinNoiseMap + noisePos.x.ToString() + "_" + noisePos.y.ToString(), noiseSaveData);

    }

    void DoesPathExistAndCreateIfDont(string path)
    {
        if (!Directory.Exists(path))
        {
            Directory.CreateDirectory(path);
        }
    }

    public bool DoesChunkExist(Vector3Int chunkPos)
    {
        return File.Exists(Application.persistentDataPath + "/" + worldName + "/" + chunkDataSavePath + chunkPos.x.ToString() + "_" + chunkPos.y.ToString() + "_" + chunkPos.z.ToString());
    }

    public bool DoesNoiseExist(Vector2Int noisePos)
    {
        return File.Exists(Application.persistentDataPath + "/" + worldName + "/" + perlinNoiseMap + noisePos.x.ToString() + "_" + noisePos.y.ToString());
    }

    public int[,,] LoadChunkBlockData(Vector3Int chunkPos)
    {
        if (DoesChunkExist(chunkPos))
        {
            return JsonUtility.FromJson<ChunkData>(File.ReadAllText(Application.persistentDataPath + "/" + worldName + "/" + chunkDataSavePath + chunkPos.x.ToString() + "_" + chunkPos.y.ToString() + "_" + chunkPos.z.ToString())).chunkBlocks;
        }
        else
        {
            return new int[VoxelData.chunkSize, VoxelData.chunkSize, VoxelData.chunkSize];
        }
    }

    public float[,] LoadPerlinData(Vector2Int noisePos)
    {
        if (DoesNoiseExist(noisePos))
        {
            return JsonUtility.FromJson<PerlinNoiseData>(File.ReadAllText(Application.persistentDataPath + "/" + worldName + "/" + perlinNoiseMap + noisePos.x.ToString() + "_" + noisePos.y.ToString())).noiseData;
        }
        else
        {
            return new float[VoxelData.chunkSize, VoxelData.chunkSize];
        }
    }
}

public class ChunkData
{
    public int[,,] chunkBlocks;
    //Mob Data
    public Vector3Int chunkPos;
}

public class PerlinNoiseData
{
    public float[,] noiseData;
    public Vector2Int noisePos;
}

WorldGenerator.cs

using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Collections;
using UnityEngine;
using UnityEngine.Experimental.AI;
using UnityEngine.Rendering;

public class WorldGenerator : MonoBehaviour
{

    public static Chunk[,,] worldChunks;

    public static int worldSizeChunks = 8;
    public static int worldChunkHeight = 4;

    public GameObject chunkPrefab;

    public Vector3[] perlinNoiseLevels;
    public Vector4 monolithNoiseLevels;

    private void Start()
    {
        System.DateTime timeStart = System.DateTime.Now;

        worldChunks = new Chunk[worldSizeChunks * 2, worldChunkHeight * 2, worldSizeChunks * 2];

        GenerateWorld();

        System.DateTime timeEnd = System.DateTime.Now;

        print("World Generation took : " + (timeEnd - timeStart).ToString());
    }

    void GenerateWorld()
    {
        int chunkOffset = -worldSizeChunks;
        int chunkHeightOffset = -worldChunkHeight;

        for (int x = 0; x < worldSizeChunks * 2; x++)
        {
            for (int y = 0; y < worldChunkHeight * 2; y++)
            {
                for (int z = 0; z < worldSizeChunks * 2; z++)
                {
                    worldChunks[x,y,z] = Instantiate(chunkPrefab, transform.position + new Vector3(x + chunkOffset,y + chunkHeightOffset,z + chunkOffset)
                        * VoxelData.chunkSize, Quaternion.identity).GetComponent<Chunk>();
                }
            }
        }

        for (int x = 0; x < worldSizeChunks * 2; x++)
        {
            for (int y = 0; y < worldChunkHeight * 2; y++)
            {
                for (int z = 0; z < worldSizeChunks * 2; z++)
                {
                    worldChunks[x, y, z].ReceiveChunkData(GenerateBetaChunk(new Vector3Int(x,y,z)));
                }
            }
        }
    }

    int[,,] GenerateAlphaChunk()
    {
        int[,,] chunkData = new int[VoxelData.chunkSize, VoxelData.chunkSize, VoxelData.chunkSize];
        int amountOfBlocks = BlockData.Instance.blockTypes.Length;

        for (int x = 0; x < VoxelData.chunkSize; x++)
        {
            for (int y = 0; y < VoxelData.chunkSize; y++)
            {
                for (int z = 0; z < VoxelData.chunkSize; z++)
                {
                    chunkData[x, y, z] = UnityEngine.Random.Range(0, amountOfBlocks);
                }
            }
        }

        return chunkData;
    }

    int[,,] GenerateBetaChunk(Vector3Int chunkPos) //in world Coordinates
    {
        float[,] perlinNoiseOut = new float[VoxelData.chunkSize, VoxelData.chunkSize];
        int[,,] outBlockData = new int[VoxelData.chunkSize, VoxelData.chunkSize, VoxelData.chunkSize];

        if (ChunkSaver.Instance.DoesChunkExist(chunkPos))
        {
            return ChunkSaver.Instance.LoadChunkBlockData(chunkPos);
        }
        else if (ChunkSaver.Instance.DoesNoiseExist(new Vector2Int(chunkPos.x, chunkPos.z)))
        {
            perlinNoiseOut = ChunkSaver.Instance.LoadPerlinData(new Vector2Int(chunkPos.x, chunkPos.z));
            outBlockData = GenerateBetaChunkData(perlinNoiseOut, chunkPos);
        }
        else
        {
            outBlockData = GenerateBetaChunkData(GenerateBetaChunkNoiseData(chunkPos), chunkPos);
        }
        

        ChunkSaver.Instance.SavePerlinData(perlinNoiseOut, new Vector2Int(chunkPos.x, chunkPos.z));

        ChunkSaver.Instance.SaveChunkData(outBlockData, chunkPos);

        return outBlockData;
    }

    int[,,] GenerateBetaChunkData(float[,] noiseData, Vector3Int chunkPos)
    {
        int[,,] chunkData = new int[VoxelData.chunkSize, VoxelData.chunkSize, VoxelData.chunkSize];
        int amountOfBlocks = BlockData.Instance.blockTypes.Length;
        int currentBlockHeight = 0;

        for (int y = 0; y < VoxelData.chunkSize; y++)
        {
            currentBlockHeight = y + chunkPos.y;
            for (int x = 0; x < VoxelData.chunkSize; x++)
            {
                for (int z = 0; z < VoxelData.chunkSize; z++)
                {
                    if(currentBlockHeight > noiseData[x, z])
                    {
                        if(currentBlockHeight < noiseData[x, z] + 3)
                        {
                            chunkData[x, y, z] = 1;
                        }else if(currentBlockHeight == noiseData[x, z] + 3)
                        {
                            chunkData[x, y, z] = 4;
                        }

                    }
                    else
                    {
                        chunkData[x, y, z] = 2;
                    }
                }
            }
        }

        return chunkData;
    }

    float[,] GenerateBetaChunkNoiseData(Vector3Int chunkPos)
    {
        float[,] perlinNoiseOut = new float[VoxelData.chunkSize, VoxelData.chunkSize];
        float currentPerlinAdd = 0f;

        //Basic Perlin Landscape

        for (int x = 0; x < VoxelData.chunkSize; x++)
        {
            for (int z = 0; z < VoxelData.chunkSize; z++)
            {
                foreach (Vector3 perlinValue in perlinNoiseLevels)
                {

                    currentPerlinAdd += Mathf.PerlinNoise((x + chunkPos.x - (int.MaxValue / 2)) * perlinValue.x, (z + chunkPos.z - (int.MaxValue / 2)) * perlinValue.y) * perlinValue.z; // Possible problem, minus to plus

                }

                perlinNoiseOut[x, z] = currentPerlinAdd;
            }
        }

        //Add Monoliths

        for (int x = 0; x < VoxelData.chunkSize; x++)
        {
            for (int z = 0; z < VoxelData.chunkSize; z++)
            {
                currentPerlinAdd = Mathf.PerlinNoise(x + chunkPos.x - (int.MaxValue / 2) * monolithNoiseLevels.x, z + chunkPos.z - (int.MaxValue / 2)) * monolithNoiseLevels.z;

                if (currentPerlinAdd > monolithNoiseLevels.w)
                {
                    currentPerlinAdd *= monolithNoiseLevels.y;
                }
                else
                {
                    currentPerlinAdd = 0f;
                }

                perlinNoiseOut[x,z] = currentPerlinAdd;
            }
        }

        ChunkSaver.Instance.SavePerlinData(perlinNoiseOut, new Vector2Int(chunkPos.x, chunkPos.z));

        return perlinNoiseOut;
    }

}

Are you forgetting a file extension?

1 Like

Yes, my stupid *** did…

Also, i created a folder in the same manor as the files and i think Windows doesn’t like it when i try to write to a folder as it were a file…

It doesn’t work all the way atm, but i will work a bit further.

Thank you for the unbelievably fast answer!

Yes, you can’t write to a folder as if it were a file. You can only write files into an existing directory.

That was a Brainfart of mine. Just seen that i need to create a folder and just copied the path.

Believe it or not, but my actual profession is an IT-Technician, with a 3-Year “apprentice” (I live in Germany and learned my profession by the “duale ausbildung” way), wich makes it extra emberessing.

Not at all… we all brainfart. Embrace the brainfart! Even simple stuff like this has a lot of moving parts that all sound the same.

The best solution I’ve found is relentlessly going over every step of a process: print every filename, print every variable, attach the debugger, breakpoint it, study what the data is…

And if I’m finally stumped, I like to open Notepad++ and start writing out my issue, copying snippets of code in, looking up API documentation links, copy/pasting the specific API info into the Notepad++ doc as I’m building up my post… explaining it to my dog (see my avatar picture) and then almost always I realize… oh… there’s my brainfart. Found it.

1 Like