我正在開發像 Hitman Go 這樣的游戲,當敵人通過巖石或聲音等發出警報時,我需要找到哪些航點最接近我的目標(特定航點)。

我為敵人設定了一些點,我的敵人在航點之間巡邏( 8 -> 6 -> 1-> 2-> 3-> 4-> 5 )然后尊重他的路徑。所以,當我在 18 號航點扔石頭時,我需要將敵人移動到這個航點,但要以最近的方式移動。當敵人獲得警覺時,成像敵人可以是任何這個航點(8、6、1、2、3、4、5點)。
注1:兩點間的距離相等。
注2:我的游戲是 3d 而非 2d。
我使用此代碼逐步移動我的敵人(轉基地)。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WaypointController : MonoBehaviour
{
public List<Transform> waypoints = new List<Transform>();
private Transform targetWaypoint;
private int targetWaypointIndex = 0;
private float minDistance = 0.1f;
private int lastWaypointIndex;
public bool reversePath;
// what easetype to use for iTweening
public iTween.EaseType easeType = iTween.EaseType.easeInOutExpo;
// how fast we move
public float moveSpeed = 1.5f;
// time to rotate to face destination
public float rotateTime = 0.5f;
// delay to use before any call to iTween
public float iTweenDelay = 0f;
// Use this for initialization
void Start()
{
lastWaypointIndex = waypoints.Count - 1;
targetWaypoint = waypoints[targetWaypointIndex];
}
public void EnemyTurn()
{
float distance = Vector3.Distance(transform.position, targetWaypoint.position);
CheckDistanceToWaypoint(distance);
// move toward the destinationPos using the easeType and moveSpeed variables
iTween.MoveTo(gameObject, iTween.Hash(
"x", targetWaypoint.position.x,
"y", targetWaypoint.position.y,
"z", targetWaypoint.position.z,
"delay", iTweenDelay,
"easetype", easeType,
"speed", moveSpeed
));
}
void CheckDistanceToWaypoint(float currentDistance)
{
if (currentDistance <= minDistance)
{
targetWaypointIndex ;
UpdateTargetWaypoint();
}
}
void UpdateTargetWaypoint()
{
if (targetWaypointIndex > lastWaypointIndex)
{
if (reversePath)
{
waypoints.Reverse();
}
targetWaypointIndex = 1;
}
targetWaypoint = waypoints[targetWaypointIndex];
}
}
uj5u.com熱心網友回復:
由于您在評論中要求提供非 A* 解決方案,因此我很無聊:)
具有非常簡單修剪的樸素DFS探路者。蠻力和非常浪費記憶體和 CPU 明智。
對于類似于 Hitman Go / Lara Croft Go 的游戲 - 我會使用此代碼而不是導航網格 / A*。
對于 RTS / FPS 或任何 AI 密集型游戲,我絕對不會使用此解決方案。
public class GridPathfinder
{
// Not thread safe
private int? _currentShortestPath;
/// <summary>
/// Finds shortest path from cell A to B
/// </summary>
/// <returns>Shortest found path; null if found no path.</returns>
public IList<Node> GetShortestPath(Node a, Node b)
{
_currentShortestPath = null;
return GetShortestPathInternal(a, b, new List<Node>());
}
private IList<Node> GetShortestPathInternal(Node @from, Node to, List<Node> currentPath)
{
// Sanity
if (currentPath.Contains(from))
{
return null;
}
// Prune
if (_currentShortestPath.HasValue && currentPath.Count 1 >= _currentShortestPath)
{
return null;
}
currentPath.Add(from);
if (from == to)
{
return currentPath;
}
// Check neighbors recursively
IList<Node> foundShortestPath = null;
foreach (var connectedCell in from.ConnectedCells)
{
var cellPath = GetShortestPathInternal(connectedCell, to, new List<Node>(currentPath));
if (cellPath == null || foundShortestPath != null && cellPath.Count >= foundShortestPath.Count)
{
continue;
}
foundShortestPath = cellPath;
}
// Update shortest path for future pruning
if (foundShortestPath != null && (!_currentShortestPath.HasValue || _currentShortestPath > foundShortestPath.Count))
{
_currentShortestPath = foundShortestPath.Count;
}
return foundShortestPath;
}
}
public class Node
{
private readonly HashSet<Node> _connectedCells = new HashSet<Node>();
public IEnumerable<Node> ConnectedCells => _connectedCells;
/// <summary>
/// Add a connection
/// </summary>
/// <param name="toAdd">Node to add</param>
/// <param name="isTwoWay">Should add a connection from target node to this node</param>
public void AddConnection(Node toAdd, bool isTwoWay=true)
{
if (toAdd == null || toAdd == this)
{
throw new Exception("Invalid connection attempted");
}
// Attempt to add
if (!_connectedCells.Add(toAdd))
{
return;
}
if (!isTwoWay) return;
toAdd.AddConnection(this);
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/317367.html
