最近按照这个教程:
https://www.bilibili.com/video/BV1Ag411m78d/?p=1&vd_source=1943ccc4ab0f1a5fef4ebc75f0c74544
准备用unity做一个简易的minec,但是出现了如图一下情况:
mesh上的texture会出现在距离较远情况下无法加载的问题(图中圈上的部分)
考虑过是图片精度的问题,但是检查了一下,图片确实是256*256像素的,每个素材没有任何偏移
找了半天原因都不知道是为什么
这些是代码,和教程中的几乎无改动:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Chunk
{
private byte abcdefghijklmnopqrstuvwxyz;//一个没用的变量,抢电脑内存用的,不用管
public ChunkCoord corrd;
public GameObject chunkObject;
public MeshRenderer meshrenderer;
public MeshFilter meshfilter;
public int vertexIndex = 0;
public List<Vector3> vertices = new List<Vector3>();
public List<int> triangles = new List<int>();
public List<Vector2> uvs = new List<Vector2>();//定义存储方块数据列表
public byte [,,]voxelMap = new byte [VorelData.chunkLength, VorelData.chunkHeight, VorelData.chunkWidth];//检查看不到的方块表面,并不绘制这些面,节省资源(参考VorelData.cs)
public world world;
public Chunk (ChunkCoord c_corrd, world w_world)
{
corrd = c_corrd;
chunkObject = new GameObject();
world = w_world;
meshfilter = chunkObject.AddComponent<MeshFilter>();
meshrenderer = chunkObject.AddComponent<MeshRenderer>();
meshrenderer.material = world.material;
chunkObject.transform.SetParent(world.transform);
chunkObject.transform.position = new Vector3(corrd.x * VorelData.chunkLength, 0.0f, corrd.z * VorelData.chunkWidth);
chunkObject.name = "Chunk" + corrd.x + "," + corrd.z;
PopulateVoxelMap();
CreateChunk();
CreateMesh();
}//world.cs中需要调用这些数据
public bool CheckVoxel(Vector3 pos)
{
int x = Mathf.FloorToInt(pos.x);
int y = Mathf.FloorToInt(pos.y);
int z = Mathf.FloorToInt(pos.z);
if((x < 0 || x > VorelData.chunkLength - 1) || (y < 0 || y > VorelData.chunkHeight - 1) || (z < 0 || z > VorelData.chunkWidth - 1))
{
return false;
}
else
{
return world.block[voxelMap[x, y, z]].isSolid;
}
}//不生成看不见的方块
public void CreateChunk()
{
for(int x = 0; x < VorelData.chunkLength; x++)
{
for(int y = 0; y < VorelData.chunkHeight; y++)
{
for(int z = 0; z < VorelData.chunkWidth; z++)
{
AddVoxelDataToChunk(new Vector3(x, y, z));
}
}
}//生成多个方块
}
public void PopulateVoxelMap()
{
for(int x = 0; x < VorelData.chunkLength; x++)
{
for(int y = 0; y < VorelData.chunkHeight; y++)
{
for(int z = 0; z < VorelData.chunkWidth; z++)
{
if(y == 0)
{
voxelMap[x, y, z] = 1;
}
else
{
if(y > 0 && y < VorelData.chunkHeight - 1)
{
voxelMap[x, y, z] = 2;
}
else
{
if(y == VorelData.chunkHeight - 1)
{
voxelMap[x, y, z] = 3;
}
else
{
voxelMap[x, y, z] = 0;
}
}
}
}
}
}
}//不同种类的的方块
public void AddVoxelDataToChunk(Vector3 pos)
{
for(int j = 0; j < 6; j++)
{
if(!CheckVoxel(pos + VorelData.faceCheck[j]))
{
byte blockID = voxelMap[(int)pos.x, (int)pos.y, (int)pos.z];
vertices.Add(pos + VorelData.voxelVerts[VorelData.voxelTris[j, 0]]);
vertices.Add(pos + VorelData.voxelVerts[VorelData.voxelTris[j, 1]]);
vertices.Add(pos + VorelData.voxelVerts[VorelData.voxelTris[j, 2]]);
vertices.Add(pos + VorelData.voxelVerts[VorelData.voxelTris[j, 3]]);
AddTextture(world.block[blockID].GetTextureId(j));//每个面加上对应的纹理
triangles.Add(vertexIndex);
triangles.Add(vertexIndex + 1);
triangles.Add(vertexIndex + 2);
triangles.Add(vertexIndex + 2);
triangles.Add(vertexIndex + 1);
triangles.Add(vertexIndex + 3);
vertexIndex += 4;
//将数据添加至列表
}//检测是否有不必要的面
}
}
public void CreateMesh()
{
Mesh mesh = new Mesh();
mesh.vertices = vertices.ToArray();
mesh.triangles = triangles.ToArray();
mesh.uv = uvs.ToArray();
mesh.RecalculateNormals();
meshfilter.mesh = mesh;//画出方块,每个面由两个三角组成(参考VorelData.cs)
}
public void AddTextture(int textureID)
{
float y = textureID / VorelData.textrueAtlasSizeInBlocks;
float x = textureID - (y * VorelData.textrueAtlasSizeInBlocks);
y *= VorelData.NormailzedBlockTextrueSize;
x *= VorelData.NormailzedBlockTextrueSize;//得到每个方块上纹理在总图片中的坐标
y = 1.0f - y - VorelData.NormailzedBlockTextrueSize;
uvs.Add(new Vector2(x + 0.001f, y + 0.001f));
uvs.Add(new Vector2(x + 0.001f, y + VorelData.NormailzedBlockTextrueSize - 0.001f));
uvs.Add(new Vector2(x + VorelData.NormailzedBlockTextrueSize - 0.001f, y + 0.001f));
uvs.Add(new Vector2(x + VorelData.NormailzedBlockTextrueSize - 0.001f, y + VorelData.NormailzedBlockTextrueSize - 0.001f));//使坐标从左上角开始计算,0.001是为了防止图片边缘与其他图片混合
}
}
public class ChunkCoord
{
public int x;
public int z;
public ChunkCoord(int x_x, int z_z)
{
x = x_x;
z = z_z;
}
}//建立每个chunk的坐标
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class world : MonoBehaviour
{
public Material material;
public Block[]block;
public void Start()
{
GenerateWorld();
}
public void GenerateWorld()
{
for(int i = 0; i < VorelData.worldSizeInChunk; i++)
{
for(int j = 0; j < VorelData.worldSizeInChunk; j++)
{
Chunk newChunk = new Chunk(new ChunkCoord(i, j), this);//连接到chunk,将Chunk.cs中的内容移动到这里并生成chunk
}
}
}
}//生成多个chunk
[System.Serializable]
public class Block
{
public string blockName;//方块名称
public bool isSolid;//判断是否为实体方块
[Header("Texture Values")]
public int backFaceTextTure;
public int frontFaceTextTure;
public int topFaceTextTure;
public int bottonFaceTextTure;
public int leftFaceTextTure;
public int rightFaceTextTure;//六个面不同的数据存放纹理
public int GetTextureId(int faceIndex)
{
switch(faceIndex)
{
case 0:
{
return backFaceTextTure;
}
case 1:
{
return frontFaceTextTure;
}
case 2:
{
return topFaceTextTure;
}
case 3:
{
return bottonFaceTextTure;
}
case 4:
{
return leftFaceTextTure;
}
case 5:
{
return rightFaceTextTure;
}
default:
{
Debug.Log("Error,faceIndex is " + faceIndex + ",it is not in scope.");
return 0;
}
}
}//每个面不同纹理
}//存储一个方块的所有数据
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public static class VorelData
{
public static readonly int chunkLength = 4;
public static readonly int chunkWidth = 4;
public static readonly int chunkHeight = 32;//地图大小
public static readonly int textrueAtlasSizeInBlocks = 16;//素材中的图片横竖分成七份
public static readonly int worldSizeInChunk = 16;
public static float NormailzedBlockTextrueSize
{
get
{
return 1.0f / (float)textrueAtlasSizeInBlocks;
}
}//每个图片的街区
public static readonly Vector3[] voxelVerts = new Vector3[8]
{
new Vector3(0.0f, 0.0f, 0.0f),
new Vector3(1.0f, 0.0f, 0.0f),
new Vector3(1.0f, 1.0f, 0.0f),
new Vector3(0.0f, 1.0f, 0.0f),
new Vector3(0.0f, 0.0f, 1.0f),
new Vector3(1.0f, 0.0f, 1.0f),
new Vector3(1.0f, 1.0f, 1.0f),
new Vector3(0.0f, 1.0f, 1.0f)//方块8个顶点坐标
};//存储每个方块的顶点数据的数组(在Chunk.cs中引用)
public static readonly Vector3[] faceCheck = new Vector3[6]
{
new Vector3(0.0f, 0.0f, -1.0f),
new Vector3(0.0f, 0.0f, 1.0f),
new Vector3(0.0f, 1.0f, 0.0f),
new Vector3(0.0f, -1.0f, 0.0f),
new Vector3(-1.0f, 0.0f, 0.0f),
new Vector3(1.0f, 0.0f, 0.0f)
};//检查看不到的方块表面,并不绘制这些面,节省资源(在Chunk.cs中引用)
public static readonly int[,] voxelTris = new int[6, 4]
{
{0, 3, 1, 2},
{5, 6, 4, 7},
{3, 7, 2, 6},
{1, 5, 0, 4},
{4, 7, 0, 3},
{1, 2, 5, 6}
};//一个正方体的面由两个三角组成,这里记录了两个三角绘制时需要的顶点(在Chunk.cs中引用)
public static readonly Vector2[] voxelUvs = new Vector2[4]
{
new Vector2(0.0f, 0.0f),
new Vector2(0.0f, 1.0f),
new Vector2(1.0f, 0.0f),
new Vector2(1.0f, 1.0f)
};//物体表面纹理的坐标
}