Пример #1
0
    public static Map Load(
        string name,
        GameObject mapRoot,
        MeshFilter tilePool,
        FieldTile fieldPrototype,
        FieldTile verticalFieldPrototype,
        FieldCollider fieldColliderPrototype,
        WalkerBehavior walkerPrototype,
        Action <Map, MeshFilter, int, int> onEachTile
        )
    {
        string    path  = Path.Combine(MapLoader.MapJsonDirectory, name);
        TextAsset asset = Resources.Load <TextAsset>(path);

        if (asset == null)
        {
            Debug.Log("could not load map file: " + path);
            return(new Map());
        }

        // JsonUtility does not support nested array

        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Map));
        RawMap raw = JsonUtility.FromJson <RawMap>(asset.text);

        MapLoader.RawMapToMap(raw, out MapLoader.currentMap);


        MapLoader.currentMap.height = (int)Mathf.Floor(MapLoader.currentMap.terrains[0].Length / MapLoader.currentMap.width) + 1;

        MapLoader.InstantiateFields(mapRoot, tilePool, fieldPrototype, verticalFieldPrototype, fieldColliderPrototype, onEachTile);
        MapLoader.InstantiateWalkerBehaviors(mapRoot, walkerPrototype);

        return(MapLoader.currentMap);
    }
Пример #2
0
    private static GameObject InstantiateFields(
        GameObject mapRoot,
        MeshFilter tilePool,
        FieldTile fieldPrototype,
        FieldTile verticalPrototype,
        FieldCollider fieldColliderPrototype,
        Action <Map, MeshFilter, int, int> onEachTile
        )
    {
        Map map = MapLoader.currentMap;

        mapRoot.isStatic = true;

        int fieldAspects = 4;
        int width        = map.width;

        int floors = (map.fields.Length > map.verticalFields.Length)
            ? map.fields.Length
            : map.verticalFields.Length;

        Dictionary <int, List <MeshFilter> > meshFilterDictionary         = new Dictionary <int, List <MeshFilter> >();
        Dictionary <int, List <MeshFilter> > verticalMeshFilterDictionary = new Dictionary <int, List <MeshFilter> >();

        // TODO: reduce draw call, RT? Mesh Combine?
        for (int floor = 0; floor < floors; floor++)
        {
            int[] floorField = (map.fields.Length > floor)
                ? map.fields[floor]
                : new int[] { };

            int[][] floorVerticalField = (map.verticalFields.Length > floor)
                ? map.verticalFields[floor]
                : new int[][] { };

            int indexes = (floorField.Length >= floorVerticalField.Length)
                ? floorField.Length
                : floorVerticalField.Length;

            for (int i = 0; i < indexes; i++)
            {
                int col = i % width;
                int row = (int)Mathf.Floor(i / width);

                do // collect MeshFilters of horizontal fields by same appearance
                {
                    if (floorField.Length <= i)
                    {
                        break;
                    }

                    int fieldId = floorField[i];
                    if (fieldId == MapLoader.EmptyField)
                    {
                        break;
                    }

                    MeshFilter filter = GameObject.Instantiate <MeshFilter>(tilePool);
                    filter.transform.parent   = mapRoot.transform.transform;
                    filter.transform.rotation = MapLoader.SurfaceUp;
                    filter.transform.position = new Vector3(col * FieldUnit.x + FieldUnit.x * 0.5f, (float)floor * FieldUnit.y, -row * FieldUnit.z - FieldUnit.z * 0.5f);

                    if (!meshFilterDictionary.ContainsKey(fieldId))
                    {
                        meshFilterDictionary.Add(fieldId, new List <MeshFilter> {
                        });
                    }

                    List <MeshFilter> filters = meshFilterDictionary[fieldId];
                    filters.Add(filter);
                    onEachTile?.Invoke(MapLoader.currentMap, filter, col, row);
                } while (false);

                do // collect MeshFilters of vertical fields by same appearance
                {
                    if (floorVerticalField.Length <= i)
                    {
                        break;
                    }

                    int[] verticalFieldDirections = floorVerticalField[i];
                    if (verticalFieldDirections.Length != fieldAspects)
                    {
                        break;
                    }

                    for (int directionNumber = 0; directionNumber < verticalFieldDirections.Length; directionNumber++)
                    {
                        int verticalFieldId = verticalFieldDirections[directionNumber];
                        if (verticalFieldId == MapLoader.EmptyField)
                        {
                            continue;
                        }

                        DirectionUtil.Direction direction = (DirectionUtil.Direction)directionNumber;

                        MeshFilter verticalFilter = GameObject.Instantiate <MeshFilter>(tilePool);
                        verticalFilter.transform.parent   = mapRoot.transform.transform;
                        verticalFilter.transform.rotation = MapLoader.SurfaceDirection[direction];
                        verticalFilter.transform.position = new Vector3(col * FieldUnit.x + 0.5f, ((float)floor + 0.5f) * FieldUnit.y, -row * FieldUnit.z - 0.5f) + MapLoader.SurfaceOffset[direction];

                        if (!verticalMeshFilterDictionary.ContainsKey(verticalFieldId))
                        {
                            verticalMeshFilterDictionary.Add(verticalFieldId, new List <MeshFilter> {
                            });
                        }

                        List <MeshFilter> verticalFilters = verticalMeshFilterDictionary[verticalFieldId];
                        verticalFilters.Add(verticalFilter);
                    }
                } while (false);
            }

            FieldCollider fieldCollider = GameObject.Instantiate <FieldCollider>(fieldColliderPrototype);
            float         height        = Mathf.Floor(map.fields[0].Length / width) + 1;
            fieldCollider.Init(width, height, floor);
            fieldCollider.transform.parent = mapRoot.transform;
            // TODO:
            fieldCollider.gameObject.SetActive(floor == 0);
        }

        // combine meshes
        {
            foreach (KeyValuePair <int, List <MeshFilter> > kv in meshFilterDictionary)
            {
                List <MeshFilter> filters = kv.Value;
                CombineInstance[] combine = new CombineInstance[filters.Count];
                for (int i = 0; i < filters.Count; i++)
                {
                    combine[i].mesh         = filters[i].sharedMesh;
                    combine[i].transform    = filters[i].transform.localToWorldMatrix;
                    combine[i].subMeshIndex = 0;
                    GameObject.Destroy(filters[i].gameObject);
                }

                FieldTile tile = GameObject.Instantiate <FieldTile>(fieldPrototype);
                tile.InitCombinedFloor(combine, kv.Key - 1);
                tile.transform.parent = mapRoot.transform;
            }

            foreach (KeyValuePair <int, List <MeshFilter> > kv in verticalMeshFilterDictionary)
            {
                List <MeshFilter> filters = kv.Value;
                CombineInstance[] combine = new CombineInstance[filters.Count];
                for (int i = 0; i < filters.Count; i++)
                {
                    combine[i].mesh         = filters[i].sharedMesh;
                    combine[i].transform    = filters[i].transform.localToWorldMatrix;
                    combine[i].subMeshIndex = 0;
                    GameObject.Destroy(filters[i].gameObject);
                }

                FieldTile tile = GameObject.Instantiate <FieldTile>(verticalPrototype);
                tile.InitCombinedFloor(combine, kv.Key - 1);
                tile.gameObject.AddComponent <Terrain>();
                tile.transform.parent = mapRoot.transform;

                // skip this if scene allows penetrate path finding raycast
                MeshCollider collider = tile.GetComponent <MeshCollider>();
                collider.sharedMesh = tile.GetComponent <MeshFilter>().sharedMesh;

                /*
                 * CombineInstance[] rcombine = new CombineInstance[filters.Count];
                 * for (int i = 0; i < filters.Count; i++)
                 * {
                 *  Vector3 euler = rcombine[i].transform.rotation.eulerAngles;
                 *  rcombine[i].mesh = filters[i].sharedMesh;
                 *  filters[i].transform.rotation = Quaternion.Euler(new Vector3(euler.x, euler.y + 180.0f, euler.z));
                 *  rcombine[i].transform = filters[i].transform.localToWorldMatrix;
                 *  rcombine[i].subMeshIndex = 0;
                 *  GameObject.Destroy(filters[i].gameObject);
                 * }
                 *
                 * FieldTile rtile = GameObject.Instantiate<FieldTile>(verticalPrototype);
                 * rtile.InitCombinedFloor(rcombine, kv.Key - 1);
                 * rtile.gameObject.AddComponent<Terrain>();
                 * rtile.transform.parent = mapRoot.transform;
                 *
                 * // skip this if scene allows penetrate path finding raycast
                 * MeshCollider rcollider = rtile.GetComponent<MeshCollider>();
                 * rcollider.sharedMesh = rtile.GetComponent<MeshFilter>().sharedMesh;
                 */
            }
        }

        return(mapRoot);
    }