Решение "Нет математики"
Возможно, у меня есть решение для вас. Я немного ленивый человек и очень плохо разбираюсь в математике ... поэтому я обычно позволяю Unity выполнять за меня математику в ситуациях, подобных вашей;)
Для этого вам понадобится один выделенный GameObject, который вращается так, как он представляет «вращение» сетки, поэтому 0,45,0
.
Тогда - поскольку ваши плитки всегда движутся с шагом ровно 1
только в повернутой системе координат - вы можете даже не использовать расстояние на основе индекса, а напрямую сравнивать абсолютные позиции, используя Transform.InverseTransformPoint
в Для того чтобы получить позиции относительно этого повернутого объекта.
InverseTransformPoint
переустанавливает, как указано, данную мировую позицию в локальном пространстве используемого преобразования, так что если объект был первоначально размещен, например, в. x=1, z=1
в нашем повернутом локальном пространстве он будет иметь позицию z=1.1414..., x=0
.
Я просто прикрепил этот компонент к моему повернутому объекту .. на самом деле, я добавляю Awake
, просто чтобы быть уверенным;)
public class PositionsManager : MonoBehaviour
{
// I know .. singleton pattern .. buuu
// but that's the fastest way to prototype ;)
public static PositionsManager Singleton;
private void Awake()
{
// just for making sure this object is at world origin
transform.position = Vector3.zero;
// rotate the object liek you need it
// possible that in your case you rather wanted -45°
transform.eulerAngles = new Vector3(0, 45, 0);
// since InverseTransformPoint is affacted by scale
// just make sure this object has the default scale
transform.localScale = Vector3.one;
// set the singleton so we can easily access this reference
Singleton = this;
}
public Vector2Int GetDistance(Transform from, Transform to)
{
var localPosFrom = transform.InverseTransformPoint(from.position);
var localPosTo = transform.InverseTransformPoint(to.position);
// Now you can simply get the actual position distance and return
// them as vector2 so you can even still see the components
// seperately
var difference = localPosTo - localPosFrom;
// since you are using X-Z not X-Y you have to convert the vector "manually"
return new Vector2Int(Mathf.RoundToInt(difference.x), Mathf.RoundToInt(difference.z));
}
public int GetAbsoluteDistance(Transform from, Trasnform to)
{
var difference = GetDistance(from, to);
return Mathf.Abs(difference.x) + Mathf.Abs(difference.y);
}
}
Теперь, когда вам нужно получить абсолютное расстояние, вы можете просто сделать
var difference = PositionsManager.Singleton.GetDistance(objectA.transform, objectB.transform);
var absoluteDistance = PositionsManager.Singleton.GetAbsoluteDistance(objectA.transform, objectB.transform);
Little Demo (использовал ящик для шахматной доски, так как у меня был ^^)
Математическое решение
Это только что пришло ко мне во время написания верхнего объяснения:
Вы уже знаете свои шаги между плитками: Это всегда Mathf.Sqrt(2)
!
Итак, снова вы можете просто использовать абсолютные позиции в вашем мире и сравнивать их как
private float Sqrt2;
private void Awake()
{
Sqrt2 = Mathf.Sqrt(2);
}
...
// devide the actual difference by Sqrt(2)
var difference = (objectA.position - objectB.position) / Mathf.Sqrt(2);
// again set the Vector2 manually since we use Z not Y
// This step is optional if you anyway aren't interrested in the Vector2
// distance .. jsut added it for completeness
// You might need the rounding part though
var fixedDifference = new Vector2Int(Mathf.RoundToInt(difference.x), Mathf.RoundToInt(difference.z));
// get the absolute difference
var absoluteDistance = Mathf.Abs(fixedDifference.x) + Mathf.Abs(fixedDifference.y);
...
все еще полностью без необходимости иметь дело с индексами вообще.