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); }
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); }