目前我正在構建一個飛行模擬器,并正在考慮限制玩家飛行路徑范圍的方法。
(使用 collider 的能力,例如 OverlapSphere,可以使其更簡單,但在這種情況下無法做到。)
假設從點 1 到點 2 有明確的飛行路徑,飛行限制設定在兩點之間的一定區域內,當超出范圍時,會發出警報并回傳到原來的位置。
情況1示例情況2
示例
除了其他的,必須在兩點之間的路徑上計算出一定的飛行限制區域,并且可以檢測到偏離該區域,但是對于我的數學能力是沒有希望的,我不知道如何處理這個.
我需要有關此計算的幫助或對其他想法的意見。
uj5u.com熱心網友回復:
我認為您只需將其分為 3 種可能的情況進行測驗:
plane在一定距離內A相當瑣碎
var planePosition = plane.transform.position; planePosition.y = 0; var aPosition = A.transform.position; aPosition.y = 0; if(Vector3.Distance(planePosition, aPosition) <= range) { return true; }plane在一定距離內B基本一樣
var planePosition = plane.transform.position; planePosition.y = 0; var bPosition = B.transform.position; bPosition.y = 0; if(Vector3.Distance(planePosition, bPosition) <= range) { return true; }plane在A 和 B 之間具有一定寬度(2x 范圍)的矩形內// vector A -> B var delta = bPosition - aPosition; var distance = delta.magnitude; // direction A -> B with normalized length 1 var direction = delta.normalized; // direction perpendicular to world Up and "direction" var cross = Vector3.Cross(direction, Vector3.up).normalized; // So now we can get our 4 rect points like var rectA = aPosition cross * range; var rectB = aPosition - cross * range; var rectC = bPosition cross * range; var rectD = bPosition - cross * range; // and now we can use the area check formular from the link var areaRect = cross * 2 * distance; var areaAPD = Mathf.Abs((planePosition.x * rectA.z - rectA.x * planePosition.z) (planePosition.x * rectD.z - rectD.x * planePosition.z) (rectA.x * rectD.z - rectD.x * rectA.z)) / 2f; var areaDPC = Mathf.Abs((planePosition.x * rectD.z - rectD.x * planePosition.z) (planePosition.x * rectC.z - rectC.x * planePosition.z) (rectC.x * rectD.z - rectD.x * rectC.z)) / 2f; var areaCPB = Mathf.Abs((planePosition.x * rectC.z - rectC.x * planePosition.z) (planePosition.x * rectB.z - rectB.x * planePosition.z) (rectC.x * rectB.z - rectB.x * rectC.z)) / 2f; var areaPBA = Mathf.Abs((planePosition.x * rectB.z - rectB.x * planePosition.z) (planePosition.x * rectA.z - rectA.x * planePosition.z) (rectB.x * rectA.z - rectA.x * rectB.z)) / 2f; return areaAPD areaDPC areaCPB areaPBA <= areaRect;
所以我認為它可能看起來像
public static class MathUtils
{
// little helper extension to get rid of any differences in Y direction
public static Vector2 XZ(this Vector3 v) => new Vector2(v.x, v.z);
public static float Area(Vector2 a, Vector2 b, Vector2 c) => Mathf.Abs((a.x * b.y - b.x * a.y) (b.x * c.y - c.x * b.y) (c.x * a.y - a.x * c.y)) / 2f;
public static bool IsWithinRange(this Vector3 p, Vector3 a, Vector3 b, float range)
{
var cleanP = p.XZ();
var cleanA = a.XZ();
if(Vector2.Distance(cleanP, cleanA) <= range) return true;
var cleanB = b.XZ();
if(Vector2.Distance(cleanP, cleanB) <= range) return true;
var delta = cleanB - cleanA;
var distance = delta.magnitude;
var direction = delta.normalized;
var cross = Vector2.Perpendicular(direction).normalized;
var rectA = cleanA cross * range;
var rectB = cleanA - cross * range;
var rectC = cleanB cross * range;
var rectD = cleanB - cross * range;
var areaRect = cross * 2 * distance;
var areaAPD = Area(cleanP, rectA, rectD);
var areaDPC = Area(cleanP, rectC, rectD);
var areaCPB = Area(cleanP, rectC, rectB);
var areaPBA = Area(cleanP, rectA, rectB);
return areaAPD areaDPC areaCPB areaPBA <= areaRect;
}
}
當然,當我在手機上輸入此內容時,您將需要對此進行測驗;)
uj5u.com熱心網友回復:
一種方法是使用兩點之間的邊界框。如此處所述:
軸對齊邊界框,簡稱 AABB,是與坐標軸對齊并完全包圍某個物件的框。因為盒子從不相對于軸旋轉,所以它可以由它的中心和范圍來定義,或者由最小和最大點來定義。
我已經為您撰寫了一個簡單的代碼來展示它是如何作業的(gizmos 代碼來自這里),如果您想要更復雜的形狀,您可以使用多個邊界框(此外,您可以使用probuilder包創建路徑,禁用形狀并且只使用它的對撞機)
[SerializeField] private Transform startTransform;
[SerializeField] private Transform endTransform;
[SerializeField] private Transform plane;
[SerializeField] private Vector3 size = Vector3.one * 3.5f;
[SerializeField] private Bounds _bounds;
private void Start()
{
_bounds = new Bounds {center = (startTransform.position endTransform.position) / 2,extents = size};
}
private void Update()
{
print(_bounds.Contains(plane.position) ? "yes" : "no");
}
private void OnDrawGizmos()
{
var xVals = new[]
{
_bounds.max.x, _bounds.min.x
};
var yVals = new[]
{
_bounds.max.y, _bounds.min.y
};
var zVals = new[]
{
_bounds.max.z, _bounds.min.z
};
for (int i = 0; i < xVals.Length; i )
{
var x = xVals[i];
for (int j = 0; j < yVals.Length; j )
{
var y = yVals[j];
for (int k = 0; k < zVals.Length; k )
{
var z = zVals[k];
var point = new Vector3(x, y, z);
Gizmos.DrawWireCube(point, _bounds.extents);
if (i == 0)
{
Gizmos.DrawLine(point, new Vector3(xVals[1], y, z));
}
if (j == 0)
{
Gizmos.DrawLine(point, new Vector3(x, yVals[1], z));
}
if (k == 0)
{
Gizmos.DrawLine(point, new Vector3(x, y, zVals[1]));
}
}
}
}
}
uj5u.com熱心網友回復:
我一直在玩一些想法,我認為最好的解決方案是使用 Point1 (A) 和 Point2 (B) 作為線的點,并計算從平面 (Point3) 到線 (AB) 的最短距離。您可以使用這樣的東西作為起點: 點和線段之間的最短距離
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/512423.html
標籤:C#算法unity3d
