如何通过脚本设置对象纹理?类Minecraft地形生成器纹理失效求助
Minecraft风格地形生成的方块纹理设置问题解决
我做了一个类似Minecraft的地形生成系统,想通过脚本给不同高度的方块设置对应纹理,但方块始终显示空白。尝试过用Cube预制体替代CreatePrimitive创建的方块(但预制体设置后无效),也试过把Block脚本的逻辑移到Chunk脚本里,都没解决问题。
Chunk 脚本
private Vector3 position; private int chunkSize; private Material blockMaterial; public float noiseScale = 0.1f; public float amplitude = 5.0f; public void Initialize(Vector3 position, int chunkSize, Material blockMaterial) { this.position = position; this.chunkSize = chunkSize; this.blockMaterial = blockMaterial; GenerateTerrain(); } void GenerateTerrain() { for (int x = 0; x < chunkSize; x++) { for (int z = 0; z < chunkSize; z++) { float perlinValue = Mathf.PerlinNoise((x + position.x) * noiseScale, (z + position.z) * noiseScale); float y = perlinValue * amplitude; // 增加地形高度随机性 for (int yBlock = 0; yBlock < y; yBlock++) { Vector3 blockPosition = new Vector3(x, yBlock, z); GameObject block = GameObject.CreatePrimitive(PrimitiveType.Cube); block.transform.parent = transform; block.transform.position = blockPosition + position; Block blockScript = block.AddComponent<Block>(); } } } }
Block 脚本
public string blockType; // 方块名称或标识符 public Texture grass; public Texture dirt; public Texture stone; void Start() { Renderer renderer = this.GetComponent<Renderer>(); SetTextures(); } void SetTextures() { float yPos = transform.position.y; if (yPos > 5) { GetComponent<Renderer>().material.mainTexture = grass; blockType = "grass"; } if (yPos <= 0) { GetComponent<Renderer>().material.mainTexture = stone; blockType = "stone"; } if (yPos > 0) { GetComponent<Renderer>().material.mainTexture = dirt; blockType = "dirt"; } }
问题原因及修复方案
1. 条件判断逻辑错误
当前SetTextures里的三个独立if会导致覆盖:当yPos > 5时,先设置grass纹理,但随后yPos > 0的条件也成立,会把纹理改成dirt,导致草方块永远显示为泥土。
修复:改用else if链式判断,确保每个高度区间只触发一次:
void SetTextures() { float yPos = transform.position.y; Renderer renderer = GetComponent<Renderer>(); if (yPos > 5) { renderer.material.mainTexture = grass; blockType = "grass"; } else if (yPos > 0) // 仅当yPos <=5时才进入这里 { renderer.material.mainTexture = dirt; blockType = "dirt"; } else // yPos <=0 { renderer.material.mainTexture = stone; blockType = "stone"; } }
2. Texture变量未赋值
grass、dirt、stone是public变量,但未在Inspector面板给Block组件拖入对应的纹理资源,导致变量为null,设置纹理后显示空白。
修复:
- 手动赋值:选中场景中任意Block对象,在Inspector的Block组件里,把对应纹理拖入
grass、dirt、stone字段。 - 动态加载:如果是批量生成的Block,可在Chunk脚本中从Resources文件夹加载纹理并赋值:
// 在Chunk的GenerateTerrain方法中,添加Block组件后赋值 Block blockScript = block.AddComponent<Block>(); blockScript.grass = Resources.Load<Texture>("Textures/grass"); blockScript.dirt = Resources.Load<Texture>("Textures/dirt"); blockScript.stone = Resources.Load<Texture>("Textures/stone");
(需将纹理放在Assets/Resources/Textures目录下)
3. 材质使用问题
CreatePrimitive创建的Cube默认使用内置Standard材质,直接修改mainTexture可能因材质渲染设置不生效;且每个方块创建材质实例会浪费性能,建议复用传入的blockMaterial。
修复:生成方块时给Renderer赋值传入的材质(创建实例避免修改共享材质):
GameObject block = GameObject.CreatePrimitive(PrimitiveType.Cube); block.transform.parent = transform; block.transform.position = blockPosition + position; // 复用传入的材质,创建实例避免影响其他方块 block.GetComponent<Renderer>().material = new Material(blockMaterial); Block blockScript = block.AddComponent<Block>();
4. 预制体无效问题
预制体为空大概率是因为未正确配置:
修复:
- 创建一个Cube对象,添加Block组件并拖入纹理资源,设置好材质。
- 将该Cube拖到Project窗口创建预制体。
- 在Chunk脚本中用
Instantiate替代CreatePrimitive:
// 在Chunk脚本中添加预制体字段 public GameObject blockPrefab; // 在GenerateTerrain中替换创建逻辑 GameObject block = Instantiate(blockPrefab, blockPosition + position, Quaternion.identity); block.transform.parent = transform;
最后在Inspector中给Chunk组件的blockPrefab拖入你的预制体。
内容的提问来源于stack exchange,提问作者jollyname
相关产品推荐
相关产品推荐

