简体   繁体   English

2D中的Unity自定义形状生成对象

[英]Unity custom shape generation objects in 2d

I new to Unity. 我是Unity新手。 I'm trying to re-write game from the site in Unity http://www.boxcar2d.com/index.html 我正在尝试从Unity http://www.boxcar2d.com/index.html中的网站重新编写游戏

So I found that I should work with Sprites. 因此,我发现我应该使用Sprites。 Now I am trying to dynamically generate an arbitrarily shaped "car". 现在,我尝试动态生成任意形状的“汽车”。 I need it to collide and interact with physics and gravity. 我需要它与物理和重力碰撞并相互作用。 I tried to use Mesh but it seems like there is no way to turn Mesh into a Sprite and work with it like with physical object. 我尝试使用Mesh但似乎无法将Mesh转换为Sprite并像处理物理对象一样使用它。

What kind of structures or approach should I use for creating those "cars" dynamically? 我应该使用哪种结构或方法来动态创建这些“汽车”?

Here is my code so far if that somehow will be useful. 到目前为止,这是我的代码(如果有帮助的话)。

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

public class GenerateCar : MonoBehaviour {

    public Material mat;



    // Use this for initialization
    void Start()
    {
        Mesh mesh = new Mesh();

        Vector3[] vertices = new Vector3[6];

        vertices[0] = new Vector3(0, 0);
        vertices[1] = new Vector3(4, 1);
        vertices[2] = new Vector3(3, -1);
        vertices[3] = new Vector3(-1, -3);
        vertices[4] = new Vector3(3, -6);
        vertices[5] = new Vector3(0, 1);
        //vertices[6] = new Vector3(width, height);
        //vertices[7] = new Vector3(width, -height);

        mesh.vertices = vertices;

        mesh.triangles = new int[] { 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 1};

        GetComponent<MeshRenderer>().material = mat;

        GetComponent<MeshFilter>().mesh = mesh;
    }

}

If you need to make arbitrary shapes that can't be made with just horizontally and vertically stretching sprites you make ahead of time, then sprites aren't suitable. 如果您需要制作任意形状,而这些形状是您无法事先使用水平和垂直拉伸的精灵创建的,那么精灵就不合适了。 A Mesh would be more practical. Mesh将更实用。

If you can describe the shape you want to make as a polygon with a known ordered list of points, you can use the community Triangular class to create a Mesh . 如果可以将要制作的形状描述为具有已知点的有序列表的多边形,则可以使用社区Triangular类创建Mesh There are other methods, but this is a community standby. 还有其他方法,但这是社区备用方法。

Whatever you use to make the Mesh , you will need to make sure there is also a PolygonCollider2D on the same object as the Mesh . 无论用什么方法制作Mesh ,都需要确保在与Mesh物体相同的对象上也有PolygonCollider2D You can use SetPath to create its outline using the same points as you fed into Triangulator . 您可以使用SetPath使用与Triangulator输入的点相同的点来创建其轮廓。 You will also need a Rigidbody2D to handle physics and collision for the body of the car. 您还需要Rigidbody2D来处理汽车车身的物理问题和碰撞。 I've never worked with wheels but WheelJoint2D might be what you can use for the wheels. 我从未使用过轮子,但是WheelJoint2D可能是您可以使用的轮子。

Triangulator Usage Example Triangulator用法示例

using UnityEngine;

public class PolygonTester : MonoBehaviour {
    void Start () {
        // Create Vector2 vertices
        Vector2[] vertices2D = new Vector2[] {
            new Vector2(0,0),
            new Vector2(0,50),
            new Vector2(50,50),
            new Vector2(50,100),
            new Vector2(0,100),
            new Vector2(0,150),
            new Vector2(150,150),
            new Vector2(150,100),
            new Vector2(100,100),
            new Vector2(100,50),
            new Vector2(150,50),
            new Vector2(150,0),
        };

        // Use the triangulator to get indices for creating triangles
        Triangulator tr = new Triangulator(vertices2D);
        int[] indices = tr.Triangulate();

        // Create the Vector3 vertices
        Vector3[] vertices = new Vector3[vertices2D.Length];
        for (int i=0; i<vertices.Length; i++) {
            vertices[i] = new Vector3(vertices2D[i].x, vertices2D[i].y, 0);
        }

        // Create the mesh
        Mesh msh = new Mesh();
        msh.vertices = vertices;
        msh.triangles = indices;
        msh.RecalculateNormals();
        msh.RecalculateBounds();

        // Set up game object with mesh;
        gameObject.AddComponent(typeof(MeshRenderer));
        MeshFilter filter = gameObject.AddComponent(typeof(MeshFilter)) as MeshFilter;
        filter.mesh = msh;
    }
}

Triangulator source Triangulator

using UnityEngine;
using System.Collections.Generic;

public class Triangulator
{
    private List<Vector2> m_points = new List<Vector2>();

    public Triangulator (Vector2[] points) {
        m_points = new List<Vector2>(points);
    }

    public int[] Triangulate() {
        List<int> indices = new List<int>();

        int n = m_points.Count;
        if (n < 3)
            return indices.ToArray();

        int[] V = new int[n];
        if (Area() > 0) {
            for (int v = 0; v < n; v++)
                V[v] = v;
        }
        else {
            for (int v = 0; v < n; v++)
                V[v] = (n - 1) - v;
        }

        int nv = n;
        int count = 2 * nv;
        for (int m = 0, v = nv - 1; nv > 2; ) {
            if ((count--) <= 0)
                return indices.ToArray();

            int u = v;
            if (nv <= u)
                u = 0;
            v = u + 1;
            if (nv <= v)
                v = 0;
            int w = v + 1;
            if (nv <= w)
                w = 0;

            if (Snip(u, v, w, nv, V)) {
                int a, b, c, s, t;
                a = V[u];
                b = V[v];
                c = V[w];
                indices.Add(a);
                indices.Add(b);
                indices.Add(c);
                m++;
                for (s = v, t = v + 1; t < nv; s++, t++)
                    V[s] = V[t];
                nv--;
                count = 2 * nv;
            }
        }

        indices.Reverse();
        return indices.ToArray();
    }

    private float Area () {
        int n = m_points.Count;
        float A = 0.0f;
        for (int p = n - 1, q = 0; q < n; p = q++) {
            Vector2 pval = m_points[p];
            Vector2 qval = m_points[q];
            A += pval.x * qval.y - qval.x * pval.y;
        }
        return (A * 0.5f);
    }

    private bool Snip (int u, int v, int w, int n, int[] V) {
        int p;
        Vector2 A = m_points[V[u]];
        Vector2 B = m_points[V[v]];
        Vector2 C = m_points[V[w]];
        if (Mathf.Epsilon > (((B.x - A.x) * (C.y - A.y)) - ((B.y - A.y) * (C.x - A.x))))
            return false;
        for (p = 0; p < n; p++) {
            if ((p == u) || (p == v) || (p == w))
                continue;
            Vector2 P = m_points[V[p]];
            if (InsideTriangle(A, B, C, P))
                return false;
        }
        return true;
    }

    private bool InsideTriangle (Vector2 A, Vector2 B, Vector2 C, Vector2 P) {
        float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
        float cCROSSap, bCROSScp, aCROSSbp;

        ax = C.x - B.x; ay = C.y - B.y;
        bx = A.x - C.x; by = A.y - C.y;
        cx = B.x - A.x; cy = B.y - A.y;
        apx = P.x - A.x; apy = P.y - A.y;
        bpx = P.x - B.x; bpy = P.y - B.y;
        cpx = P.x - C.x; cpy = P.y - C.y;

        aCROSSbp = ax * bpy - ay * bpx;
        cCROSSap = cx * apy - cy * apx;
        bCROSScp = bx * cpy - by * cpx;

        return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM