我正在关注 b3agz 在 youtube 上关于如何统一制作我的世界和我的游戏崩溃的教程需要帮助

问题描述 投票:0回答:1

我正在按照 b3agz 的 Make Minecraft In Unity 3D 教程制作类似 minecraft 的游戏,我正在学习第 11 章 - 树,但我的代码使我的游戏崩溃。这里有很多代码只是为了让你们知道。本教程相当古老(准确地说是 3-4 年),所以它可能只是代码,可能不是,因为我使用的是最新的 unity 3d 版本,其他一切都运行良好。当我点击播放按钮时,我的整体崩溃了,我不得不再次打开它。这是 world.cs :

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

public class World : MonoBehaviour {
public int seed;
public BiomeAttributes biome;

public Transform player;
public Vector3 spawnPosition;

public Material material;
public Material transparentMaterial;

public BlockType[] blockTypes;

Chunk[,] chunks = new Chunk[VoxelData.WorldSizeInChunks, VoxelData.WorldSizeInChunks];

List<ChunkCoord> activeChunks = new List<ChunkCoord>();
public ChunkCoord playerChunkCoord;
ChunkCoord playerLastChunkCoord;

List<ChunkCoord> chunksToCreate = new List<ChunkCoord>();
List<Chunk> chunksToUpdate = new List<Chunk>();

bool applyingModifications = false;

Queue<VoxelMod> modifications = new Queue<VoxelMod>();

public GameObject debugScreen;

private void Start() {
    Random.InitState(seed);

    spawnPosition = new Vector3((VoxelData.WorldSizeInChunks * VoxelData.ChunkWidth) / 2f, VoxelData.ChunkHeight - 50f, (VoxelData.WorldSizeInChunks * VoxelData.ChunkWidth) / 2f);
    GenerateWorld();
    playerLastChunkCoord = GetChunkCoordFromVector3(player.position);
}

private void Update() {
    playerChunkCoord = GetChunkCoordFromVector3(player.position);

    if (!playerChunkCoord.Equals(playerLastChunkCoord))
        CheckRenderDistance();

    if(modifications.Count > 0 && !applyingModifications)
        StartCoroutine(ApplyModifications());

    if(chunksToCreate.Count > 0)
        CreateChunk();

    if(chunksToUpdate.Count > 0)
        UpdateChunks();

    if (Input.GetKeyDown(KeyCode.F3))
        debugScreen.SetActive(!debugScreen.activeSelf);
}

void GenerateWorld () {
    for (int x = (VoxelData.WorldSizeInChunks / 2) - VoxelData.RenderDistanceInChunks; x < (VoxelData.WorldSizeInChunks / 2) + VoxelData.RenderDistanceInChunks; x++) {
        for (int z = (VoxelData.WorldSizeInChunks / 2) - VoxelData.RenderDistanceInChunks; z < (VoxelData.WorldSizeInChunks / 2) + VoxelData.RenderDistanceInChunks; z++) {
            chunks[x, z] = new Chunk(new ChunkCoord(x, z), this, true);
            activeChunks.Add(new ChunkCoord(x, z));
        }
    }

    while(modifications.Count > 0) {
        VoxelMod v = modifications.Dequeue();
        ChunkCoord c = GetChunkCoordFromVector3(v.position);

        if(chunks[c.x, c.z] == null) {
            chunks[c.x, c.z] = new Chunk(c, this, true);
            activeChunks.Add(c);
        }

        chunks[c.x, c.z].modifications.Enqueue(v);

        if(!chunksToUpdate.Contains(chunks[c.x, c.z]))
            chunksToUpdate.Add(chunks[c.x, c.z]);
    }

    for (int i = 0; i < chunksToUpdate.Count; i++) {
        chunksToUpdate[0].UpdateChunk();
        chunksToUpdate.RemoveAt(0);
    }

    player.position = spawnPosition;
}

void CreateChunk () {
    ChunkCoord c = chunksToCreate[0];
    chunksToCreate.RemoveAt(0);
    activeChunks.Add(c);
    chunks[c.x, c.z].Init();
}

void UpdateChunks () {
    bool updated = false;
    int index = 0;

    while (!updated && index < chunksToUpdate.Count - 1) {
        if (chunksToUpdate[index].isVoxelMapPopulated) {
            chunksToUpdate[index].UpdateChunk();
            chunksToUpdate.RemoveAt(index);
            updated = true;
        }
        else
            index++;
    }
}

IEnumerator ApplyModifications () {
    applyingModifications = true;
    int count = 0;

    while (modifications.Count > 0) {
        VoxelMod v = modifications.Dequeue();
        ChunkCoord c = GetChunkCoordFromVector3(v.position);

        if (chunks[c.x, c.z] == null) {
            chunks[c.x, c.z] = new Chunk(c, this, true);
            activeChunks.Add(c);
        }

        chunks[c.x, c.z].modifications.Enqueue(v);

        if (!chunksToUpdate.Contains(chunks[c.x, c.z]))
            chunksToUpdate.Add(chunks[c.x, c.z]);

        count++;
        if (count > 110) {
            count = 0;
            yield return null;
        }
    }

    applyingModifications = false;
}

ChunkCoord GetChunkCoordFromVector3 (Vector3 pos) {
    int x = Mathf.FloorToInt(pos.x / VoxelData.ChunkWidth);
    int z = Mathf.FloorToInt(pos.z / VoxelData.ChunkWidth);
    return new ChunkCoord(x, z);
}

public Chunk GetChunkFromVector3 (Vector3 pos) {

    int x = Mathf.FloorToInt(pos.x / VoxelData.ChunkWidth);
    int z = Mathf.FloorToInt(pos.z / VoxelData.ChunkWidth);
    return chunks[x, z];

}

void CheckRenderDistance () {

    ChunkCoord coord = GetChunkCoordFromVector3(player.position);
    playerLastChunkCoord = playerChunkCoord;

    List<ChunkCoord> previouslyActiveChunks = new List<ChunkCoord>(activeChunks);

    for (int x = coord.x - VoxelData.RenderDistanceInChunks; x < coord.x + VoxelData.RenderDistanceInChunks; x++) {
        for (int z = coord.z - VoxelData.RenderDistanceInChunks; z < coord.z + VoxelData.RenderDistanceInChunks; z++) {

            if (IsChunkInWorld (new ChunkCoord (x, z))) {
                if (chunks[x, z] == null) {
                    chunks[x, z] = new Chunk(new ChunkCoord(x, z), this, false);
                    chunksToCreate.Add(new ChunkCoord(x, z));
                }  else if (!chunks[x, z].isActive) {
                    chunks[x, z].isActive = true;
                }
                activeChunks.Add(new ChunkCoord(x, z));
            }

            // Check through previously active chunks to see if this chunk is there. If it is, remove it from the list.
            for (int i = 0; i < previouslyActiveChunks.Count; i++) {

                if (previouslyActiveChunks[i].Equals(new ChunkCoord(x, z)))
                    previouslyActiveChunks.RemoveAt(i);

            }

        }
    }

    // Any chunks left in the previousActiveChunks list are no longer in the player's view distance, so loop through and disable them.
    foreach (ChunkCoord c in previouslyActiveChunks)
        chunks[c.x, c.z].isActive = false;

}

public bool CheckForVoxel (Vector3 pos) {

    ChunkCoord thisChunk = new ChunkCoord(pos);

    if (!IsChunkInWorld(thisChunk) || pos.y < 0 || pos.y > VoxelData.ChunkHeight)
        return false;

    if (chunks[thisChunk.x, thisChunk.z] != null && chunks[thisChunk.x, thisChunk.z].isVoxelMapPopulated)
        return blockTypes[chunks[thisChunk.x, thisChunk.z].GetVoxelFromGlobalVector3(pos)].isSolid;

    return blockTypes[GetVoxel(pos)].isSolid;

}

public bool CheckIfVoxelTransparent (Vector3 pos) {

    ChunkCoord thisChunk = new ChunkCoord(pos);

    if (!IsChunkInWorld(thisChunk) || pos.y < 0 || pos.y > VoxelData.ChunkHeight)
        return false;

    if (chunks[thisChunk.x, thisChunk.z] != null && chunks[thisChunk.x, thisChunk.z].isVoxelMapPopulated)
        return blockTypes[chunks[thisChunk.x, thisChunk.z].GetVoxelFromGlobalVector3(pos)].isTransparent;

    return blockTypes[GetVoxel(pos)].isTransparent;

}

public byte GetVoxel (Vector3 pos) {
    int yPos = Mathf.FloorToInt(pos.y);

    /* IMMUTABLE PASS */

    // If outside world, return air.
    if (!IsVoxelInWorld(pos))
        return 0;

    // If bottom block of chunk, return bedrock.
    if (yPos == 0)
        return 1;

    /* BASIC TERRAIN PASS */

    int terrainHeight = Mathf.FloorToInt(biome.terrainHeight * Noise.Get2DPerlin(new Vector2(pos.x, pos.z), 0, biome.terrainScale)) + biome.solidGroundHeight;
    byte voxelValue = 0;

    if (yPos == terrainHeight)
        voxelValue = 3;
    else if (yPos < terrainHeight && yPos > terrainHeight - 4)
        voxelValue = 5;
    else if (yPos > terrainHeight)
        return 0;
    else
        voxelValue = 2;

    /* SECOND PASS */

    if (voxelValue == 2) {
        foreach (Lode lode in biome.lodes) {
            if (yPos > lode.minHeight && yPos < lode.maxHeight)
                if (Noise.Get3DPerlin(pos, lode.noiseOffset, lode.scale, lode.threshold))
                    voxelValue = lode.blockID;
        }
    }

    /* TREE PASS */

    if (yPos == terrainHeight) {
        if (Noise.Get2DPerlin(new Vector2(pos.x, pos.z), 0f, biome.treeZoneScale) > biome.treeZoneThreshold) {
            voxelValue = 1;
            if (Noise.Get2DPerlin(new Vector2(pos.x, pos.z), 0f, biome.treePlacementScale) > biome.treePlacementThreshold)
                voxelValue = 8;
                Structure.MakeTree(pos, modifications, biome.minTreeHeight, biome.maxTreeHeight);
        }
    }

    return voxelValue;
}

bool IsChunkInWorld (ChunkCoord coord) {

    if (coord.x > 0 && coord.x < VoxelData.WorldSizeInChunks - 1 && coord.z > 0 && coord.z < VoxelData.WorldSizeInChunks - 1)
        return true;
    else
        return
            false;

}

bool IsVoxelInWorld (Vector3 pos) {

    if (pos.x >= 0 && pos.x < VoxelData.WorldSizeInVoxels && pos.y >= 0 && pos.y < VoxelData.ChunkHeight && pos.z >= 0 && pos.z < VoxelData.WorldSizeInVoxels)
        return true;
    else
        return false;

}
}

[System.Serializable]
public class BlockType {

public string blockName;
public bool isSolid;
public bool isTransparent;
public Sprite icon;

[Header("Texture Values")]
public int backFaceTexture;
public int frontFaceTexture;
public int topFaceTexture;
public int bottomFaceTexture;
public int leftFaceTexture;
public int rightFaceTexture;

// Back, Front, Top, Bottom, Left, Right

public int GetTextureID (int faceIndex) {

    switch (faceIndex) {

        case 0:
            return backFaceTexture;
        case 1:
            return frontFaceTexture;
        case 2:
            return topFaceTexture;
        case 3:
            return bottomFaceTexture;
        case 4:
            return leftFaceTexture;
        case 5:
            return rightFaceTexture;
        default:
            Debug.Log("Error in GetTextureID; invalid face index");
            return 0;


    }

}

}

public class VoxelMod {
public Vector3 position;
public byte id;

public VoxelMod () {
    position = new Vector3();
    id = 0;
}

public VoxelMod (Vector3 _position, byte _id) {
    position = _position;
    id = _id;
}
}

这是 chunk.cs:

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

public class Chunk {
public ChunkCoord coord;

GameObject chunkObject;
MeshRenderer meshRenderer;
MeshFilter meshFilter;

int vertexIndex = 0;

List<Vector3> vertices = new List<Vector3> ();
List<int> triangles = new List<int> ();
List<int> transparentTriangles = new List<int>();

Material[] materials = new Material[2];
List<Vector2> uvs = new List<Vector2> ();

public byte[,,] voxelMap = new byte[VoxelData.ChunkWidth, VoxelData.ChunkHeight, VoxelData.ChunkWidth];

public Queue<VoxelMod> modifications = new Queue<VoxelMod>();

World world;

private bool _isActive;
public bool isVoxelMapPopulated = false;

public Chunk (ChunkCoord _coord, World _world, bool generateOnLoad) {
    coord = _coord;
    world = _world;
    isActive = true;

    if (generateOnLoad)
        Init();
}

public void Init () {
    chunkObject = new GameObject();
    meshFilter = chunkObject.AddComponent<MeshFilter>();
    meshRenderer = chunkObject.AddComponent<MeshRenderer>();

    materials[0] = world.material;
    materials[1] = world.transparentMaterial;
    meshRenderer.materials = materials;

    chunkObject.transform.SetParent(world.transform);
    chunkObject.transform.position = new Vector3(coord.x * VoxelData.ChunkWidth, 0f, coord.z * VoxelData.ChunkWidth);
    chunkObject.name = "Chunk " + coord.x + ", " + coord.z;


    PopulateVoxelMap();
    UpdateChunk();
}

void PopulateVoxelMap () {

    for (int y = 0; y < VoxelData.ChunkHeight; y++) {
        for (int x = 0; x < VoxelData.ChunkWidth; x++) {
            for (int z = 0; z < VoxelData.ChunkWidth; z++) {

                voxelMap[x, y, z] = world.GetVoxel(new Vector3(x, y, z) + position);

            }
        }
    }

    isVoxelMapPopulated = true;
}

public void UpdateChunk () {
    while (modifications.Count > 0) {
        VoxelMod v = modifications.Dequeue();
        Vector3 pos = v.position -= position;
        voxelMap[(int)pos.x, (int)pos.y, (int)pos.z] = v.id;
    }

    ClearMeshData();

    for (int y = 0; y < VoxelData.ChunkHeight; y++) {
        for (int x = 0; x < VoxelData.ChunkWidth; x++) {
            for (int z = 0; z < VoxelData.ChunkWidth; z++) {

                if (world.blockTypes[voxelMap[x, y, z]].isSolid)
                    UpdateMeshData (new Vector3(x, y, z));

            }
        }
    }

    CreateMesh();

}

void ClearMeshData () {

    vertexIndex = 0;
    vertices.Clear();
    triangles.Clear();
    transparentTriangles.Clear();
    uvs.Clear();

}

public bool isActive {

    get { return _isActive; }
    set {

        _isActive = value;
        if (chunkObject != null)
            chunkObject.SetActive(value);

    }

}

public Vector3 position {

    get { return chunkObject.transform.position; }

}

bool IsVoxelInChunk (int x, int y, int z) {

    if (x < 0 || x > VoxelData.ChunkWidth - 1 || y < 0 || y > VoxelData.ChunkHeight - 1 || z < 0 || z > VoxelData.ChunkWidth - 1)
        return false;
    else
        return true;

}

public void EditVoxel (Vector3 pos, byte newID) {

    int xCheck = Mathf.FloorToInt(pos.x);
    int yCheck = Mathf.FloorToInt(pos.y);
    int zCheck = Mathf.FloorToInt(pos.z);

    xCheck -= Mathf.FloorToInt(chunkObject.transform.position.x);
    zCheck -= Mathf.FloorToInt(chunkObject.transform.position.z);

    voxelMap[xCheck, yCheck, zCheck] = newID;

    UpdateSurroundingVoxels(xCheck, yCheck, zCheck);

    UpdateChunk();

}

void UpdateSurroundingVoxels (int x, int y, int z) {

    Vector3 thisVoxel = new Vector3(x, y, z);

    for (int p = 0; p < 6; p++) {

        Vector3 currentVoxel = thisVoxel + VoxelData.faceChecks[p];

        if (!IsVoxelInChunk((int)currentVoxel.x, (int)currentVoxel.y, (int)currentVoxel.z)) {

            world.GetChunkFromVector3(currentVoxel + position).UpdateChunk();

        }

    }

}

bool CheckVoxel (Vector3 pos) {

    int x = Mathf.FloorToInt(pos.x);
    int y = Mathf.FloorToInt(pos.y);
    int z = Mathf.FloorToInt(pos.z);

    if (!IsVoxelInChunk(x, y, z))
        return world.CheckIfVoxelTransparent(pos + position);

    return world.blockTypes[voxelMap[x, y, z]].isTransparent;

}

public byte GetVoxelFromGlobalVector3 (Vector3 pos) {

    int xCheck = Mathf.FloorToInt(pos.x);
    int yCheck = Mathf.FloorToInt(pos.y);
    int zCheck = Mathf.FloorToInt(pos.z);

    xCheck -= Mathf.FloorToInt(chunkObject.transform.position.x);
    zCheck -= Mathf.FloorToInt(chunkObject.transform.position.z);

    return voxelMap[xCheck, yCheck, zCheck];

}

void UpdateMeshData (Vector3 pos) {

    byte blockID = voxelMap[(int)pos.x, (int)pos.y, (int)pos.z];

    bool isTransparent = world.blockTypes[blockID].isTransparent;

    for (int p = 0; p < 6; p++) { 

        if (CheckVoxel(pos + VoxelData.faceChecks[p])) {

            vertices.Add (pos + VoxelData.voxelVerts [VoxelData.voxelTris [p, 0]]);
            vertices.Add (pos + VoxelData.voxelVerts [VoxelData.voxelTris [p, 1]]);
            vertices.Add (pos + VoxelData.voxelVerts [VoxelData.voxelTris [p, 2]]);
            vertices.Add (pos + VoxelData.voxelVerts [VoxelData.voxelTris [p, 3]]);

            AddTexture(world.blockTypes[blockID].GetTextureID(p));

            if (!isTransparent) {
                triangles.Add (vertexIndex);
                triangles.Add (vertexIndex + 1);
                triangles.Add (vertexIndex + 2);
                triangles.Add (vertexIndex + 2);
                triangles.Add (vertexIndex + 1);
                triangles.Add (vertexIndex + 3);
            } else {
                transparentTriangles.Add (vertexIndex);
                transparentTriangles.Add (vertexIndex + 1);
                transparentTriangles.Add (vertexIndex + 2);
                transparentTriangles.Add (vertexIndex + 2);
                transparentTriangles.Add (vertexIndex + 1);
                transparentTriangles.Add (vertexIndex + 3);
            }

            vertexIndex += 4;

        }
    }

}

void CreateMesh () {

    Mesh mesh = new Mesh ();
    mesh.vertices = vertices.ToArray ();

    mesh.subMeshCount = 2;
    mesh.SetTriangles(triangles.ToArray(), 0);
    mesh.SetTriangles(transparentTriangles.ToArray(), 1);

    mesh.uv = uvs.ToArray ();

    mesh.RecalculateNormals ();

    meshFilter.mesh = mesh;

}

void AddTexture (int textureID) {

    float y = textureID / VoxelData.TextureAtlasSizeInBlocks;
    float x = textureID - (y * VoxelData.TextureAtlasSizeInBlocks);

    x *= VoxelData.NormalizedBlockTextureSize;
    y *= VoxelData.NormalizedBlockTextureSize;

    y = 1f - y - VoxelData.NormalizedBlockTextureSize;

    uvs.Add(new Vector2(x, y));
    uvs.Add(new Vector2(x, y + VoxelData.NormalizedBlockTextureSize));
    uvs.Add(new Vector2(x + VoxelData.NormalizedBlockTextureSize, y));
    uvs.Add(new Vector2(x + VoxelData.NormalizedBlockTextureSize, y + VoxelData.NormalizedBlockTextureSize));


}

}

public class ChunkCoord {

public int x;
public int z;

public ChunkCoord () {

    x = 0;
    z = 0;

}

public ChunkCoord (int _x, int _z) {

    x = _x;
    z = _z;

}

public ChunkCoord (Vector3 pos) {

    int xCheck = Mathf.FloorToInt(pos.x);
    int zCheck = Mathf.FloorToInt(pos.z);

    x = xCheck / VoxelData.ChunkWidth;
    z = zCheck / VoxelData.ChunkWidth;

}

public bool Equals (ChunkCoord other) {

    if (other == null)
        return false;
    else if (other.x == x && other.z == z)
        return true;
    else
        return false;

}

}

这些是主要的 2 个脚本,如果您需要更多,请告诉我。

c# unity3d
1个回答
0
投票

哦,所以我取消了评论,我让它工作了,谢谢。

© www.soinside.com 2019 - 2024. All rights reserved.