程序树生成器中的问题 C# 统一

问题描述

我目前正在研究程序化地形生成器,但在我的场景中程序化生成树木时遇到了一个问题。 Unity 给了我一个错误,但我真的不知道如何解决这个问题。

unity error

这是我的世界生成器和树生成器的代码

世界生成

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

public class TerrainGenerator : MonoBehavIoUr
{

    [Serializefield]
    private int terrainWidthInChunks,terrainLengthInChunks;

    [Serializefield]
    private GameObject ChunkPrefab;

    [Serializefield]
    private float centreVertex,maxdistance;

    [Serializefield]
    private TreeGenerator treeGenerator;

    [Serializefield]
    private RiverGenerator riverGenerator;


    // Start is called before the first frame update
    void Start()
    {
        GenerateWorld ();

    }

    void GenerateWorld()
    {

        //gets the chunk dimensions from the chunk prefab
        Vector3 chunkSize = ChunkPrefab.GetComponent<MeshRenderer>().bounds.size;
        int terrainHeight = (int)chunkSize.z;
        int terrainWidth = (int)chunkSize.x;

        //Calculates the number of vertices of the chunk in each axis of the mesh
        Vector3[] terrainMeshVertices = ChunkPrefab.GetComponent<MeshFilter>().sharedMesh.vertices;
        int terrainHeightInVertices = (int)Mathf.Sqrt(terrainMeshVertices.Length);
        int terrainWidthInVertices = terrainHeightInVertices;
        float distanceBetweenVertices = (float)terrainHeight / (float)terrainHeightInVertices;

        //builds an empty object to be filled with the terrain chunks that are generated on run-time
        WorldData worldData = new WorldData(terrainHeightInVertices,terrainWidthInVertices,this.terrainLengthInChunks,this.terrainWidthInChunks);

        //for each chunk we will want to instantiate a chunk in the correct position
        for (int x = 0; x < terrainWidthInChunks; x++)
        {

            for (int z = 0; z < terrainLengthInChunks; z++)
            {

                // calculates the chunk position based on x and z indices
                Vector3 chunkPosition = new Vector3(this.gameObject.transform.position.x + x * terrainWidth,this.gameObject.transform.position.y,this.gameObject.transform.position.z + z * terrainHeight);
                //instantiates new chunk
                GameObject Chunk = Instantiate(ChunkPrefab,chunkPosition,Quaternion.identity) as GameObject;

                //generates the chunk texture and stores it in ChunkData
                ChunkData chunkData = Chunk.GetComponent<TerrainchunkGenerator>().GenerateChunk(centreVertex,maxdistance);
                worldData.AddChunkData(chunkData,z,x);

            }

        }

        //generates trees for the world 
        treeGenerator.GenerateTrees(this.terrainLengthInChunks * terrainHeightInVertices,this.terrainWidthInChunks * terrainWidthInVertices,distanceBetweenVertices,worldData);

        //generates rivers for the world
        riverGenerator.GenerateRivers(this.terrainLengthInChunks * terrainHeightInVertices,worldData);

    }
}

//class to store merged chunk data
public class WorldData
{

    private int terrainHeightInVertices,terrainWidthInVertices;

    public ChunkData[,] chunksData;

    public WorldData(int terrainHeightInVertices,int terrainWidthInVertices,int terrainLengthInChunks,int terrainWidthInChunks)
    {

        //builds the chunkdata matrix based on terrain depth and width in verts and chunks
        chunksData = new ChunkData[terrainHeightInVertices * terrainLengthInChunks,terrainWidthInVertices * terrainWidthInChunks];

        this.terrainHeightInVertices = terrainHeightInVertices;
        this.terrainWidthInVertices = terrainWidthInVertices;

    }

    public void AddChunkData(ChunkData chunkData,int chunkZIndex,int chunkXIndex)
    {

        //saves the chunk data in the correct coordinates
        chunksData[chunkZIndex,chunkXIndex] = chunkData;

    }

    public ChunkCoordinate ConverttochunkCoordinate(int z,int x)
    {

        //the chunk index is calculates by dividing the index by yhr number of chunks in that axis
        int chunkZIndex = (int)Mathf.Floor((float)z / (float)this.terrainHeightInVertices);
        int chunkXIndex = (int)Mathf.Floor((float)x / (float)this.terrainWidthInVertices);
        //the coord index is calculated by aquiring the remainder of the division operation above
        //this translates te origin to the bottom left corner 
        int coordinateZIndex = this.terrainHeightInVertices - (z % this.terrainHeightInVertices) - 1;
        int coordinateXIndex = this.terrainWidthInVertices - (x % this.terrainWidthInVertices) - 1;

        ChunkCoordinate chunkCoordinate = new ChunkCoordinate(chunkZIndex,chunkXIndex,coordinateZIndex,coordinateXIndex);
        return chunkCoordinate;

    }

}

//class that represents a coordinate in the chunk coordinate System
public class ChunkCoordinate
{

    public int chunkZIndex;
    public int chunkXIndex;
    public int coordinateZIndex;
    public int coordinateXIndex;

    public ChunkCoordinate(int chunkZIndex,int chunkXIndex,int coordinateZIndex,int coordinateXIndex)
    {

        this.chunkZIndex = chunkZIndex;
        this.chunkXIndex = chunkXIndex;
        this.coordinateZIndex = coordinateZIndex;
        this.coordinateXIndex = coordinateXIndex;

    }


}

*tree generator*

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

public class TreeGenerator : MonoBehavIoUr
{

    [Serializefield]
    private NoisemapGenerator noisemapGenerator;

    [Serializefield]
    private Octave[] octaves;

    [Serializefield]
    private float terrainScale;

    [Serializefield]
    private float[] neighborRadius;

    [Serializefield]
    private GameObject[] treePrefab;

    public void GenerateTrees(int height,int width,float distanceBetweenVertices,WorldData worldData)
    {

        //Generates a tree noise map using the perlin noise function from noise map generator
        float[,] treeNoiseMap = this.noisemapGenerator.GeneratePerlinNoiseMap(height,width,this.terrainScale,this.octaves);

        float chunkSizeX = width * distanceBetweenVertices;
        float chunkSizeZ = height * distanceBetweenVertices;

        for (int z = 0; z < height; z++)
        {

            for (int x = 0; x < width; x++)
            {

                //converts from the world coord system to the chunk coord system and retreieves the chunkdata
                ChunkCoordinate chunkCoordinate = worldData.ConverttochunkCoordinate(z,x);
                ChunkData chunkData = worldData.chunksData[chunkCoordinate.chunkZIndex,chunkCoordinate.chunkXIndex];
                int chunkWidth = chunkData.heightMap.GetLength(1);

                //calculates the mesh vertex index
                Vector3[] meshVertices = chunkData.mesh.vertices;
                int vertexIndex = chunkCoordinate.coordinateZIndex * chunkWidth + chunkCoordinate.coordinateXIndex;

                //gets the terrain region of this coord
                TerrainRegion terrainRegion = chunkData.chosenHeightTerrainRegion[chunkCoordinate.coordinateZIndex,chunkCoordinate.coordinateXIndex];

                //gets the current biome of the coord
                Biome biome = chunkData.chosenBiomes[chunkCoordinate.coordinateZIndex,chunkCoordinate.coordinateXIndex];

                //check if the coord is "water" terrain. We obvIoUslt don't want trees to be placed within the water
                if (terrainRegion.name != "water")
                {

                    float treeValue = treeNoiseMap[z,x];

                    int terrainRegionIndex = terrainRegion.index;

                    //compares the current noise value to the neighbouring values
                    int neighborZBegin = (int)Mathf.Max(0,z - this.neighborRadius[biome.index]);
                    int neighborZEnd = (int)Mathf.Min(height-1,z + this.neighborRadius[biome.index]);
                    int neighborXBegin = (int)Mathf.Max(0,x - this.neighborRadius[biome.index]);
                    int neighborXEnd = (int)Mathf.Min(width - 1,x + this.neighborRadius[biome.index]);
                    float maxValue = 0f;
                    for (int neighborZ = neighborZBegin; neighborZ <= neighborZEnd; neighborZ++)
                    {

                        for (int neighborX = neighborXBegin; neighborX <= neighborXEnd; neighborX++)
                        {

                            float neighborValue = treeNoiseMap[neighborZ,neighborX];

                            //saves the max tree noise values in the radius
                            if (neighborValue >= maxValue)
                            {

                                maxValue = neighborValue;

                            }

                        }

                    }

                    //if the current trees nise value is the max of one then place a tree in that location
                    if (treeValue == maxValue)
                    {

                        Vector3 treePosition = new Vector3(x * distanceBetweenVertices,meshVertices[vertexIndex].y,z * distanceBetweenVertices);
                        GameObject tree = Instantiate(this.treePrefab[biome.index],treePosition,Quaternion.identity) as GameObject;
                        tree.transform.localScale = new Vector3(0.05f,0.05f,0.05f);
                        

                    }

                }

            }

        }

    }

}

解决方法

在 GenerateWorld() 方法中,我看到您正在使用 treeGenerator.GenerateTrees 方法,但我没有看到 treeGenerator 对象的任何初始化。这是您收到错误的地方。那么在使用之前需要对类对象进行初始化。

我认为您还需要初始化 riverGenerator 对象。