/// <summary> /// Creates this Tile Object (an object that has OriginalID) if applicable /// </summary> /// <param name="tiledMap">The base Tile Map</param> /// <param name="layerDepth">Layer's zDepth</param> /// <param name="sortingLayerName">Layer's SortingLayerName</param> /// <param name="parent">Transform to parent this object to</param> /// <param name="materials">List of TileSet Materials</param> public static GameObject CreateTileObject(this MapObject obj, Map tiledMap, string sortingLayerName, int layerDepth, List<Material> materials, Transform parent = null) { if (obj.GID > 0) { Tile objTile = null; if (tiledMap.MapRenderParameter.Orientation != Orientation.Orthogonal) objTile = tiledMap.Tiles[obj.GID].Clone(new Vector2(0.5f, 0.5f)); else objTile = tiledMap.Tiles[obj.GID].Clone(); objTile.CreateTileObject(obj.Name, parent != null ? parent : obj.ParentObjectLayer.LayerGameObject.transform, sortingLayerName, tiledMap.DefaultSortingOrder + tiledMap.GetSortingOrder(obj.Bounds.x, obj.Bounds.y), tiledMap.TiledPositionToWorldPoint(obj.Bounds.x, obj.Bounds.y, layerDepth), materials); obj.Bounds.Set(obj.Bounds.x, obj.Bounds.y - 1, obj.Bounds.width, obj.Bounds.height); objTile.TileGameObject.SetActive(obj.Visible); // Since Tiled 0.12, TileObjects' Bounds will have the desired width and height of the image, so scale accordingly if(obj.Bounds.width != 1 || obj.Bounds.height != 1) objTile.TileGameObject.transform.localScale = new Vector3(obj.Bounds.width / objTile.TileSprite.bounds.size.x, obj.Bounds.height / objTile.TileSprite.bounds.size.y); return objTile.TileGameObject; } return null; }
/// <summary> /// Adds a Box Collider 2D or 3D to an existing GameObject using one MapObject as properties source /// </summary> /// <param name="gameObject">GameObject to add a Box Collider</param> /// <param name="obj">MapObject which properties will be used to generate this collider.</param> /// <param name="isTrigger">True for Trigger Collider, false otherwise</param> /// <param name="zDepth">Z Depth of the collider.</param> /// <param name="colliderWidth">Width of the collider, in Units</param> /// <param name="used2DColider">True to generate a 2D collider, false to generate a 3D collider.</param> /// <param name="createRigidbody">True to attach a Rigidbody to the created collider</param> /// <param name="rigidbodyIsKinematic">Sets if the attached rigidbody is kinematic or not</param> public static void AddBoxCollider(Map map, GameObject gameObject, MapObject obj, bool used2DColider = true, bool isTrigger = false, float zDepth = 0, float colliderWidth = 1.0f, bool createRigidbody = false, bool rigidbodyIsKinematic = true) { if (used2DColider) AddBoxCollider2D(map, gameObject, obj, isTrigger, null, zDepth, createRigidbody, rigidbodyIsKinematic); else AddBoxCollider3D(map, gameObject, obj, isTrigger, null, zDepth, colliderWidth, createRigidbody, rigidbodyIsKinematic); }
/// <summary> /// Creates a Map Object Layer from node /// </summary> /// <param name="node">XML node to parse</param> /// <param name="tiledMap">MapObjectLayer parent Map</param> /// <param name="layerDepth">This Layer's zDepth</param> /// <param name="materials">List of Materials containing the TileSet textures</param> public MapObjectLayer(NanoXMLNode node, Map tiledMap, int layerDepth) : base(node, tiledMap) { if (node.GetAttribute("color") != null) { // get the color string, removing the leading # string color = node.GetAttribute("color").Value.Substring(1); // get the RGB individually string r = color.Substring(0, 2); string g = color.Substring(2, 2); string b = color.Substring(4, 2); // convert to the color Color = new Color( (byte)int.Parse(r, NumberStyles.AllowHexSpecifier), (byte)int.Parse(g, NumberStyles.AllowHexSpecifier), (byte)int.Parse(b, NumberStyles.AllowHexSpecifier)); } Objects = new List<MapObject>(); foreach (NanoXMLNode objectNode in node.SubNodes) { if (!objectNode.Name.Equals("object")) continue; MapObject mapObjectContent = new MapObject(objectNode, this); mapObjectContent = mapObjectContent.ScaleObject(tiledMap.MapRenderParameter) as MapObject; // Object names need to be unique for our lookup system, but Tiled // doesn't require unique names. string objectName = mapObjectContent.Name; int duplicateCount = 2; // if a object already has the same name... if (Objects.Find(o => o.Name.Equals(objectName)) != null) { // figure out a object name that does work do { objectName = string.Format("{0}{1}", mapObjectContent.Name, duplicateCount); duplicateCount++; } while (Objects.Find(o => o.Name.Equals(objectName)) != null); // log a warning for the user to see //Debug.LogWarning("Renaming object \"" + mapObjectContent.Name + "\" to \"" + objectName + "\" in layer \"" + Name + "\" to make a unique name."); // save that name mapObjectContent.Name = objectName; } //mapObjectContent.CreateTileObject(tiledMap, Name, layerDepth, materials); AddObject(mapObjectContent); } }
void SetPlayerNewPosition(Map lastMap, Vector2 _doorFromPosition) { Vector2 fromDoorIndex = lastMap.WorldPointToTileIndex(_doorFromPosition); // Change door tile to opened door :P int originalID = lastMap.GetTileLayer("Layer 0").Tiles[fromDoorIndex.x, fromDoorIndex.y].OriginalID; lastMap.GetTileLayer("Layer 0").SetTile(fromDoorIndex.x, fromDoorIndex.y, originalID + 2); int lastMapWidth = lastMap.Width; int lastMapHeight = lastMap.Height; // Position player MapObjectLayer mol = _currentMap.GetObjectLayer("Doors"); for (int i = 0; i < mol.Objects.Count; i++) { // This is a Left Door - X = 0 if (mol.Objects[i].Bounds.x < 1) { // And we came from a Right Door! if (fromDoorIndex.x >= lastMapWidth - 1) { _player.transform.localPosition = _currentMap.TiledPositionToWorldPoint(1.5f, mol.Objects[i].Bounds.y + 0.5f); } } // This is a Right Door - X = _currentMap.Width - 1 if (mol.Objects[i].Bounds.x >= _currentMap.Width - 1) { // And we came from a Left Door! if (fromDoorIndex.x < 1) { _player.transform.localPosition = _currentMap.TiledPositionToWorldPoint(mol.Objects[i].Bounds.x - 1, mol.Objects[i].Bounds.y + 0.5f); } } // This is an Up Door - Y = 0 if (mol.Objects[i].Bounds.y < 1) { // And we came from a Down Door! if (fromDoorIndex.y >= lastMapHeight - 1) { _player.transform.localPosition = _currentMap.TiledPositionToWorldPoint(mol.Objects[i].Bounds.x + 0.5f, 1.4f); } } // This is a Down Door - Y = _currentMap.Height - 1 if (mol.Objects[i].Bounds.y >= _currentMap.Height - 1) { // And we came from an Up Door! if (fromDoorIndex.y < 1) { _player.transform.localPosition = _currentMap.TiledPositionToWorldPoint(mol.Objects[i].Bounds.x, mol.Objects[i].Bounds.y - 0.5f); } } } _player.gameObject.GetComponent<X_UniTMX.Utils.SortingOrderAutoCalculator>().SetMap(_currentMap); }
/// <summary> /// Adds a BoxCollider2D to a GameObject /// </summary> /// <param name="gameObject">GameObject to add the collider</param> /// <param name="obj">MapObject which properties will be used to generate this collider</param> /// <param name="isTrigger">True for Trigger Collider, false otherwise</param> /// <param name="physicsMaterial">PhysicsMaterial2D to be set to the collider</param> /// <param name="zDepth">Z Depth of the collider</param> /// <param name="createRigidbody">True to attach a Rigidbody to the created collider</param> /// <param name="rigidbodyIsKinematic">Sets if the attached rigidbody is kinematic or not</param> public static void AddBoxCollider2D(Map map, GameObject gameObject, MapObject obj, bool isTrigger = false, PhysicsMaterial2D physicsMaterial = null, float zDepth = 0, bool createRigidbody = false, bool rigidbodyIsKinematic = true) { // Orthogonal and Staggered maps can use BoxCollider, Isometric maps must use polygon collider if (map.MapRenderParameter.Orientation != X_UniTMX.Orientation.Isometric) { BoxCollider2D bx = gameObject.AddComponent<BoxCollider2D>(); bx.isTrigger = isTrigger || obj.Type.Equals(Map.Object_Type_Trigger); #if UNITY_5 bx.offset = new Vector2(obj.Bounds.width / 2.0f, -obj.Bounds.height / 2.0f); #else bx.center = new Vector2(obj.Bounds.width / 2.0f, -obj.Bounds.height / 2.0f); #endif bx.size = new Vector2(obj.Bounds.width, obj.Bounds.height); if (physicsMaterial != null) bx.sharedMaterial = physicsMaterial; } else if (map.MapRenderParameter.Orientation == X_UniTMX.Orientation.Isometric) { PolygonCollider2D pc = gameObject.AddComponent<PolygonCollider2D>(); pc.isTrigger = isTrigger || obj.Type.Equals(Map.Object_Type_Trigger); Vector2[] points = new Vector2[4]; points[0] = map.TiledPositionToWorldPoint(obj.Bounds.xMin - obj.Bounds.x, obj.Bounds.yMax - obj.Bounds.y); points[1] = map.TiledPositionToWorldPoint(obj.Bounds.xMin - obj.Bounds.x, obj.Bounds.yMin - obj.Bounds.y); points[2] = map.TiledPositionToWorldPoint(obj.Bounds.xMax - obj.Bounds.x, obj.Bounds.yMin - obj.Bounds.y); points[3] = map.TiledPositionToWorldPoint(obj.Bounds.xMax - obj.Bounds.x, obj.Bounds.yMax - obj.Bounds.y); points[0].x -= map.MapRenderParameter.Width / 2.0f; points[1].x -= map.MapRenderParameter.Width / 2.0f; points[2].x -= map.MapRenderParameter.Width / 2.0f; points[3].x -= map.MapRenderParameter.Width / 2.0f; pc.SetPath(0, points); if (physicsMaterial != null) pc.sharedMaterial = physicsMaterial; } if (createRigidbody) { Rigidbody2D r = gameObject.AddComponent<Rigidbody2D>(); r.isKinematic = rigidbodyIsKinematic; } if (obj.Rotation != 0) gameObject.transform.localRotation = Quaternion.AngleAxis(obj.Rotation, Vector3.forward); ApplyCustomProperties(gameObject, obj); // Link this collider to the MapObject obj.LinkedGameObject = gameObject; }
/// <summary> /// Creates a Tile Layer from node /// </summary> /// <param name="node">XML node to parse</param> /// <param name="map">TileLayer parent Map</param> /// <param name="layerDepth">This Layer's zDepth</param> /// <param name="makeUnique">true to generate Unique Tiles</param> /// <param name="materials">List of Materials containing the TileSet textures</param> public TileLayer(NanoXMLNode node, Map map, int layerDepth, bool makeUnique, List<Material> materials) : base(node) { NanoXMLNode dataNode = node["data"]; Data = new uint[Width * Height]; LayerDepth = layerDepth; MakeUniqueTiles = makeUnique; // figure out what encoding is being used, if any, and process // the data appropriately if (dataNode.GetAttribute("encoding") != null) { string encoding = dataNode.GetAttribute("encoding").Value; if (encoding == "base64") { ReadAsBase64(dataNode); } else if (encoding == "csv") { ReadAsCsv(dataNode); } else { throw new Exception("Unknown encoding: " + encoding); } } else { // XML format simply lays out a lot of <tile gid="X" /> nodes inside of data. int i = 0; foreach (NanoXMLNode tileNode in dataNode.SubNodes) { if (tileNode.Name.Equals("tile")) { Data[i] = uint.Parse(tileNode.GetAttribute("gid").Value, CultureInfo.InvariantCulture); i++; } } if (i != Data.Length) throw new Exception("Not enough tile nodes to fill data"); } Initialize(map, Data, materials); }
/// <summary> /// Creates an Image Layer from node /// </summary> /// <param name="node">XML node to parse</param> /// <param name="map">ImageLayer parent Map</param> /// <param name="mapPath">Map's directory path</param> /// <param name="baseMaterial">Material to use on this SpriteRenderer</param> public ImageLayer(NanoXMLNode node, Map map, string mapPath) : base(node, map) { NanoXMLNode imageNode = node["image"]; this.Image = imageNode.GetAttribute("source").Value; if (node.GetAttribute("x") != null) { Position.x = float.Parse(node.GetAttribute("x").Value, NumberStyles.Float) / (float)map.MapRenderParameter.TileWidth; } if (node.GetAttribute("y") != null) { Position.y = -float.Parse(node.GetAttribute("y").Value, NumberStyles.Float) / (float)map.MapRenderParameter.TileHeight; } // if the image is in any director up from us, just take the filename //if (this.Image.StartsWith("..")) // this.Image = Path.GetFileName(this.Image); if (imageNode.GetAttribute("trans") != null) { string color = imageNode.GetAttribute("trans").Value; string r = color.Substring(0, 2); string g = color.Substring(2, 2); string b = color.Substring(4, 2); this.ColorKey = new Color((byte)Convert.ToInt32(r, 16), (byte)Convert.ToInt32(g, 16), (byte)Convert.ToInt32(b, 16)); } SortingOrder = map.DefaultSortingOrder - LayerDepth; _ppu = map.MapRenderParameter.TileWidth; useWWWToLoad = map.UsingStreamingAssetsPath; string texturePath = mapPath; if (!useWWWToLoad) { texturePath = Utils.XUniTMXHelpers.ParsePath(mapPath, Image); } else { if (!texturePath.Contains("://")) texturePath = "file://" + texturePath + Path.GetFileName(this.Image); } Image = texturePath; }
public TileLayer(XmlNode node, Map map, float layerDepth, bool makeUnique, List<Material> materials) : base(node) { XmlNode dataNode = node["data"]; Data = new uint[Width * Height]; LayerDepth = layerDepth; Debug.Log("Layer Depth: " + LayerDepth); // figure out what encoding is being used, if any, and process // the data appropriately if (dataNode.Attributes["encoding"] != null) { string encoding = dataNode.Attributes["encoding"].Value; if (encoding == "base64") { ReadAsBase64(node, dataNode); } else if (encoding == "csv") { ReadAsCsv(node, dataNode); } else { throw new Exception("Unknown encoding: " + encoding); } } else { // XML format simply lays out a lot of <tile gid="X" /> nodes inside of data. int i = 0; foreach (XmlNode tileNode in dataNode.SelectNodes("tile")) { Data[i] = uint.Parse(tileNode.Attributes["gid"].Value, CultureInfo.InvariantCulture); i++; } if (i != Data.Length) throw new Exception("Not enough tile nodes to fill data"); } Initialize(map, Data, makeUnique, materials); }
public ImageLayer(XElement node, Map map, string mapPath, Material baseMaterial) : base(node) { XElement imageNode = node.Element("image"); this.Image = imageNode.Attribute("source").Value; // if the image is in any director up from us, just take the filename if (this.Image.StartsWith("..")) this.Image = Path.GetFileName(this.Image); if (imageNode.Attribute("trans") != null) { string color = imageNode.Attribute("trans").Value; string r = color.Substring(0, 2); string g = color.Substring(2, 2); string b = color.Substring(4, 2); this.ColorKey = new Color((byte)Convert.ToInt32(r, 16), (byte)Convert.ToInt32(g, 16), (byte)Convert.ToInt32(b, 16)); } string texturePath = mapPath; if (Path.GetDirectoryName(this.Image).Length > 0) texturePath += Path.GetDirectoryName(this.Image) + Path.AltDirectorySeparatorChar; this.Texture = (Texture2D)Resources.Load(texturePath + Path.GetFileNameWithoutExtension(this.Image), typeof(Texture2D)); LayerGameObject = new GameObject(Name); LayerGameObject.transform.parent = map.MapObject.transform; LayerGameObject.transform.localPosition = new Vector3(0, 0, this.LayerDepth); LayerGameObject.isStatic = true; LayerGameObject.SetActive(Visible); SpriteRenderer tileRenderer = LayerGameObject.AddComponent<SpriteRenderer>(); tileRenderer.sprite = Sprite.Create(Texture, new Rect(0, 0, Texture.width, Texture.height), Vector2.up, map.TileWidth); tileRenderer.sprite.name = Texture.name; tileRenderer.sortingOrder = map.DefaultSortingOrder - LayerDepth; // Use Layer's name as Sorting Layer tileRenderer.sortingLayerName = this.Name; //tileRenderer.material = new Material(baseMaterial); //tileRenderer.material.mainTexture = Texture; }
public void LoadMap(string map, Vector2 _doorFromPosition) { if (map.Equals(_currentMap.MapObject.name)) return; Map lastMap = _currentMap; _currentMap.MapObject.SetActive(false); Map nextMap = null; // If map was already loaded, just enable its GameObject if (_loadedMaps.TryGetValue(map, out nextMap)) { nextMap.MapObject.SetActive(true); _currentMap = nextMap; } else { // Else, load the map and generate its collisions for (int i = 0; i < _maps.Length; i++) { if (_maps[i].name.Equals(map)) { nextMap = new Map(_maps[i].text, map, _tiledMapComponent.MapTMXPath, _tiledMapComponent.gameObject, _tiledMapComponent.materialDefaultFile, _tiledMapComponent.DefaultSortingOrder, true); nextMap.GenerateTileCollisions(); nextMap.GenerateCollidersFromLayer("WallColliders"); nextMap.GenerateCollidersFromLayer("Doors", true, true); _loadedMaps.Add(map, nextMap); _currentMap = nextMap; break; } } } if (nextMap == null) return; // Set the player's position on the new map SetPlayerNewPosition(lastMap, _doorFromPosition); }
protected Layer(NanoXMLNode node, Map tileMap) { //string Type = node.Name; Name = node.GetAttribute("name").Value; if (string.IsNullOrEmpty(Name)) Name = "Layer"; if (node.GetAttribute("width") != null) Width = int.Parse(node.GetAttribute("width").Value, CultureInfo.InvariantCulture); else Width = 0; if (node.GetAttribute("height") != null) Height = int.Parse(node.GetAttribute("height").Value, CultureInfo.InvariantCulture); else Height = 0; if (node.GetAttribute("opacity") != null) { Opacity = float.Parse(node.GetAttribute("opacity").Value, CultureInfo.InvariantCulture); } else Opacity = 1; if (node.GetAttribute("visible") != null) { Visible = int.Parse(node.GetAttribute("visible").Value, CultureInfo.InvariantCulture) == 1; } else Visible = true; NanoXMLNode propertiesNode = node["properties"]; if (propertiesNode != null) { Properties = new PropertyCollection(propertiesNode); } BaseMap = tileMap; }
private static void ApproximateEllipse3D(Map map, GameObject newCollider, MapObject obj, bool isTrigger = false, PhysicMaterial physicsMaterial = null, float zDepth = 0, float colliderWidth = 1.0f, bool createRigidbody = false, bool rigidbodyIsKinematic = true) { // since there's no "EllipseCollider", we must create one by approximating a polygon collider //newCollider.transform.localPosition = TiledPositionToWorldPoint(obj.Bounds.x, obj.Bounds.y, zDepth); Mesh colliderMesh = new Mesh(); colliderMesh.name = "Collider_" + obj.Name; MeshCollider mc = newCollider.AddComponent<MeshCollider>(); mc.isTrigger = isTrigger || obj.Type.Equals(Map.Object_Type_Trigger); int segments = XUniTMXConfiguration.Instance.EllipsoideColliderApproximationFactor; // Segments per quadrant int incFactor = Mathf.FloorToInt(segments / 4.0f); float minIncrement = 2 * Mathf.PI / (incFactor * segments / 2.0f); int currentInc = 0; bool grow = true; Vector2[] points = new Vector2[segments]; float width = obj.Bounds.width; float height = obj.Bounds.height; Vector2 center = new Vector2(width / 2.0f, height / 2.0f); float r = 0; float angle = 0; for (int i = 0; i < segments; i++) { // Calculate radius at each point //angle = i * increment; angle += currentInc * minIncrement; r = width * height / Mathf.Sqrt(Mathf.Pow(height * Mathf.Cos(angle), 2) + Mathf.Pow(width * Mathf.Sin(angle), 2)) / 2.0f; points[i] = r * new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)) + center; if (map.MapRenderParameter.Orientation == X_UniTMX.Orientation.Staggered) points[i].y *= -1; if (grow) currentInc++; else currentInc--; if (currentInc > incFactor - 1 || currentInc < 1) grow = !grow; // POG :P if (map.MapRenderParameter.Orientation != X_UniTMX.Orientation.Isometric) { if (i < 1 || i == segments / 2 - 1) points[i].y += obj.Bounds.height / 20.0f; if (i >= segments - 1 || i == segments / 2) points[i].y -= obj.Bounds.height / 20.0f; } } List<Vector3> vertices = new List<Vector3>(); List<int> triangles = new List<int>(); GenerateVerticesAndTris(map, new List<Vector2>(points), vertices, triangles, zDepth, colliderWidth, false, !(map.MapRenderParameter.Orientation == X_UniTMX.Orientation.Staggered)); // Connect last point with first point (create the face between them) triangles.Add(vertices.Count - 1); triangles.Add(1); triangles.Add(0); triangles.Add(0); triangles.Add(vertices.Count - 2); triangles.Add(vertices.Count - 1); FillFaces(points, triangles); colliderMesh.vertices = vertices.ToArray(); colliderMesh.uv = new Vector2[colliderMesh.vertices.Length]; //colliderMesh.uv1 = colliderMesh.uv; colliderMesh.uv2 = colliderMesh.uv; colliderMesh.triangles = triangles.ToArray(); colliderMesh.RecalculateNormals(); mc.sharedMesh = colliderMesh; if (physicsMaterial != null) mc.sharedMaterial = physicsMaterial; }
/*private GameObject GenerateSingleMesh(List<Vector3> vertices, Tile t) { GameObject obj = new GameObject(); MeshFilter mfilter = obj.AddComponent<MeshFilter>(); MeshRenderer mrender = obj.AddComponent<MeshRenderer>(); Vector3 TopLeft = new Vector3(Mathf.Infinity, Mathf.NegativeInfinity, Mathf.Infinity); Vector3 TopRight = new Vector3(Mathf.NegativeInfinity, Mathf.NegativeInfinity, Mathf.Infinity); Vector3 BottomLeft = new Vector3(Mathf.Infinity, Mathf.Infinity, Mathf.Infinity); Vector3 BottomRight = new Vector3(Mathf.NegativeInfinity, Mathf.Infinity, Mathf.Infinity); foreach (Vector3 vertex in vertices) { if (vertex.x < TopLeft.x && -vertex.y > TopLeft.y) TopLeft = vertex; if (vertex.x > TopRight.x && -vertex.y > TopRight.y) TopRight = vertex; if (vertex.x < BottomLeft.x && -vertex.y < BottomLeft.y) BottomLeft = vertex; if (vertex.x > BottomRight.x && -vertex.y < BottomRight.y) BottomRight = vertex; } Debug.Log("TopLeft: " + TopLeft + "\nTopRight: " + TopRight + "\nBottomLeft: " + BottomLeft + "\nBottomRight: " + BottomRight); Mesh mesh = new Mesh(); mesh.vertices = vertices.ToArray(); float uTileWidth = (float)t.TileSet.TileWidth / (float)t.TileSet.Texture.width; float vTileHeight = (float)t.TileSet.TileHeight / (float)t.TileSet.Texture.height; float u = t.Source.x / (float)t.TileSet.Texture.width; float v = 1.0f - t.Source.y / (float)t.TileSet.Texture.height; mesh.uv = new Vector2[] { new Vector2(u + uTileWidth, v), new Vector2(u + uTileWidth, v - vTileHeight), new Vector2(u, v), new Vector2(u, v - vTileHeight) }; mesh.triangles = new int[] { 0, 1, 2, 2, 1, 3, }; mesh.RecalculateNormals(); mfilter.mesh = mesh; Material mat = new Material(Shader.Find("Unlit/Transparent")); mat.mainTexture = t.TileSet.Texture; mrender.material = mat; return obj; } */ // Renders the tile vertices. // Basically, it reads the tiles and creates its 4 vertexes (forming a rectangle or square according to settings) private void GenerateLayerMesh(Map map, List<Material> materials) { LayerGameObject = new GameObject(Name);//(GameObject)GameObject.Instantiate(Resources.Load("Tilemap"));// LayerGameObject.transform.position = new Vector3(0f,0f,0f); LayerMesh = new Mesh(); LayerMeshFilter = (MeshFilter)LayerGameObject.AddComponent("MeshFilter"); LayerMeshRenderer = (MeshRenderer)LayerGameObject.AddComponent("MeshRenderer"); List<Vector3> vertices = new List<Vector3>(); List<Vector2> uv = new List<Vector2>(); List<int> triangles = new List<int>(); List<Texture2D> textures = new List<Texture2D>(); Tile t; /*List<GameObject> meshes = new List<GameObject>(); Tile lastTile = null; int lastGID = -1; //int j = 0; for (int i = 0; i < Width; i++) { for (int j = 0; j < Height; j++) { t = Tiles[i, j]; if (t != null) { Debug.Log(t.GID); if (lastGID == t.GID) { vertices.AddRange(new Vector3[] { new Vector3 (t.Source.width / t.TileSet.TileWidth * (i + 1), t.Source.height / t.TileSet.TileHeight * -j, 0), new Vector3 (t.Source.width / t.TileSet.TileWidth * (i + 1), t.Source.height / t.TileSet.TileHeight * (-j - 1), 0), new Vector3 (t.Source.width / t.TileSet.TileWidth * i, t.Source.height / t.TileSet.TileHeight * -j, 0), new Vector3 (t.Source.width / t.TileSet.TileWidth * i, t.Source.height / t.TileSet.TileHeight * (-j - 1), 0) }); lastTile = t; } else { lastGID = t.GID; if(vertices.Count > 0) meshes.Add(GenerateSingleMesh(vertices, lastTile)); vertices.Clear(); vertices.AddRange(new Vector3[] { new Vector3 (t.Source.width / t.TileSet.TileWidth * (i + 1), t.Source.height / t.TileSet.TileHeight * -j, 0), new Vector3 (t.Source.width / t.TileSet.TileWidth * (i + 1), t.Source.height / t.TileSet.TileHeight * (-j - 1), 0), new Vector3 (t.Source.width / t.TileSet.TileWidth * i, t.Source.height / t.TileSet.TileHeight * -j, 0), new Vector3 (t.Source.width / t.TileSet.TileWidth * i, t.Source.height / t.TileSet.TileHeight * (-j - 1), 0) }); lastTile = t; } } j++; } } CombineInstance[] combine = new CombineInstance[meshes.Count]; List<Material> materials = new List<Material>(); for (int i = 0; i < meshes.Count; i++) { combine[i].mesh = meshes[i].GetComponent<MeshFilter>().mesh; combine[i].transform = meshes[i].GetComponent<MeshFilter>().transform.localToWorldMatrix; materials.Add(meshes[i].GetComponent<MeshRenderer>().material); } LayerMesh.CombineMeshes(combine); LayerMeshFilter.mesh = LayerMesh; LayerMeshRenderer.materials = materials.ToArray(); */ for (int i = 0; i < Width; i++) { for (int j = 0; j < Height; j++) { t = Tiles[i, j]; if(t != null) { // Add Tile's vertices to layer's mesh vertices.AddRange(new Vector3[] { new Vector3 (t.Source.width / t.TileSet.TileWidth * (i + 1), t.Source.height / t.TileSet.TileHeight * -j, 0), new Vector3 (t.Source.width / t.TileSet.TileWidth * (i + 1), t.Source.height / t.TileSet.TileHeight * (-j - 1), 0), new Vector3 (t.Source.width / t.TileSet.TileWidth * i, t.Source.height / t.TileSet.TileHeight * -j, 0), new Vector3 (t.Source.width / t.TileSet.TileWidth * i, t.Source.height / t.TileSet.TileHeight * (-j - 1), 0) }); // Generate this Tile's Triangles on Layer's mesh triangles.AddRange(new int[] { VertexCount, VertexCount + 1, VertexCount + 2, VertexCount + 2, VertexCount + 1, VertexCount + 3, }); VertexCount += 4; // Add Tile's texture source to textures list, to create the materials if (textures.Find(text => text.name == t.TileSet.Texture.name) == null) textures.Add(t.TileSet.Texture); // Save UV mapping of this Tile on it's texture //Debug.Log(t.Source); float uTileWidth = (float)t.TileSet.TileWidth / (float)t.TileSet.Texture.width; float vTileHeight = (float)t.TileSet.TileHeight / (float)t.TileSet.Texture.height; //float uBorderWidth = (float)t.TileSet.Spacing / t.TileSet.Texture.width; //float vBorderHeight = (float)t.TileSet.Spacing / t.TileSet.Texture.height; float u = t.Source.x / (float)t.TileSet.Texture.width;//(uTileWidth + uBorderWidth) * t.Source.x + uBorderWidth / 2; float v = 1.0f - t.Source.y / (float)t.TileSet.Texture.height;//1.0f - (vTileHeight - vBorderHeight) * t.Source.y - vBorderHeight / 2; uv.AddRange(new Vector2[] { new Vector2(u + uTileWidth, v), new Vector2(u + uTileWidth, v - vTileHeight), new Vector2(u, v), new Vector2(u, v - vTileHeight) }); } } } //t = null; LayerMesh.vertices = vertices.ToArray(); LayerMesh.uv = uv.ToArray(); LayerMesh.triangles = triangles.ToArray(); LayerMesh.RecalculateNormals(); LayerMeshFilter.mesh = LayerMesh; List<Material> layerMaterials = new List<Material>(); // Generate Materials for (int i = 0; i < textures.Count; i++) { //Material layerMat = new Material(Shader.Find("Unlit/Transparent")); //layerMat.mainTexture = textures[i]; //materials.Add(layerMat); for (int j = 0; j < materials.Count; j++) { if (materials[j].mainTexture.name == textures[i].name) layerMaterials.Add(materials[j]); } } LayerMeshRenderer.sharedMaterials = layerMaterials.ToArray(); LayerGameObject.transform.parent = map.Parent.transform; LayerGameObject.transform.position = new Vector3(0, 0, this.LayerDepth); Debug.Log(LayerGameObject.name + LayerGameObject.transform.position); LayerGameObject.isStatic = true; }
/// <summary> /// Creates a map object layer from .tmx /// </summary> /// <param name="node"></param> public MapObjectLayer(XElement node, Map tiledMap, int layerDepth, List<Material> materials) : base(node) { if (node.Attribute("color") != null) { // get the color string, removing the leading # string color = node.Attribute("color").Value.Substring(1); // get the RGB individually string r = color.Substring(0, 2); string g = color.Substring(2, 2); string b = color.Substring(4, 2); // convert to the color Color = new Color( (byte)int.Parse(r, NumberStyles.AllowHexSpecifier), (byte)int.Parse(g, NumberStyles.AllowHexSpecifier), (byte)int.Parse(b, NumberStyles.AllowHexSpecifier)); } Objects = new List<MapObject>(); foreach (XElement objectNode in node.Descendants("object")) { MapObject mapObjectContent = new MapObject(objectNode); //if (tiledMap.Orientation == Orientation.Orthogonal) //{ // mapObjectContent.ScaleObject(tiledMap.TileWidth, tiledMap.TileHeight); //} //// In Isometric maps, we must consider tile width == height for objects so their size can be correctly calculated //else if (tiledMap.Orientation == Orientation.Isometric) //{ // mapObjectContent.ScaleObject(tiledMap.TileHeight, tiledMap.TileHeight); //} //// In Staggered maps, we must pre-alter object position, as it comes mixed between staggered and orthogonal properties //else if (tiledMap.Orientation == Orientation.Staggered) //{ // float x = mapObjectContent.Bounds.x / (float)tiledMap.TileWidth; // float y = mapObjectContent.Bounds.y / (float)tiledMap.TileHeight * 2.0f; // float width = mapObjectContent.Bounds.width / (float)tiledMap.TileWidth; // float height = mapObjectContent.Bounds.height / (float)tiledMap.TileWidth; // if (Mathf.FloorToInt(Mathf.Abs(y)) % 2 > 0) // x -= 0.5f; // mapObjectContent.Bounds = new Rect(x, y, width, height); // if (mapObjectContent.Points != null) // { // for (int i = 0; i < mapObjectContent.Points.Count; i++) // { // mapObjectContent.Points[i] = new Vector2(mapObjectContent.Points[i].x / (float)tiledMap.TileWidth, mapObjectContent.Points[i].y / (float)tiledMap.TileHeight * 2.0f); // } // } //} mapObjectContent.ScaleObject(tiledMap.TileWidth, tiledMap.TileHeight, tiledMap.Orientation); mapObjectContent.Name = this.Name + "_" + mapObjectContent.Name; // Object names need to be unique for our lookup system, but Tiled // doesn't require unique names. string objectName = mapObjectContent.Name; int duplicateCount = 2; // if a object already has the same name... if (Objects.Find(o => o.Name.Equals(objectName)) != null) { // figure out a object name that does work do { objectName = string.Format("{0}{1}", mapObjectContent.Name, duplicateCount); duplicateCount++; } while (Objects.Find(o => o.Name.Equals(objectName)) != null); // log a warning for the user to see Debug.Log("Renaming object \"" + mapObjectContent.Name + "\" to \"" + objectName + "\" in layer \"" + Name + "\" to make a unique name."); // save that name mapObjectContent.Name = objectName; } mapObjectContent.CreateTileObject(tiledMap, Name, layerDepth, materials); AddObject(mapObjectContent); } }
public static void AddPolylineCollider3D(Map map, GameObject gameObject, MapObject obj, bool isTrigger = false, PhysicMaterial physicsMaterial = null, float zDepth = 0, float colliderWidth = 1.0f, bool innerCollision = false, bool createRigidbody = false, bool rigidbodyIsKinematic = true) { Mesh colliderMesh = new Mesh(); colliderMesh.name = "Collider_" + obj.Name; MeshCollider mc = gameObject.AddComponent<MeshCollider>(); mc.isTrigger = isTrigger || obj.Type.Equals(Map.Object_Type_Trigger); List<Vector3> vertices = new List<Vector3>(); List<int> triangles = new List<int>(); GenerateVerticesAndTris(map, obj.Points, vertices, triangles, zDepth, colliderWidth, innerCollision); colliderMesh.vertices = vertices.ToArray(); colliderMesh.uv = new Vector2[colliderMesh.vertices.Length]; //colliderMesh.uv1 = colliderMesh.uv; colliderMesh.uv2 = colliderMesh.uv; colliderMesh.triangles = triangles.ToArray(); colliderMesh.RecalculateNormals(); mc.sharedMesh = colliderMesh; if (physicsMaterial != null) mc.sharedMaterial = physicsMaterial; if (createRigidbody) { Rigidbody r = gameObject.AddComponent<Rigidbody>(); r.isKinematic = rigidbodyIsKinematic; } if (obj.Rotation != 0) gameObject.transform.localRotation = Quaternion.AngleAxis(obj.Rotation, Vector3.forward); if (obj.GetPropertyAsBoolean(Map.Property_CreateMesh)) { if (gameObject.GetComponent<MeshFilter>() == null) gameObject.AddComponent<MeshFilter>(); if (gameObject.GetComponent<MeshRenderer>() == null) gameObject.AddComponent<MeshRenderer>(); MeshFilter _meshFilter = gameObject.GetComponent<MeshFilter>(); if (mc != null) { mc.sharedMesh.RecalculateBounds(); mc.sharedMesh.RecalculateNormals(); MathfExtensions.CalculateMeshTangents(mc.sharedMesh); _meshFilter.sharedMesh = mc.sharedMesh; } } ApplyCustomProperties(gameObject, obj); // Link this collider to the MapObject obj.LinkedGameObject = gameObject; }
public static void AddPolylineCollider2D(Map map, GameObject gameObject, MapObject obj, bool isTrigger = false, PhysicsMaterial2D physicsMaterial = null, float zDepth = 0, bool createRigidbody = false, bool rigidbodyIsKinematic = true) { EdgeCollider2D edgeCollider = gameObject.AddComponent<EdgeCollider2D>(); edgeCollider.isTrigger = isTrigger || obj.Type.Equals(Map.Object_Type_Trigger); Vector2[] points = obj.Points.ToArray(); for (int i = 0; i < points.Length; i++) { points[i] = map.TiledPositionToWorldPoint(points[i].x, points[i].y); if (map.MapRenderParameter.Orientation == X_UniTMX.Orientation.Isometric) points[i].x -= map.MapRenderParameter.Width / 2.0f; } edgeCollider.points = points; if (physicsMaterial != null) edgeCollider.sharedMaterial = physicsMaterial; if (createRigidbody) { Rigidbody2D r = gameObject.AddComponent<Rigidbody2D>(); r.isKinematic = rigidbodyIsKinematic; } if (obj.Rotation != 0) gameObject.transform.localRotation = Quaternion.AngleAxis(obj.Rotation, Vector3.forward); ApplyCustomProperties(gameObject, obj); // Link this collider to the MapObject obj.LinkedGameObject = gameObject; }
public static void AddEllipseCollider3D(Map map, GameObject gameObject, MapObject obj, bool isTrigger = false, PhysicMaterial physicsMaterial = null, float zDepth = 0, float colliderWidth = 1.0f, bool createRigidbody = false, bool rigidbodyIsKinematic = true) { GameObject gameObjectMesh = null; if (map.MapRenderParameter.Orientation != X_UniTMX.Orientation.Isometric && obj.Bounds.width == obj.Bounds.height) { CapsuleCollider cc = null; if (obj.GetPropertyAsBoolean(Map.Property_CreateMesh)) { gameObjectMesh = GameObject.CreatePrimitive(PrimitiveType.Capsule); gameObjectMesh.name = obj.Name; gameObjectMesh.transform.parent = gameObject.transform; gameObjectMesh.transform.localPosition = new Vector3(obj.Bounds.height / 2.0f, -obj.Bounds.width / 2.0f); cc = gameObjectMesh.GetComponent<CapsuleCollider>(); cc.isTrigger = isTrigger || obj.Type.Equals(Map.Object_Type_Trigger); gameObjectMesh.transform.localScale = new Vector3(obj.Bounds.width, colliderWidth, obj.Bounds.height); gameObjectMesh.transform.localRotation = Quaternion.AngleAxis(90, Vector3.right); } else { cc = gameObject.AddComponent<CapsuleCollider>(); cc.isTrigger = isTrigger || obj.Type.Equals(Map.Object_Type_Trigger); cc.center = new Vector3(obj.Bounds.height / 2.0f, -obj.Bounds.width / 2.0f); cc.direction = 0; cc.radius = obj.Bounds.height / 2.0f; cc.height = obj.Bounds.width; } if (physicsMaterial != null) cc.sharedMaterial = physicsMaterial; } else { ApproximateEllipse3D(map, gameObject, obj, isTrigger, physicsMaterial, zDepth, colliderWidth, createRigidbody, rigidbodyIsKinematic); } if (createRigidbody) { Rigidbody r = gameObject.AddComponent<Rigidbody>(); r.isKinematic = rigidbodyIsKinematic; } if (obj.Rotation != 0) gameObject.transform.localRotation = Quaternion.AngleAxis(obj.Rotation, Vector3.forward); if (gameObjectMesh) ApplyCustomProperties(gameObjectMesh, obj); else ApplyCustomProperties(gameObject, obj); // Link this collider to the MapObject obj.LinkedGameObject = gameObject; }
// Callback for when the map has been loaded. void OnMapLoaded(Map map) { // Set the loaded map tiledMap = map; /* * Generate the map with the following options: * * TileManager's GameObject is the parent in the hierarchy * The default material is the default sprite's material */ tiledMap.Generate(this.gameObject, defaultMaterial); // Generate any tile collisions tiledMap.GenerateTileCollisions(); MapObjectLayer resourcesObjectLayer; // The object layer for resources // Check if the map has a resources object layer if ((resourcesObjectLayer = tiledMap.GetObjectLayer("Resources")) != null) { // Get the list of MapObjects on the resources layer List<MapObject> resourceObjects = resourcesObjectLayer.Objects; // Check if the game is new if (GameMaster.Instance.IsNew) { // The game is new so add all the resources to the list foreach (var resource in resourceObjects) { resourcePositions.Add(ToMap(resource.Bounds)); } // end foreach // Finally, save the resource positions list GameMaster.Instance.SaveResources(); } // end if else { // The game isn't new so load all the saved resources resourcePositions = GameMaster.Instance.LoadResources(); } // end else // Loop through the objects to check if they're on the resources list foreach (var resource in resourceObjects) { // Make sure the resource is in the list if (resourcePositions.Contains(ToMap(resource.Bounds))) { // Generate the prefab for the resource tiledMap.GeneratePrefab(resource, Vector2.zero, null, false, true); } // end if } // end foreach } // end if // Check if the map has a markets object layer if (tiledMap.GetObjectLayer("Markets") != null) { // Get the list of MapObjects on the markets layer List<MapObject> marketObjects = tiledMap.GetObjectLayer("Markets").Objects; // Add all the markets to the list foreach (var market in marketObjects) { marketPositions.Add(ToMap(market.Bounds)); } // end foreach // Generate the colliders from this layer tiledMap.GenerateCollidersFromLayer("Markets"); // Generate the prefabs from this layer tiledMap.GeneratePrefabsFromLayer("Markets", Vector2.zero, false, true); } // end if // Finally, Update the TileUtils static class SetDimensions(tiledMap.MapRenderParameter.TileHeight, tiledMap.MapRenderParameter.Width, tiledMap.MapRenderParameter.Height); }
void OnGenerateFinished(Map map) { tiledMap = map; Resources.UnloadUnusedAssets(); GenerateColliders(); GeneratePrefabs(); if (OnTiledMapInitialized != null) OnTiledMapInitialized(); }
// Renders the tile vertices. // Basically, it reads the tiles and creates its 4 vertexes (forming a rectangle or square according to settings) private void GenerateLayer(Map map, List<Material> materials) { LayerGameObject = new GameObject(Name); Tile t; // We must create tiles in reverse order so Z order is correct according to the majority of tilesets for (int x = Width - 1; x > -1; x--) { for (int y = Height - 1; y > -1; y--) { t = Tiles[x, y]; if(t != null) { Vector3 pos = Vector3.zero; // Set Tile's position according to map orientation // Can't use Map.TiledPositionToWorldPoint as sprites' anchors doesn't follow tile anchor point if (map.Orientation == Orientation.Orthogonal) { pos = new Vector3( x * (map.TileWidth / (float)t.TileSet.TileWidth), (-y - 1) * (map.TileHeight / (float)t.TileSet.TileHeight) * ((float)t.TileSet.TileHeight / (float)t.TileSet.TileWidth), 0); } else if (map.Orientation == Orientation.Isometric) { pos = new Vector3( (map.TileWidth / 2.0f * (map.Width - y + x) - t.TileSet.TileWidth / 2.0f) / (float)map.TileWidth, -map.Height + map.TileHeight * (map.Height - ((x + y) / (map.TileWidth / (float)map.TileHeight)) / 2.0f) / (float)map.TileHeight - (map.TileHeight / (float)map.TileWidth), 0); } else if (map.Orientation == Orientation.Staggered) { // In Staggered maps, odd rows and even rows are handled differently if (y % 2 < 1) { // Even row pos.x = x * (map.TileWidth / (float)t.TileSet.TileWidth); pos.y = (-y - 2) * (map.TileHeight / 2.0f / (float)t.TileSet.TileHeight) * ((float)t.TileSet.TileHeight / (float)t.TileSet.TileWidth); } else { // Odd row pos.x = x * (map.TileWidth / (float)t.TileSet.TileWidth) + (map.TileWidth / (float)t.TileSet.TileWidth) / 2.0f; pos.y = (-y - 2) * (map.TileHeight / 2.0f / (float)t.TileSet.TileHeight) * ((float)t.TileSet.TileHeight / (float)t.TileSet.TileWidth); } } // Create Tile's GameObject t.CreateTileObject(Name + "[" + x + ", " + y + "]", LayerGameObject.transform, Name, pos, materials, Opacity); } } } LayerGameObject.transform.parent = map.MapObject.transform; LayerGameObject.transform.localPosition = new Vector3(0, 0, this.LayerDepth); LayerGameObject.isStatic = true; LayerGameObject.SetActive(Visible); }
private static void ApproximateEllipse2D(Map map, GameObject newCollider, MapObject obj, bool isTrigger = false, PhysicsMaterial2D physicsMaterial = null, float zDepth = 0, bool createRigidbody = false, bool rigidbodyIsKinematic = true) { // since there's no "EllipseCollider2D", we must create one by approximating a polygon collider newCollider.transform.localPosition = map.TiledPositionToWorldPoint(obj.Bounds.x, obj.Bounds.y, zDepth); PolygonCollider2D polygonCollider = newCollider.AddComponent<PolygonCollider2D>(); polygonCollider.isTrigger = isTrigger || obj.Type.Equals(Map.Object_Type_Trigger); int segments = XUniTMXConfiguration.Instance.EllipsoideColliderApproximationFactor; // Segments per quadrant int incFactor = Mathf.FloorToInt(segments / 4.0f); float minIncrement = 2 * Mathf.PI / (incFactor * segments / 2.0f); int currentInc = 0; // grow represents if we are going right on x-axis (true) or left (false) bool grow = true; Vector2[] points = new Vector2[segments]; // Ellipsoide center Vector2 center = new Vector2(obj.Bounds.width / 2.0f, obj.Bounds.height / 2.0f); float r = 0; float angle = 0; for (int i = 0; i < segments; i++) { // Calculate radius at each point angle += currentInc * minIncrement; r = obj.Bounds.width * obj.Bounds.height / Mathf.Sqrt(Mathf.Pow(obj.Bounds.height * Mathf.Cos(angle), 2) + Mathf.Pow(obj.Bounds.width * Mathf.Sin(angle), 2)) / 2.0f; // Define the point localization using the calculated radius, angle and center points[i] = r * new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)) + center; points[i] = map.TiledPositionToWorldPoint(points[i].x, points[i].y); // Offset points where needed if (map.MapRenderParameter.Orientation == X_UniTMX.Orientation.Isometric) points[i].x -= map.MapRenderParameter.Width / 2.0f; if (map.MapRenderParameter.Orientation == X_UniTMX.Orientation.Staggered) points[i].y *= map.MapRenderParameter.TileWidth / (float)map.MapRenderParameter.TileHeight * 2.0f; if (map.MapRenderParameter.Orientation == X_UniTMX.Orientation.Hexagonal) { points[i].y *= map.MapRenderParameter.TileWidth / (float)map.MapRenderParameter.TileHeight * 2.0f; } // if we are "growing", increment the angle, else, start decrementing it to close the polygon if (grow) currentInc++; else currentInc--; if (currentInc > incFactor - 1 || currentInc < 1) grow = !grow; // POG :P -> Orthogonal and Staggered Isometric generated points are slightly offset on Y if (map.MapRenderParameter.Orientation != X_UniTMX.Orientation.Isometric) { if (i < 1 || i == segments / 2 - 1) points[i].y -= obj.Bounds.height / 20.0f; if (i >= segments - 1 || i == segments / 2) points[i].y += obj.Bounds.height / 20.0f; } } polygonCollider.SetPath(0, points); if (physicsMaterial != null) polygonCollider.sharedMaterial = physicsMaterial; }
public static void AddCollider3D(Map map, GameObject gameObject, MapObject obj, bool isTrigger = false, PhysicMaterial physicsMaterial = null, float zDepth = 0, float colliderWidth = 1, bool innerCollision = false, bool createRigidbody = false, bool rigidbodyIsKinematic = true) { switch (obj.ObjectType) { case ObjectType.Box: AddBoxCollider3D(map, gameObject, obj, isTrigger, physicsMaterial, zDepth, colliderWidth, createRigidbody, rigidbodyIsKinematic); break; case ObjectType.Ellipse: AddEllipseCollider3D(map, gameObject, obj, isTrigger, physicsMaterial, zDepth, colliderWidth, createRigidbody, rigidbodyIsKinematic); break; case ObjectType.Polygon: AddPolygonCollider3D(map, gameObject, obj, isTrigger, physicsMaterial, zDepth, colliderWidth, innerCollision, createRigidbody, rigidbodyIsKinematic); break; case ObjectType.Polyline: AddPolylineCollider3D(map, gameObject, obj, isTrigger, physicsMaterial, zDepth, colliderWidth, innerCollision, createRigidbody, rigidbodyIsKinematic); break; } }
/// <summary> /// Adds a 3D BoxCollider to a GameObject /// </summary> /// <param name="gameObject">GameObject to add the collider</param> /// <param name="obj">MapObject which properties will be used to generate this collider</param> /// <param name="isTrigger">True for Trigger Collider, false otherwise</param> /// <param name="physicsMaterial">PhysicMaterial to be set to the collider</param> /// <param name="zDepth">Z Depth of the collider</param> /// <param name="colliderWidth">Width of the collider, in Units</param> /// <param name="createRigidbody">True to attach a Rigidbody to the created collider</param> /// <param name="rigidbodyIsKinematic">Sets if the attached rigidbody is kinematic or not</param> public static void AddBoxCollider3D(Map map, GameObject gameObject, MapObject obj, bool isTrigger = false, PhysicMaterial physicsMaterial = null, float zDepth = 0, float colliderWidth = 1.0f, bool createRigidbody = false, bool rigidbodyIsKinematic = true) { GameObject gameObjectMesh = null; // Orthogonal and Staggered maps can use BoxCollider, Isometric maps must use polygon collider if (map.MapRenderParameter.Orientation != X_UniTMX.Orientation.Isometric) { BoxCollider boxCollider = null; if (obj.GetPropertyAsBoolean(Map.Property_CreateMesh)) { gameObjectMesh = GameObject.CreatePrimitive(PrimitiveType.Cube); gameObjectMesh.name = obj.Name; gameObjectMesh.transform.parent = gameObject.transform; gameObjectMesh.transform.localPosition = new Vector3(0.5f, -0.5f); boxCollider = gameObjectMesh.GetComponent<BoxCollider>(); } else { boxCollider = gameObject.AddComponent<BoxCollider>(); boxCollider.center = new Vector3(0.5f, -0.5f); } boxCollider.isTrigger = isTrigger || obj.Type.Equals(Map.Object_Type_Trigger); if (physicsMaterial != null) boxCollider.sharedMaterial = physicsMaterial; gameObject.transform.localScale = new Vector3(obj.Bounds.width, obj.Bounds.height, colliderWidth); } else { List<Vector2> points = new List<Vector2>(); points.Add(new Vector2(obj.Bounds.xMin - obj.Bounds.x, obj.Bounds.yMax - obj.Bounds.y)); points.Add(new Vector2(obj.Bounds.xMin - obj.Bounds.x, obj.Bounds.yMin - obj.Bounds.y)); points.Add(new Vector2(obj.Bounds.xMax - obj.Bounds.x, obj.Bounds.yMin - obj.Bounds.y)); points.Add(new Vector2(obj.Bounds.xMax - obj.Bounds.x, obj.Bounds.yMax - obj.Bounds.y)); X_UniTMX.MapObject isoBox = new MapObject(obj.Name, obj.Type, obj.Bounds, obj.Properties, obj.GID, points, obj.Rotation, obj.ParentObjectLayer); AddPolygonCollider3D(map, gameObject, isoBox, isTrigger, physicsMaterial, zDepth, colliderWidth); //gameObject = GeneratePolygonCollider3D(isoBox, isTrigger, zDepth, colliderWidth); } if (createRigidbody) { Rigidbody r = gameObject.AddComponent<Rigidbody>(); r.isKinematic = rigidbodyIsKinematic; } if (obj.Rotation != 0) gameObject.transform.localRotation = Quaternion.AngleAxis(obj.Rotation, Vector3.forward); if (gameObjectMesh != null) ApplyCustomProperties(gameObjectMesh, obj); else ApplyCustomProperties(gameObject, obj); // Link this collider to the MapObject obj.LinkedGameObject = gameObject; }
/// <summary> /// Creates this Tile Object (an object that has GID) if applicable /// </summary> /// <param name="tiledMap">The base Tile Map</param> public void CreateTileObject(Map tiledMap, string sortingLayerName, int layerDepth, List<Material> materials) { if(GID > 0) { Tile objTile = tiledMap.Tiles[GID].Clone(); objTile.CreateTileObject(Name, tiledMap.MapObject.transform, sortingLayerName, new Vector3(Bounds.x, -Bounds.y, layerDepth), materials); objTile.TileObject.SetActive(Visible); } }
private void Initialize(Map map, uint[] data, bool makeUnique, List<Material> materials) { Tiles = new TileGrid(Width, Height); // data is left-to-right, top-to-bottom for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { uint index = data[y * Width + x]; // compute the SpriteEffects to apply to this tile SpriteEffects spriteEffects = SpriteEffects.None; if ((index & FlippedHorizontallyFlag) != 0) spriteEffects |= SpriteEffects.FlipHorizontally; if ((index & FlippedVerticallyFlag) != 0) spriteEffects |= SpriteEffects.FlipVertically; // strip out the flip flags to get the real ID int id = (int)(index & ~(FlippedVerticallyFlag | FlippedHorizontallyFlag)); //Debug.Log("Tile ID: " + id + " (index : " + index + ")"); // get the tile Tile t = null; map.Tiles.TryGetValue(id, out t); // if the tile is non-null... if (t != null) { // if we want unique instances, clone it if (makeUnique) { t = t.Clone(); t.SpriteEffects = spriteEffects; } // otherwise we may need to clone if the tile doesn't have the correct effects // in this world a flipped tile is different than a non-flipped one; just because // they have the same source rect doesn't mean they're equal. else if (t.SpriteEffects != spriteEffects) { t = t.Clone(); t.SpriteEffects = spriteEffects; } } // put that tile in our grid Tiles[x, y] = t; } } GenerateLayer(map, materials); }
private static void CreateFrontBackPoints(Map map, Vector3 refPoint, out Vector3 refFront, out Vector3 refBack, float zDepth, float colliderWidth, bool calculateWorldPos = true, bool ignoreOrientation = false) { if (calculateWorldPos) { refFront = map.TiledPositionToWorldPoint(refPoint.x, refPoint.y, zDepth - colliderWidth / 2.0f); refBack = map.TiledPositionToWorldPoint(refPoint.x, refPoint.y, zDepth + colliderWidth / 2.0f); } else { refFront = new Vector3(refPoint.x, refPoint.y, zDepth - colliderWidth / 2.0f); refBack = new Vector3(refPoint.x, refPoint.y, zDepth + colliderWidth / 2.0f); } if (!ignoreOrientation && map.MapRenderParameter.Orientation == X_UniTMX.Orientation.Isometric) { refFront.x -= map.MapRenderParameter.Width / 2.0f; refBack.x -= map.MapRenderParameter.Width / 2.0f; } }
private void Initialize(Map map, uint[] data, List<Material> materials) { Tiles = new TileGrid(Width, Height); BaseMap = map; BaseMaterials = materials; LayerTileSets = new List<TileSet>(); // data is left-to-right, top-to-bottom for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { uint id = data[y * Width + x]; // compute the SpriteEffects to apply to this tile SpriteEffects spriteEffects = new SpriteEffects(); // MARIO: new method to verify flipped tiles spriteEffects.flippedHorizontally = (id & FlippedHorizontallyFlag) == FlippedHorizontallyFlag; spriteEffects.flippedVertically = (id & FlippedVerticallyFlag) == FlippedVerticallyFlag; spriteEffects.flippedAntiDiagonally = (id & FlippedAntiDiagonallyFlag) == FlippedAntiDiagonallyFlag; // MARIO: new strip out the flip flags to get the real ID // Fixed for AntiDiagonallyFlgs id &= ~(FlippedHorizontallyFlag | FlippedVerticallyFlag | FlippedAntiDiagonallyFlag); // get the tile Tile t = null; BaseMap.Tiles.TryGetValue((int)id, out t); // if the tile is non-null... if (t != null) { // if we want unique instances, clone it if (MakeUniqueTiles) { t = t.Clone(); t.SpriteEffects = spriteEffects; } // otherwise we may need to clone if the tile doesn't have the correct effects // in this world a flipped tile is different than a non-flipped one; just because // they have the same source rect doesn't mean they're equal. else if (t.SpriteEffects != spriteEffects) { t = t.Clone(); t.SpriteEffects = spriteEffects; } // Add this Tile's TileSet to LayerTileSets list, if it is not there yet if (!LayerTileSets.Contains(t.TileSet)) LayerTileSets.Add(t.TileSet); } // put that tile in our grid Tiles[x, y] = t; } } GenerateLayer(); }
private static void GenerateVerticesAndTris(Map map, List<Vector2> points, List<Vector3> generatedVertices, List<int> generatedTriangles, float zDepth = 0, float colliderWidth = 1.0f, bool innerCollision = false, bool calculateWorldPos = true, bool ignoreOrientation = false) { Vector3 firstPoint = (Vector3)points[0]; Vector3 firstFront = Vector3.zero, firstBack = Vector3.zero, secondPoint = Vector3.zero, secondFront = Vector3.zero, secondBack = Vector3.zero; CreateFrontBackPoints(map, firstPoint, out firstFront, out firstBack, zDepth, colliderWidth, calculateWorldPos, ignoreOrientation); if (innerCollision) { generatedVertices.Add(firstBack); // 3 generatedVertices.Add(firstFront); // 2 } else { generatedVertices.Add(firstFront); // 3 generatedVertices.Add(firstBack); // 2 } // Calculate line planes for (int i = 1; i < points.Count; i++) { secondPoint = (Vector3)points[i]; CreateFrontBackPoints(map, secondPoint, out secondFront, out secondBack, zDepth, colliderWidth, calculateWorldPos, ignoreOrientation); if (innerCollision) { generatedVertices.Add(secondBack); // 1 generatedVertices.Add(secondFront); // 0 } else { generatedVertices.Add(secondFront); // 1 generatedVertices.Add(secondBack); // 0 } generatedTriangles.Add((i - 1) * 2 + 3); generatedTriangles.Add((i - 1) * 2 + 2); generatedTriangles.Add((i - 1) * 2 + 0); generatedTriangles.Add((i - 1) * 2 + 0); generatedTriangles.Add((i - 1) * 2 + 1); generatedTriangles.Add((i - 1) * 2 + 3); firstPoint = secondPoint; firstFront = secondFront; firstBack = secondBack; } }
/// <summary> /// Creates this Tile Object (an object that has OriginalID) if applicable /// </summary> /// <param name="tiledMap">The base Tile Map</param> /// <param name="layerDepth">Layer's zDepth</param> /// <param name="sortingLayerName">Layer's SortingLayerName</param> /// <param name="parent">Transform to parent this object to</param> /// <param name="materials">List of TileSet Materials</param> public void CreateTileObject(Map tiledMap, string sortingLayerName, int layerDepth, List<Material> materials, Transform parent = null) { if(GID > 0) { Tile objTile = null; if(tiledMap.Orientation != Orientation.Orthogonal) objTile = tiledMap.Tiles[GID].Clone(new Vector2(0.5f, 0.5f)); else objTile = tiledMap.Tiles[GID].Clone(); //string sortingLayer = GetPropertyAsString("SortingLayer"); //int sortingOrder = GetPropertyAsInt("SortingOrder"); objTile.CreateTileObject(Name, parent != null ? parent : ParentObjectLayer.LayerGameObject.transform, sortingLayerName, tiledMap.DefaultSortingOrder + tiledMap.GetSortingOrder(Bounds.x, Bounds.y), tiledMap.TiledPositionToWorldPoint(Bounds.x, Bounds.y, layerDepth), materials); this.Bounds = new Rect(Bounds.x, Bounds.y - 1, 1, 1); /*Debug.Log(Bounds); tiledMap.AddBoxCollider(objTile.TileGameObject, this);*/ objTile.TileGameObject.SetActive(Visible); } }
public static void AddEllipseCollider2D(Map map, GameObject gameObject, MapObject obj, bool isTrigger = false, PhysicsMaterial2D physicsMaterial = null, float zDepth = 0, bool createRigidbody = false, bool rigidbodyIsKinematic = true) { if (map.MapRenderParameter.Orientation != X_UniTMX.Orientation.Isometric && obj.Bounds.width == obj.Bounds.height) { CircleCollider2D cc = gameObject.AddComponent<CircleCollider2D>(); cc.isTrigger = isTrigger || obj.Type.Equals(Map.Object_Type_Trigger); gameObject.transform.localPosition = map.TiledPositionToWorldPoint(obj.Bounds.x, obj.Bounds.y, zDepth); #if UNITY_5 cc.offset = new Vector2(obj.Bounds.width / 2.0f, -obj.Bounds.height / 2.0f); #else cc.center = new Vector2(obj.Bounds.width / 2.0f, -obj.Bounds.height / 2.0f); #endif cc.radius = obj.Bounds.width / 2.0f; if (physicsMaterial != null) cc.sharedMaterial = physicsMaterial; } else { ApproximateEllipse2D(map, gameObject, obj, isTrigger, physicsMaterial, zDepth, createRigidbody, rigidbodyIsKinematic); } if (createRigidbody) { Rigidbody2D r = gameObject.AddComponent<Rigidbody2D>(); r.isKinematic = rigidbodyIsKinematic; } if (obj.Rotation != 0) gameObject.transform.localRotation = Quaternion.AngleAxis(obj.Rotation, Vector3.forward); ApplyCustomProperties(gameObject, obj); // Link this collider to the MapObject obj.LinkedGameObject = gameObject; }