【问题标题】:In Unity3D, I am following a tilemap tutorial. However, the UV layout is coming out strange. How can I fix this?在 Unity3D 中,我正在关注一个 tilemap 教程。然而,UV 布局却显得很奇怪。我怎样才能解决这个问题?
【发布时间】:2015-11-07 00:50:41
【问题描述】:

我正在按照本教程集:https://www.youtube.com/watch?v=owBt9SNKXCI&index=6&list=PLbghT7MmckI4qGA0Wm_TZS8LVrqS47I9R 动态构建平铺地图布局。它在一定程度上起作用,但它会生成一个非常奇怪的布局,其中包含 128 x 128 大小的图块。

显然,奇怪的分区不应该发生,但我似乎无法追踪是什么原因导致它。这是我的代码版本,与 quill18creates 的版本基本相同,没有一些小差异:

using UnityEngine;
using System.Collections;

[ExecuteInEditMode]
public class TileMap : MonoBehaviour {

    public int size_x = 100;
    public int size_z = 50;
    public float tileSize = 1.0f;

    public Texture2D terrainTiles;
    int tileResolution = 128;

    // Use this for initialization
    void Start () {
        BuildMesh();
    }

    Color[][] ChopUpTiles() {
        int numTilesPerRow = terrainTiles.width / tileResolution;
        int numRows = terrainTiles.height / tileResolution;

        Color[][] tiles = new Color[numTilesPerRow*numRows][];

        for(int y=0; y < numRows; y++) {
            for(int x=0; x < numTilesPerRow; x++) {
                tiles[y * numTilesPerRow + x] = terrainTiles.GetPixels( x*tileResolution , y*tileResolution, tileResolution, tileResolution );
            }
        }

        return tiles;
    }

    void BuildTexture() {
        //DTileMap map = new DTileMap(size_x, size_z);

        int texWidth = size_x * tileResolution;
        int texHeight = size_z * tileResolution;
        Texture2D texture = new Texture2D(texWidth, texHeight);

        Color[][] tiles = ChopUpTiles();


        for(int y=0; y < size_z; y++) {
            for(int x=0; x < size_x; x++) {
                Color[] p = tiles[Mathf.RoundToInt(Random.Range(0, 5))];
                texture.SetPixels(x * tileResolution, y * tileResolution, tileResolution, tileResolution, p);
            }
        }

        //texture.filterMode = FilterMode.Bilinear;
        texture.wrapMode = TextureWrapMode.Clamp;
        texture.Apply();

        MeshRenderer mesh_renderer = GetComponent<MeshRenderer>();
        mesh_renderer.sharedMaterials[0].mainTexture = texture;
    }

    public void BuildMesh() {
        int numTiles = size_x * size_z;
        int numTris = numTiles * 2;

        int vsize_x = size_x + 1;
        int vsize_z = size_z + 1;
        int numVerts = vsize_x * vsize_z;

        // Generate the mesh data
        Vector3[] vertices = new Vector3[ numVerts ];
        Vector3[] normals = new Vector3[numVerts];
        Vector2[] uv = new Vector2[numVerts];

        int[] triangles = new int[ numTris * 3 ];

        int x, z;
        for(z=0; z < vsize_z; z++) {
            for(x=0; x < vsize_x; x++) {
                vertices[ z * vsize_x + x ] = new Vector3( x*tileSize, 0, -z*tileSize );
                normals[ z * vsize_x + x ] = Vector3.up;
                uv[ (z * vsize_x) + x ] = new Vector2( (float)x / size_x, (float)z / size_z );
            }
        }
        Debug.Log ("Done Verts!");

        for(z=0; z < size_z; z++) {
            for(x=0; x < size_x; x++) {
                int squareIndex = z * size_x + x;
                int triOffset = squareIndex * 6;
                triangles[triOffset + 0] = z * vsize_x + x +           0;
                triangles[triOffset + 2] = z * vsize_x + x + vsize_x + 0;
                triangles[triOffset + 1] = z * vsize_x + x + vsize_x + 1;

                triangles[triOffset + 3] = z * vsize_x + x +           0;
                triangles[triOffset + 5] = z * vsize_x + x + vsize_x + 1;
                triangles[triOffset + 4] = z * vsize_x + x +           1;
            }
        }

        // Create a new Mesh and populate with the data
        Mesh mesh = new Mesh();
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.normals = normals;
        mesh.uv = uv;

        // Assign our mesh to our filter/renderer/collider
        MeshFilter mesh_filter = GetComponent<MeshFilter>();
        MeshCollider mesh_collider = GetComponent<MeshCollider>();

        mesh_filter.mesh = mesh;
        mesh_collider.sharedMesh = mesh;


        BuildTexture();
    }   
}

【问题讨论】:

  • 有人愿意尝试一下吗?我喜欢代码的这个想法,我似乎无法让 UV 定位布局按应有的方式工作。
  • 你能发布什么区别吗?看起来这就是你想看的地方。

标签: c# unity3d uv-mapping


【解决方案1】:

我不知道图像中的哪个部分有问题,但我认为是相同的图块混在一起。 我试过你的代码,它对我很有效。但我想以下部分可能会导致您出现混淆问题:

Color[] p = tiles[Mathf.RoundToInt(Random.Range(0, 5))];

你应该这样做:

Color[] p = tiles[Random.Range(0, 5)];

因为,另一方面,Random 正在生成浮点数,并且它们可能彼此靠近,将它们四舍五入为整数会给出相同的图块。试一试。 另外提醒一下,确保纹理的宽度和高度可以被 128 整除。

【讨论】:

  • 恐怕大部分都关闭了,尽管我相信这可能是 ChopUpTiles 函数造成的。我只是不确定如何。
  • 我想我重现了这个问题。 Unity 中可以拥有的最大纹理大小为 2^14 x 2^14。当您尝试生成更大的纹理时,它会在创建纹理时出现异常,但无论如何都会创建网格。所以纹理沿着网格延伸,看起来像瓷砖聚集在一起。纹理大小的一维由size_x * tileResolution 决定。所以当你尝试创建一个更大的网格时,你会得到这个错误。
  • 无论如何我注意到这是创建这种网格的不好方法。您可以创建多个网格来拥有更大的世界,但我仍然认为这不是一个好方法。相反,您应该这样做:每个图块使用 4 个顶点。根据它们在原始纹理上的位置分配 uv 坐标。并使用材质中的原始纹理。所以不要创建新的纹理。这样,您可以拥有任何大小的网格,只要它的顶点数少于 64k。再说一次,没有办法克服 64k 顶点,所以如果你想让它更大,你必须创建另一个网格。
  • 但是我仍然不确定您是否收到此错误。如果遇到异常,我认为您会明确说明。
  • 有趣的是,原来给出的瓦片地图要大得多,尽管实际的瓦片更小。但是,这可能是问题所在。我得试试这个建议。
【解决方案2】:

嗯,这绝对是尺寸问题,但也有定位问题。瓷砖必须从左下角开始,坐标系才能找到它们。

【讨论】:

    猜你喜欢
    • 2013-10-24
    • 1970-01-01
    • 1970-01-01
    • 2019-04-10
    • 1970-01-01
    • 1970-01-01
    • 2012-03-16
    • 2022-06-10
    • 1970-01-01
    相关资源
    最近更新 更多