在 Collider 上隨機找一個著彈點.

為了不浪費 NPC 射的子彈, 又不希望玩家身中多槍, 我們很多時候會在玩家週遭找一些障礙物來給 NPC 射擊.

一方面給玩家給成緊張感, 另一方面著彈點也可以合理的播放particle 效果.
提升找入感.

那麼如何標示這些著彈點就要花點心思了.

 

private bool GetInterestShootablePoint(Vector3 playerHeadPos, Vector3 firedPoint, out Vector3 point)
	{
		int hitted = aroundPlayerHead.OverlapNonAlloc(playerHeadPos, _attractFieldArea, ref markedObjs, _bulletAttractLayer, QueryTriggerInteraction.Ignore);

		if (_debugDeviation)
			DebugExtend.DrawCircle(playerHeadPos, Vector3.up, s_AimTarget, _attractFieldArea, s_DebugShootingLine, true);

		if (hitted == 0)
		{
			point = default;
			 // can't find anything interest shoot point in range.
			return false;
		}
		else
		{
			int rnd = UnityEngine.Random.Range(0, hitted);
			Collider selected = markedObjs[rnd];
			Quaternion quat = Quaternion.LookRotation(playerHeadPos - firedPoint);
			Vector3 boxCenter = selected.bounds.center;
			Vector3 factor = selected.bounds.extents;
			float hFactor = Mathf.Max(factor.x, factor.z);
			float vFactor = factor.y;
			float rndHor = UnityEngine.Random.Range(-hFactor, hFactor);
			float rndVert = UnityEngine.Random.Range(-vFactor, vFactor);
			Matrix4x4 matrix = Matrix4x4.TRS(boxCenter, quat, Vector3.one);
			point = matrix.MultiplyPoint(MemoryManager.V3(rndHor, rndVert, 0f));
			if (_debugDeviation)
			{
				DebugExtend.DrawPoint(matrix.MultiplyPoint(MemoryManager.V3(0f, vFactor,0f)), s_ColorSizeDetection, 0.2f, s_DebugShootingLine);
				DebugExtend.DrawPoint(matrix.MultiplyPoint(MemoryManager.V3(0f,-vFactor, 0f)), s_ColorSizeDetection, 0.2f, s_DebugShootingLine);
				DebugExtend.DrawPoint(matrix.MultiplyPoint(MemoryManager.V3(hFactor, 0f, 0f)), s_ColorSizeDetection, 0.2f, s_DebugShootingLine);
				DebugExtend.DrawPoint(matrix.MultiplyPoint(MemoryManager.V3(-hFactor, 0f, 0f)), s_ColorSizeDetection, 0.2f, s_DebugShootingLine);
			}

			point = selected.ClosestPoint(point);
			if (_debugDeviation)
			{
				Debug.DrawLine(firedPoint, playerHeadPos, s_AimTarget, s_DebugShootingLine, true); // Org path.
				Debug.DrawLine(firedPoint, point, s_ColorSafeAttack, s_DebugShootingLine, true); // final selection.
			}
			return true;
		}
	}

功能很簡單, 

提供 playerHeadPos 玩家的頭部位置, 以其圓週範圍取得附近可用的障礙物,
在 NPC 需要 “射不中” 玩家時即以週遭的 Collider 為目標發射.

 

Enemies shoot near by player

取得 Collider 後才是有趣的地方, 總不成永遠打 Collider 中某一個位置, 所以我們要做點隨機, 這要求到計算 Collider 中可用的體積.

取得 Collider.Bound 為參考, 這東西只是顯示層面上的 bound box, 不是這東西 (Mesh) 的實際體積,
取得 bound 後 center + extents 就能夠知道這東西的三維體積了.

就可以用 X, Y 來決定射擊這個 Mesh 中有效的範圍.
決定好位置後, 因為我們是用投映來運算這隨機點,

把這個 bound box 以 NPC 面向 Player 的vector角度為軸, 投影成平面.
把這個 bound box 轉換為 Matrix 後就可以用 multilypoint() 來換算 world position.

最後就只是把子彈依著新的著彈點角度發射即可.

The blue circle showing that slice plane based on NPC perspective

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

*

這個網站採用 Akismet 服務減少垃圾留言。進一步瞭解 Akismet 如何處理網站訪客的留言資料