예제 #1
0
    void AddCircleCollider2Ds(Transform parent)
    {
        // find all valid colliders, add them to projection
        var colliders = FindObjectsOfType <CircleCollider2D>();
        var filtered  = colliders.Where(co => IsValidCollider(co)).ToList();

        foreach (var collider in filtered)
        {
            // note: creating a primitive is necessary in order for it to bake properly
            var go = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
            go.isStatic         = true;
            go.transform.parent = parent;
            // position via offset and transformpoint
            var localPos = new Vector3(collider.offset.x, collider.offset.y, 0);
            var worldPos = collider.transform.TransformPoint(localPos);
            // position in 3D with Y aligned so feet are at y=0
            go.transform.position = new Vector3(worldPos.x, NavMesh2D.ProjectedObjectY, worldPos.y);
            // scale depending on scale * collider size (circle=radius/box=size/...)
            go.transform.localScale = NavMeshUtils2D.ScaleFromCircleCollider2D(collider);
            // rotation
            go.transform.rotation = Quaternion.Euler(NavMeshUtils2D.RotationTo3D(collider.transform.eulerAngles));

            MakeUnwalkable(go);
        }
    }
예제 #2
0
    // monobehaviour ///////////////////////////////////////////////////////////
    void Awake()
    {
        // create projection
        var go = GameObject.CreatePrimitive(PrimitiveType.Cylinder);

        go.name = "NAVIGATION2D_OBSTACLE";
        go.transform.position = NavMeshUtils2D.ProjectTo3D(transform.position);
        go.transform.rotation = Quaternion.Euler(NavMeshUtils2D.RotationTo3D(transform.eulerAngles));
        obst = go.AddComponent <NavMeshObstacle>();

        // disable mesh and collider (no collider for now)
        Destroy(obst.GetComponent <Collider>());
        Destroy(obst.GetComponent <MeshRenderer>());
    }
예제 #3
0
    void Update()
    {
        // copy properties to projection all the time
        // (in case they are modified after creating it)
        obst.carving = carve;
        obst.center  = NavMeshUtils2D.ProjectTo3D(center);
        obst.size    = new Vector3(size.x, 1, size.y);

        // scale and rotate to match scaled/rotated sprites center properly
        obst.transform.localScale = new Vector3(transform.localScale.x, 1, transform.localScale.y);
        obst.transform.rotation   = Quaternion.Euler(NavMeshUtils2D.RotationTo3D(transform.eulerAngles));

        // project position to 3d
        obst.transform.position = NavMeshUtils2D.ProjectTo3D(transform.position);
    }
예제 #4
0
    void AddPolygonCollider2Ds(Transform parent)
    {
        // find all valid colliders, add them to projection
        var colliders = GameObject.FindObjectsOfType <PolygonCollider2D>();
        var filtered  = colliders.Where(co => IsValidCollider(co)).ToList();

        foreach (var collider in filtered)
        {
            for (int i = 0; i < collider.pathCount; i++)
            {
                // note: creating a primitive is necessary in order for it to bake properly
                var go = GameObject.CreatePrimitive(PrimitiveType.Cube);
                go.isStatic         = true;
                go.transform.parent = parent;

                // position via offset and transformpoint
                var localPos = new Vector3(collider.offset.x, collider.offset.y, 0);
                var worldPos = collider.transform.TransformPoint(localPos);
                go.transform.position = new Vector3(worldPos.x, 0, worldPos.y);
                // scale depending on scale * collider size (circle=radius/box=size/...)
                go.transform.localScale = NavMeshUtils2D.ScaleFromPolygonCollider2D(collider);
                // rotation
                go.transform.rotation = Quaternion.Euler(NavMeshUtils2D.RotationTo3D(collider.transform.eulerAngles));

                // remove box collider. note that baking uses the meshfilter, so
                // the collider doesn't really matter anyway.
                DestroyImmediate(go.GetComponent <BoxCollider>());

                // Use the triangulator to get indices for creating triangles
                int[] indices = Triangulation.Triangulate(collider.GetPath(i).ToList()).ToArray();

                // convert vector2 points to vector3 vertices
                var vertices = collider.GetPath(i).Select(p => new Vector3(p.x, 0, p.y)).ToList();

                // create mesh
                var mesh = new Mesh();
                mesh.vertices  = vertices.ToArray();
                mesh.triangles = indices;
                //mesh.RecalculateNormals();
                mesh.RecalculateBounds();

                // assign it to the mesh filter
                go.GetComponent <MeshFilter>().sharedMesh = mesh;

                MakeUnwalkable(go);
            }
        }
    }
예제 #5
0
    void AddTilemapCollider2Ds(Transform parent)
    {
        // find all grids
        Grid[] grids = GameObject.FindObjectsOfType <Grid>();
        foreach (Grid grid in grids)
        {
            // find tilemaps (we only care about those that have colliders)
            var tilemaps = grid.GetComponentsInChildren <Tilemap>().Where(
                tm => tm.GetComponent <TilemapCollider2D>()
                ).ToList();

            foreach (Tilemap tilemap in tilemaps)
            {
                // go through each cell
                BoundsInt bounds = tilemap.cellBounds;
                for (int y = bounds.position.y; y < bounds.size.y; ++y)
                {
                    for (int x = bounds.position.x; x < bounds.size.x; ++x)
                    {
                        // find out if it has a collider
                        Vector3Int cellPosition = new Vector3Int(x, y, 0);
                        if (tilemap.GetColliderType(cellPosition) != Tile.ColliderType.None)
                        {
                            // convert to world space
                            Vector3 worldPosition = tilemap.GetCellCenterWorld(cellPosition);

                            // note: creating a primitive is necessary in order for it to bake properly
                            var go = GameObject.CreatePrimitive(PrimitiveType.Cube);
                            go.isStatic         = true;
                            go.transform.parent = parent;
                            // position via offset and transformpoint
                            go.transform.position = new Vector3(worldPosition.x, 0, worldPosition.y);
                            // scale depending on scale * collider size (circle=radius/box=size/...)
                            go.transform.localScale = NavMeshUtils2D.ScaleTo3D(tilemap.transform.localScale);
                            // rotation
                            go.transform.rotation = Quaternion.Euler(NavMeshUtils2D.RotationTo3D(tilemap.transform.eulerAngles));

                            MakeUnwalkable(go);
                        }
                    }
                }
            }
        }
    }
예제 #6
0
    void AddEdgeCollider2Ds(Transform parent)
    {
        // find all valid colliders, add them to projection
        var colliders = GameObject.FindObjectsOfType <EdgeCollider2D>();
        var filtered  = colliders.Where(co => IsValidCollider(co)).ToList();

        foreach (var collider in filtered)
        {
            // note: creating a primitive is necessary in order for it to bake properly
            var go = GameObject.CreatePrimitive(PrimitiveType.Cube);
            go.isStatic         = true;
            go.transform.parent = parent;

            // position via offset and transformpoint
            var localPos = new Vector3(collider.offset.x, collider.offset.y, 0);
            var worldPos = collider.transform.TransformPoint(localPos);
            go.transform.position = new Vector3(worldPos.x, 0, worldPos.y);
            // scale depending on scale * collider size (circle=radius/box=size/...)
            go.transform.localScale = NavMeshUtils2D.ScaleFromEdgeCollider2D(collider);
            // rotation
            go.transform.rotation = Quaternion.Euler(NavMeshUtils2D.RotationTo3D(collider.transform.eulerAngles));

            // remove box collider. note that baking uses the meshfilter, so
            // the collider doesn't really matter anyway.
            DestroyImmediate(go.GetComponent <BoxCollider>());

            // create mesh from edgecollider2D by stepping through each point
            // and creating a triangle with point, point-1 and point-1 with y=1
            List <Vector3> vertices = new List <Vector3>();
            List <int>     indices  = new List <int>();

            // start at 2nd point so we can use the first one in our triangle,
            for (int i = 1; i < collider.points.Length; ++i)
            {
                Vector2 a2D = collider.points[i - 1];
                Vector2 b2D = collider.points[i];

                // convert to 3D
                //   point A
                //   point B
                //   point C := A with y+1
                Vector3 a3D = new Vector3(a2D.x, 0, a2D.y);
                Vector3 b3D = new Vector3(b2D.x, 0, b2D.y);
                Vector3 c3D = new Vector3(a2D.x, 1, a2D.y);

                // add 3 vertices
                vertices.Add(a3D);
                vertices.Add(b3D);
                vertices.Add(c3D);

                // add last 3 vertices as indices
                indices.Add(vertices.Count - 1);
                indices.Add(vertices.Count - 2);
                indices.Add(vertices.Count - 3);
            }

            // create mesh
            var mesh = new Mesh();
            mesh.vertices  = vertices.ToArray();
            mesh.triangles = indices.ToArray();
            //mesh.RecalculateNormals();
            mesh.RecalculateBounds();

            // assign it to the mesh filter
            go.GetComponent <MeshFilter>().sharedMesh = mesh;

            MakeUnwalkable(go);
        }
    }