0

I'm trying to make a minecraft like game and myscript throws a NullReferenceException for some reason when i'm generating UVs for my Block. I've tried to change some variables but it didn't help.

BlockType.cs:

public class BlockType
{
    public string name { get; private set; }
    public bool isTransparent { get; private set; }
    public bool everySideSame { get; private set; }

    public Vector2[] topUV { private get; set; }
    public Vector2[] sideUV { private get; set; }
    public Vector2[] bottomUV { private get; set; }

    public List<Vector2[]> blocktypeUVs = new List<Vector2[]>();

    public BlockType(string name, bool isTransparent, bool everySideSame)
    {
        this.name = name;
        this.isTransparent = isTransparent;
        this.everySideSame = everySideSame;
    }
    public Vector2[] getUV(Block.BlockSide side)
    {
        if (everySideSame||(side!=Block.BlockSide.Top&&side!=Block.BlockSide.Bottom))
            return sideUV;

        if (side == Block.BlockSide.Top)
            return topUV;
        else
            return bottomUV;
    }
    public void GenerateUVs()
    {
        if (sideUV.Length>0)
            this.blocktypeUVs.Add(new Vector2[4] { sideUV[3], sideUV[2], sideUV[0], sideUV[1] });
        if (topUV.Length > 0)
        {
            this.blocktypeUVs.Add(new Vector2[4] { topUV[3], topUV[2], topUV[0], topUV[1] });
        }
        if (bottomUV.Length>0)
        {
            this.blocktypeUVs.Add(new Vector2[4] { bottomUV[3], bottomUV[2], bottomUV[0], bottomUV[1] });
        }
    }
    public Vector2[] getBlockUVs(Block.BlockSide side)
    {
        if (everySideSame || (side != Block.BlockSide.Top && side != Block.BlockSide.Bottom))
            return blocktypeUVs[0];

        if (side == Block.BlockSide.Top)
            return blocktypeUVs[1];
        else
            return blocktypeUVs[2];
    }
}

World.cs Code:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;


class World:MonoBehaviour
{
    Material blockMaterial;
    public Texture2D[] atlasTexture;
    public static Dictionary<string, Rect> atlasDictionary = new Dictionary<string, Rect>();
    public static Dictionary<string, Chunk> chunks = new Dictionary<string, Chunk>();
    public int chunkSize = 16;
    public int columnHeight = 16;
    public int worldSize = 5;
    public static List<BlockType> blockTypes = new List<BlockType>();

    private void Start()
    {

        Texture2D atlas = GetTextureAtlas();
        Material material = new Material(Shader.Find("Standard"));
        material.mainTexture = atlas;
        blockMaterial = material;
        GenerateBlockType();
        GenerateWorld();
        StartCoroutine(BuildWorld());
    }
    IEnumerator BuildWorld()
    {
        foreach (KeyValuePair<string,Chunk> chunk in chunks )
        {
            chunk.Value.DrawChunk(chunkSize);
            yield return null;
        }

    }
    void GenerateWorld()
    {
        for (int z = 0; z < worldSize; z++)
        {
            for (int x = 0; x < worldSize; x++)
            {
                for (int y = 0; y < columnHeight; y++)
                {
                    Vector3 chunkposition = new Vector3(x * chunkSize, y * chunkSize, z * chunkSize);
                    string chunkName = GetChunkName(chunkposition);
                    Chunk chunk = new Chunk(chunkName, chunkposition, blockMaterial);
                    chunk.chunkObject.transform.parent = transform;
                    chunks.Add(chunkName, chunk);
                }
            }
        }
    }

    void GenerateBlockType()
    {
        BlockType dirt = new BlockType("dirt", false, true);
        dirt.sideUV = setUVS("dirt");
        print(dirt.getUV(Block.BlockSide.Left));
        dirt.GenerateUVs();
        blockTypes.Add(dirt);

        BlockType grass = new BlockType("grass", false, false);
        grass.topUV = setUVS("grass");
        grass.sideUV = setUVS("grass_side");
        grass.bottomUV = setUVS("dirt");
        print(grass.getUV(Block.BlockSide.Top));
        grass.GenerateUVs();
        blockTypes.Add(grass);

        BlockType brick = new BlockType("brick", false, true);
        brick.sideUV = setUVS("brick");
        print(brick.getUV(Block.BlockSide.Left));
        brick.GenerateUVs();
        blockTypes.Add(brick);

        BlockType air = new BlockType("air", true, true);
        air.sideUV = setUVS("air");
        print(air.getUV(Block.BlockSide.Left));
        air.GenerateUVs();
        blockTypes.Add(air);
    }
    Vector2[] setUVS(string name)
    {
        if (name=="air")
        {
            return  new Vector2[4] {
                    new Vector2(0, 0),
                    new Vector2(1, 0),
                    new Vector2(0, 1),
                    new Vector2(1, 1) 
            };
        }
        return new Vector2[4] {
                new Vector2(atlasDictionary[name].x,
                            atlasDictionary[name].y),

                new Vector2(atlasDictionary[name].x+atlasDictionary[name].width,
                            atlasDictionary[name].y),

                new Vector2(atlasDictionary[name].x,
                            atlasDictionary[name].y+atlasDictionary[name].height),

                new Vector2(atlasDictionary[name].x+atlasDictionary[name].width,
                            atlasDictionary[name].y+atlasDictionary[name].height),
                };

    }
    string GetChunkName(Vector3 position)
    {
        return (int)position.x+"_"+(int)position.y+"_"+(int)position.z;
    }
    Texture2D GetTextureAtlas()
    {
        Texture2D textureAtlas = new Texture2D(8192, 8192);
        Rect[] rectCoordinates = textureAtlas.PackTextures(atlasTexture, 0, 8192, false);
        textureAtlas.Apply();
        for (int i = 0; i < rectCoordinates.Length; i++)
        {
            atlasDictionary.Add(atlasTexture[i].name.ToLower(), rectCoordinates[i]);
        }
        return textureAtlas;
    }

}

It shows the error is exactly on this line in BlockType.cs:

this.blocktypeUVs.Add(new Vector2[4] { sideUV[3], sideUV[2], sideUV[0], sideUV[1] });

Please someone help me.

Bartek Dusza
  • 156
  • 8
  • What is the stacktrace of the exception? – Renat Mar 18 '20 at 10:44
  • NullReferenceException: Object reference not set to an instance of an object BlockType.GenerateUVs () (at Assets/skrypty/świat/generowanie świata/BlockType.cs:38) World.GenerateBlockType () (at Assets/skrypty/świat/generowanie świata/World.cs:63) World.Start () (at Assets/skrypty/świat/generowanie świata/World.cs:27) – Bartek Dusza Mar 18 '20 at 10:46
  • One of the arrays was not initialized, so has null value. Better to check for null. This may work: `public void GenerateUVs() { if (sideUV!=null && sideUV.Length>0)...; if (topUV!=null && topUV.Length > 0) {...} if (bottomUV!=null && bottomUV.Length>0){ ...}` – Renat Mar 18 '20 at 11:14
  • still getting NullReferenceException – Bartek Dusza Mar 18 '20 at 11:25
  • 1
    @Renat usually if you get an exception you should rather investigate why and fix the cause .. not silently ignore the failure ;) – derHugo Mar 18 '20 at 12:30
  • @BartekDusza `sideUV` and `topUV` and `bottomUV` are never assigned ... Also note: I never saw a usecase where you would allow public setting but only private getting of a property .. not even sure if this is allowed ^^ Usually you want to go the other way round – derHugo Mar 18 '20 at 12:34

0 Answers0