public static bool IsLayerIn(LayerTypeSelection SpecifyLayers, LayerType Layer) { LayerTypeSelection LayerCon = LayerType2LayerTypeSelection(Layer); //Bits are set in SpecifyLayers, doing a logical AND with the layer will return either 0 if it doesn't contain it or the layer bit itself. return((SpecifyLayers & LayerCon) > 0); }
/// <summary> /// Returns all colliders found in the cone of sight /// Provide the direction to look and /// include the layers you want to test for in the hitMask /// </summary> public List <MatrixManager.CollisionHit> GetObjectsInSight(LayerMask hitMask, LayerTypeSelection hitLayers, Vector2 direction, float lengthOfSight, int rayCount = 5) { var angleOfDir = Vector3.Angle(direction, transform.up); var cw = Vector3.Cross(transform.up, direction).z < 0f; if (!cw) { angleOfDir = -angleOfDir; } var offsetDegrees = fieldOfView / 2f; List <MatrixManager.CollisionHit> hitColls = new List <MatrixManager.CollisionHit>(); for (int i = 0; i < rayCount; i++) { var step = (float)i / ((float)rayCount - 1); var offset = Mathf.Lerp(-offsetDegrees, offsetDegrees, step); var castDir = (Quaternion.AngleAxis(-angleOfDir, Vector3.forward) * Quaternion.Euler(0, 0, -offset)) * Vector3.up; var hit = MatrixManager.RayCast(transform.position + castDir, castDir, lengthOfSight, hitLayers, hitMask); // Debug.DrawRay(transform.position, castDir, Color.blue, 10f); if (hit.ItHit) { hitColls.Add(hit.CollisionHit); } } return(hitColls); }
/// <summary> /// Returns the furthest unhindered position possible in the cone of sight. /// A world position is returned. It is advisable to use this /// with matrix manager so all matricies are considered /// </summary> public Vector2 GetFurthestPositionInSight(Vector2 originWorldPos, LayerTypeSelection layerMask, LayerMask hitMask, Vector2 direction, float lengthOfSight, int rayCount = 5) { var angleOfDir = Vector3.Angle(direction, transform.up); var cw = Vector3.Cross(transform.up, direction).z < 0f; if (!cw) { angleOfDir = -angleOfDir; } var offsetDegrees = fieldOfView / 2f; var furthestDist = 0f; var furthestPoint = Vector2.zero; //First see how far the initial direction is var dirHit = MatrixManager.RayCast(originWorldPos, direction, lengthOfSight, layerMask, hitMask); // Debug.DrawRay(originWorldPos, direction, Color.red, 10f); if (dirHit.ItHit == false) { furthestDist = lengthOfSight; furthestPoint = originWorldPos + ((direction * lengthOfSight) - direction); } else { furthestDist = dirHit.Distance; furthestPoint = originWorldPos + ((direction * dirHit.Distance) - direction); } //now test all rays in the cone of sight: for (int i = 0; i < rayCount; i++) { var step = (float)i / ((float)rayCount - 1); var offset = Mathf.Lerp(-offsetDegrees, offsetDegrees, step); var castDir = (Quaternion.AngleAxis(-angleOfDir, Vector3.forward) * Quaternion.Euler(0, 0, -offset)) * Vector3.up; var hit = MatrixManager.RayCast(originWorldPos, castDir, lengthOfSight, layerMask, hitMask); // Debug.DrawRay(originWorldPos, castDir, Color.blue, 10f); if (hit.ItHit) { if (hit.Distance > furthestDist) { //this ray is longer, calculate the general position: furthestDist = hit.Distance; furthestPoint = originWorldPos + (Vector2)((castDir * hit.Distance) - (castDir * 1.5f)); } } } return(furthestPoint); }
/// <summary> /// Gets the topmost tile at the specified cell position , Whilst ignoring the specified tiles in the ExcludedLayers /// </summary> /// <param name="cellPosition">cell position within the tilemap to get the tile of. NOT the same /// as world position.</param> /// <returns></returns> public LayerTile GetTile(Vector3Int cellPosition, LayerTypeSelection ExcludedLayers) { for (var i = 0; i < LayersValues.Length; i++) { LayerTile tile = LayersValues[i].GetTile(cellPosition); if (tile != null) { if (LTSUtil.IsLayerIn(ExcludedLayers, tile.LayerType)) { continue; } return(tile); } } return(null); }
/// <summary> /// Returns all colliders found in the cone of sight /// Provide the direction to look and /// include the layers you want to test for in the hitMask /// </summary> public List <GameObject> GetObjectsInSight(LayerMask hitMask, LayerTypeSelection hitLayers, Vector2 direction, float lengthOfSight) { var angleOfDir = Vector3.Angle(direction, transform.up); var cw = Vector3.Cross(transform.up, direction).z < 0f; if (!cw) { angleOfDir = -angleOfDir; } var offsetDegrees = fieldOfView / 2f; List <GameObject> hitColls = new List <GameObject>(); var Hits = Physics2D.OverlapCircleAll(transform.position, lengthOfSight, hitMask); var v1 = transform.position + (Quaternion.AngleAxis(-angleOfDir, Vector3.forward) * Quaternion.Euler(0, 0, -offsetDegrees)) * Vector3.up * lengthOfSight; var v2 = transform.position + (Quaternion.AngleAxis(-angleOfDir, Vector3.forward) * Quaternion.Euler(0, 0, offsetDegrees)) * Vector3.up * lengthOfSight; foreach (var hit in Hits) { if (IsInsideSector(hit.transform.position.To2(), transform.position.To2(), transform.position.To2() - v2.To2(), transform.position.To2() - v1.To2())) { var RayHit = MatrixManager.RayCast(transform.position, Vector2.zero, lengthOfSight, hitLayers, WorldTo: hit.gameObject.transform.position); if (RayHit.ItHit == false) //No obstructions { hitColls.Add(hit.gameObject); } } } return(hitColls); }
/// <summary> /// Gets the topmost tile at the specified cell position , Whilst ignoring the specified tiles in the ExcludedLayers /// </summary> /// <param name="cellPosition">cell position within the tilemap to get the tile of. NOT the same /// as world position.</param> /// <returns></returns> public LayerTile GetTile(Vector3Int cellPosition, LayerTypeSelection ExcludedLayers) { TileLocation TileLcation = null; foreach (var layer in LayersValues) { if (layer.LayerType == LayerType.Objects) { continue; } if (LTSUtil.IsLayerIn(ExcludedLayers, layer.LayerType)) { continue; } lock (PresentTiles) { PresentTiles[layer].TryGetValue(cellPosition, out TileLcation); } if (TileLcation != null) { break; } } return(TileLcation?.Tile); // for (var i = 0; i < LayersValues.Length; i++) // { // LayerTile tile = LayersValues[i].GetTile(cellPosition); // if (tile != null) // { // if (LTSUtil.IsLayerIn(ExcludedLayers, tile.LayerType)) continue; // return tile; // } // } // return null; }
public static CustomPhysicsHit RayCast(Vector3 Worldorigin, Vector2 direction, float distance, LayerTypeSelection layerMask, LayerMask?Layermask2D = null, Vector3?WorldTo = null) { Worldorigin.z = 0; //TODO RRT //get to from vector CustomPhysicsHit?ClosestHit = null; CustomPhysicsHit?Checkhit = null; // Vector3 Localdorigin = Vector3.zero; // Vector3 LocalTo = Vector3.zero; if (WorldTo == null) { WorldTo = Worldorigin + (Vector3)(direction.normalized * distance); } if (direction.x == 0 && direction.y == 0) { direction = (WorldTo.Value - Worldorigin).normalized; } if (layerMask != LayerTypeSelection.None) { for (var i = Instance.ActiveMatrices.Count - 1; i >= 0; i--) { MatrixInfo mat = Instance.ActiveMatrices[i]; //if (mat.Matrix == Instance.spaceMatrix) continue; if (LineIntersectsRect(Worldorigin, (Vector2)WorldTo, mat.WorldBounds)) { Checkhit = mat.MetaTileMap.Raycast(Worldorigin.ToLocal(mat.Matrix), Vector2.zero, distance, layerMask, WorldTo.Value.ToLocal(mat.Matrix)); if (Checkhit != null) { if (ClosestHit != null) { if (ClosestHit.Value.Distance < Checkhit.Value.Distance) { ClosestHit = Checkhit; } } else { ClosestHit = Checkhit; } } } } } if (Layermask2D != null) { var Hit2D = Physics2D.Raycast(Worldorigin, direction.normalized, distance, Layermask2D.Value); if (ClosestHit != null) { if (Hit2D.distance != 0 && ClosestHit.Value.Distance > Hit2D.distance) { ClosestHit = new CustomPhysicsHit(Hit2D); } } else { ClosestHit = new CustomPhysicsHit(Hit2D); } } if (ClosestHit == null) { ClosestHit = new CustomPhysicsHit(); } return(ClosestHit.Value); }
public static CustomPhysicsHit Linecast(Vector3 Worldorigin, LayerTypeSelection layerMask, LayerMask?Layermask2D, Vector3 WorldTo) { return(RayCast(Worldorigin, Vector2.zero, 0, layerMask, Layermask2D, WorldTo)); }
/// <summary> /// Gets the LayerTile of the tile at the indicated position, null if no tile there (open space). /// </summary> /// <param name="worldPos"></param> /// <returns></returns> public LayerTile LayerTileAt(Vector2 worldPos, LayerTypeSelection ExcludedLayers) { Vector3Int pos = objectLayer.transform.InverseTransformPoint(worldPos).RoundToInt(); return(metaTileMap.GetTile(pos, ExcludedLayers)); }
//Gets the first hit public MatrixManager.CustomPhysicsHit? Raycast( Vector2 origin, Vector2 direction, float distance, LayerTypeSelection layerMask, Vector2? To = null) { if (To == null) { To = direction.normalized * distance; } if (direction.x == 0 && direction.y == 0) { direction = (To.Value - origin).normalized; distance = (To.Value - origin).magnitude; } // var Beginning = (new Vector3((float) origin.x, (float) origin.y, 0).ToWorld(PresentMatrix)); // Debug.DrawLine(Beginning + (Vector3.right * 0.09f), Beginning + (Vector3.left * 0.09f), Color.yellow, 30); // Debug.DrawLine(Beginning + (Vector3.up * 0.09f), Beginning + (Vector3.down * 0.09f), Color.yellow, 30); // var end = (new Vector3((float) To.Value.x, (float) To.Value.y, 0).ToWorld(PresentMatrix)); // Debug.DrawLine(end + (Vector3.right * 0.09f), end + (Vector3.left * 0.09f), Color.red, 30); // Debug.DrawLine(end + (Vector3.up * 0.09f), end + (Vector3.down * 0.09f), Color.red, 30); // Debug.DrawLine(Beginning, end, Color.magenta, 30); Vector2 Relativetarget = To.Value - origin; //custom code on tile to ask if it aptly got hit, if you want custom geometry // //What needs to be returned //What it hit, game object/tile //Normal of hit //Can be done quite easily since we know if me moving left or right //Static manager //Calculate if Within bounds of matrix? //End and start World pos // //Calculate offset to then put onto positions, Maybe each position gets its own Calculation double RelativeX = 0; double RelativeY = 0; double gridOffsetx = 0; double gridOffsety = 0; int xSteps = 0; int ySteps = 0; int stepX = 0; int stepY = 0; double Offsetuntouchx = (origin.x - Math.Round(origin.x)); double Offsetuntouchy = (origin.y - Math.Round(origin.y)); if (direction.x < 0) { gridOffsetx = -(-0.5d + Offsetuntouchx); //0.5f //this is So when you multiply it gives you 0.5 that some tile borders stepX = -1; //For detecting which Tile it hits } else { gridOffsetx = -0.5d - Offsetuntouchx; //-0.5f stepX = 1; //sideDistX = (mapX + 1.0 - posX) * deltaDistX; } if (direction.y < 0) { gridOffsety = -(-0.5d + Offsetuntouchy); // 0.5f stepY = -1; //sideDistY = (posY - mapY) * deltaDistY; } else { gridOffsety = -0.5d - Offsetuntouchy; //-0.5f stepY = 1; //sideDistY = (mapY + 1.0 - posY) * deltaDistY; } var vec = Vector3Int.zero; //Tile it hit Local Coordinates var vecHit = Vector3.zero; //Coordinates of Edge tile hit TileLocation TileLcation = null; var vexinvX = (1d / (direction.x)); //Editions need to be done here for Working offset var vexinvY = (1d / (direction.y)); //Needs to be conditional double calculationFloat = 0; bool LeftFaceHit = true; while (Math.Abs((xSteps + gridOffsetx + stepX) * vexinvX) < distance || Math.Abs((ySteps + gridOffsety + stepY) * vexinvY) < distance) //for (int Ai = 0; Ai < 6; Ai++) { //if (xBuildUp > yBuildUp) if ((xSteps + gridOffsetx + stepX) * vexinvX < (ySteps + gridOffsety + stepY) * vexinvY ) // which one has a lesser multiplication factor since that will give a less Magnitude { xSteps += stepX; calculationFloat = ((xSteps + gridOffsetx) * vexinvX); RelativeX = direction.x * calculationFloat; //Remove offset here maybe? RelativeY = direction.y * calculationFloat; LeftFaceHit = true; } //else if (xBuildUp < yBuildUp) else //if (xBuildUp < yBuildUp) { ySteps += stepY; calculationFloat = ((ySteps + gridOffsety) * vexinvY); RelativeX = direction.x * calculationFloat; RelativeY = direction.y * calculationFloat; LeftFaceHit = false; } vec.x = (int)Mathf.Round(origin.x) + xSteps; vec.y = (int)Mathf.Round(origin.y) + ySteps; vecHit.x = origin.x + (float)RelativeX; //+ offsetX; vecHit.y = origin.y + (float)RelativeY; // + offsetY; //Check point here if (LeftFaceHit) { // float TestX = ((vecHit.x - 0.5f) - Mathf.Floor(vecHit.x)); // if (0.05f < Math.Abs(TestX)) // { // Logger.Log("Offsetuntouchx = " + Offsetuntouchx + "\n" + "directionx = " + direction.x + "\n" + // "Step = " + xSteps + "\n" + "vexinv = " + vexinvX + "\n" + "offset = " + offsetX + // "\n" + "\n" + "Test =" + TestX + "\n" + "Relative =" + (RelativeX) // + "\n" + "\n" // + " direction.x = " + direction.x + " calculationFloat " + calculationFloat // + "\n" + " xSteps " + xSteps + " gridOffsetx " + gridOffsetx +" vexinvX " + vexinvX); // } } else { // float Testy = ((vecHit.y - 0.5f) - Mathf.Floor(vecHit.y)); // if (0.05f < Math.Abs(Testy)) // { // Logger.Log("Offsetuntouchx = " + Offsetuntouchy + "\n" + "directionx = " + direction.y + "\n" + // "Step = " + ySteps + "\n" + "vexinv = " + vexinvY + "\n" + "offset = " + offsetY + // "\n" + "\n" + "Test =" + Testy + "\n" + "Relative =" + (RelativeY) // + "\n" + "\n" // + " direction.y = " + direction.y + " calculationFloat " + calculationFloat // + "\n" + " ySteps " + ySteps + " gridOffsety " + gridOffsety +" vexinvY " + vexinvY); // } } for (var i = 0; i < LayersValues.Length; i++) { if (LayersValues[i].LayerType == LayerType.Objects) { continue; } if (LTSUtil.IsLayerIn(layerMask, LayersValues[i].LayerType)) { lock (PresentTiles) { PresentTiles[LayersValues[i]].TryGetValue(vec, out TileLcation); } // var wold = (vecHit.ToWorld(PresentMatrix)); // Debug.DrawLine(wold + (Vector3.right * 0.09f), wold + (Vector3.left * 0.09f), Color.green, 30); // Debug.DrawLine(wold + (Vector3.up * 0.09f), wold + (Vector3.down * 0.09f), Color.green, 30); // if (LeftFaceHit) // { // Debug.DrawLine(wold + (Vector3.up * 4f), wold + (Vector3.down * 4), Color.blue, 30); // } // else // { // Debug.DrawLine(wold + (Vector3.right * 4), wold + (Vector3.left * 4), Color.blue, 30); // } // ColorUtility.TryParseHtmlString("#ea9335", out var Orange); // var map = ((Vector3) vec).ToWorld(PresentMatrix); // Debug.DrawLine(map + (Vector3.right * 0.09f), map + (Vector3.left * 0.09f), Orange, 30); // Debug.DrawLine(map + (Vector3.up * 0.09f), map + (Vector3.down * 0.09f), Orange, 30); if (TileLcation != null) { Vector2 normal; if (LeftFaceHit) { normal = Vector2.left * stepX; } else { normal = Vector2.down * stepY; } Vector3 AdjustedNormal = ((Vector3)normal).ToWorld(PresentMatrix); AdjustedNormal = AdjustedNormal - (Vector3.zero.ToWorld(PresentMatrix)); // Debug.DrawLine(wold, wold + AdjustedNormal, Color.cyan, 30); return(new MatrixManager.CustomPhysicsHit(((Vector3)vec).ToWorld(PresentMatrix), (vecHit).ToWorld(PresentMatrix), AdjustedNormal, new Vector2((float)RelativeX, (float)RelativeY).magnitude, TileLcation)); } } } } return(null); }
public static bool IsLayerIn(LayerTypeSelection SpecifyLayers, LayerType Layer) { LayerTypeSelection LayerCon = LayerType2LayerTypeSelection(Layer); return(SpecifyLayers.HasFlag(LayerCon)); }