Crowd: Detail API documentation for primary members declared in DetourCrowd.h.
Also includes some minor updates to the path corridor documentation.
This commit is contained in:
parent
588d674c72
commit
0ec4f993cb
@ -26,66 +26,121 @@
|
||||
#include "DetourProximityGrid.h"
|
||||
#include "DetourPathQueue.h"
|
||||
|
||||
|
||||
/// The maximum number of neighbors that a crowd agent can take into account
|
||||
/// for steering decisions.
|
||||
/// @ingroup crowd
|
||||
static const int DT_CROWDAGENT_MAX_NEIGHBOURS = 6;
|
||||
|
||||
/// The maximum number of corners a crowd agent will look ahead in the path.
|
||||
/// This value is used for sizing the crowd agent corner buffers.
|
||||
/// Due to the behavior of the crowd manager, the actual number of useful
|
||||
/// corners will be one less than this number.
|
||||
/// @ingroup crowd
|
||||
static const int DT_CROWDAGENT_MAX_CORNERS = 4;
|
||||
|
||||
/// The maximum number of crowd avoidance configurations supported by the
|
||||
/// crowd manager.
|
||||
/// @ingroup crowd
|
||||
/// @see dtObstacleAvoidanceParams, dtCrowd::setObstacleAvoidanceParams(), dtCrowd::getObstacleAvoidanceParams(),
|
||||
/// dtCrowdAgentParams::obstacleAvoidanceType
|
||||
static const int DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS = 8;
|
||||
|
||||
/// Provides neighbor data for agents managed by the crowd.
|
||||
/// @ingroup crowd
|
||||
/// @see dtCrowdAgent::neis, dtCrowd
|
||||
struct dtCrowdNeighbour
|
||||
{
|
||||
int idx;
|
||||
float dist;
|
||||
int idx; ///< The index of the neighbor in the crowd.
|
||||
float dist; ///< The distance between the current agent and the neighbor.
|
||||
};
|
||||
|
||||
/// The type of navigation mesh polygon the agent is currently traversing.
|
||||
/// @ingroup crowd
|
||||
enum CrowdAgentState
|
||||
{
|
||||
DT_CROWDAGENT_STATE_INVALID,
|
||||
DT_CROWDAGENT_STATE_WALKING,
|
||||
DT_CROWDAGENT_STATE_OFFMESH,
|
||||
DT_CROWDAGENT_STATE_INVALID, ///< The agent is not in a valid state.
|
||||
DT_CROWDAGENT_STATE_WALKING, ///< The agent is traversing a normal navigation mesh polygon.
|
||||
DT_CROWDAGENT_STATE_OFFMESH, ///< The agent is traversing an off-mesh connection.
|
||||
};
|
||||
|
||||
/// Configuration parameters for a crowd agent.
|
||||
/// @ingroup crowd
|
||||
struct dtCrowdAgentParams
|
||||
{
|
||||
float radius;
|
||||
float height;
|
||||
float maxAcceleration;
|
||||
float maxSpeed;
|
||||
float radius; ///< Agent radius. [Limit: >= 0]
|
||||
float height; ///< Agent height. [Limit: > 0]
|
||||
float maxAcceleration; ///< Maximum allowed acceleration. [Limit: >= 0]
|
||||
float maxSpeed; ///< Maximum allowed speed. [Limit: >= 0]
|
||||
|
||||
/// Defines how close a collision element must be before it is considered for steering behaviors. [Limits: > 0]
|
||||
float collisionQueryRange;
|
||||
float pathOptimizationRange;
|
||||
|
||||
float pathOptimizationRange; ///< The path visibility optimization range. [Limit: > 0]
|
||||
|
||||
/// How aggresive the agent manager should be at avoiding collisions with this agent. [Limit: >= 0]
|
||||
float separationWeight;
|
||||
|
||||
/// Flags that impact steering behavior. (See: #UpdateFlags)
|
||||
unsigned char updateFlags;
|
||||
unsigned char obstacleAvoidanceType;
|
||||
|
||||
/// The index of the avoidance configuration to use for the agent.
|
||||
/// [Limits: 0 <= value <= #DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS]
|
||||
unsigned char obstacleAvoidanceType;
|
||||
|
||||
/// User defined data attached to the agent.
|
||||
void* userData;
|
||||
};
|
||||
|
||||
/// Represents an agent managed by a #dtCrowd object.
|
||||
/// @ingroup crowd
|
||||
struct dtCrowdAgent
|
||||
{
|
||||
/// 1 if the agent is active, or 0 if the agent is in an unused slot in the agent pool.
|
||||
unsigned char active;
|
||||
|
||||
/// The type of mesh polygon the agent is traversing. (See: #CrowdAgentState)
|
||||
unsigned char state;
|
||||
|
||||
/// The path corridor the agent is using.
|
||||
dtPathCorridor corridor;
|
||||
|
||||
/// The local boundary data for the agent.
|
||||
dtLocalBoundary boundary;
|
||||
|
||||
float t;
|
||||
float var;
|
||||
|
||||
/// The last time the agent's path corridor was optimized.
|
||||
float topologyOptTime;
|
||||
|
||||
/// The known neighbors of the agent.
|
||||
dtCrowdNeighbour neis[DT_CROWDAGENT_MAX_NEIGHBOURS];
|
||||
|
||||
/// The number of neighbors.
|
||||
int nneis;
|
||||
|
||||
/// The desired speed.
|
||||
float desiredSpeed;
|
||||
|
||||
float npos[3];
|
||||
float npos[3]; ///< The current agent position. [(x, y, z)]
|
||||
float disp[3];
|
||||
float dvel[3];
|
||||
float dvel[3]; ///< The desired velocity of the agent. [(x, y, z)]
|
||||
float nvel[3];
|
||||
float vel[3];
|
||||
float vel[3]; ///< The actual velocity of the agent. [(x, y, z)]
|
||||
|
||||
/// The agent's configuration parameters.
|
||||
dtCrowdAgentParams params;
|
||||
|
||||
/// The local path corridor corners for the agent. (Staight path.) [(x, y, z) * #ncorners]
|
||||
float cornerVerts[DT_CROWDAGENT_MAX_CORNERS*3];
|
||||
|
||||
/// The local path corridor corner flags. (See: #dtStraightPathFlags) [(flags) * #ncorners]
|
||||
unsigned char cornerFlags[DT_CROWDAGENT_MAX_CORNERS];
|
||||
|
||||
/// The reference id of the polygon being entered at the corner. [(polyRef) * #ncorners]
|
||||
dtPolyRef cornerPolys[DT_CROWDAGENT_MAX_CORNERS];
|
||||
|
||||
/// The number of corners.
|
||||
int ncorners;
|
||||
};
|
||||
|
||||
@ -97,13 +152,16 @@ struct dtCrowdAgentAnimation
|
||||
float t, tmax;
|
||||
};
|
||||
|
||||
/// Crowd agent update flags.
|
||||
/// @ingroup crowd
|
||||
/// @see dtCrowdAgentParams::updateFlags
|
||||
enum UpdateFlags
|
||||
{
|
||||
DT_CROWD_ANTICIPATE_TURNS = 1,
|
||||
DT_CROWD_OBSTACLE_AVOIDANCE = 2,
|
||||
DT_CROWD_SEPARATION = 4,
|
||||
DT_CROWD_OPTIMIZE_VIS = 8,
|
||||
DT_CROWD_OPTIMIZE_TOPO = 16,
|
||||
DT_CROWD_OPTIMIZE_VIS = 8, ///< Use #dtPathCorridor::optimizePathVisibility() to optimize the agent path.
|
||||
DT_CROWD_OPTIMIZE_TOPO = 16, ///< Use dtPathCorridor::optimizePathTopology() to optimize the agent path.
|
||||
};
|
||||
|
||||
struct dtCrowdAgentDebugInfo
|
||||
@ -113,6 +171,8 @@ struct dtCrowdAgentDebugInfo
|
||||
dtObstacleAvoidanceDebugData* vod;
|
||||
};
|
||||
|
||||
/// Provides local steering behaviors for a group of agents.
|
||||
/// @ingroup crowd
|
||||
class dtCrowd
|
||||
{
|
||||
int m_maxAgents;
|
||||
@ -182,37 +242,201 @@ public:
|
||||
dtCrowd();
|
||||
~dtCrowd();
|
||||
|
||||
/// Initializes the crowd.
|
||||
/// @param[in] maxAgents The maximum number of agents the crowd can manage. [Limit: >= 1]
|
||||
/// @param[in] maxAgentRadius The maximum radius of any agent that will be added to the crowd. [Limit: > 0]
|
||||
/// @param[in] nav The navigation mesh to use for planning.
|
||||
/// @return True if the initialization succeeded.
|
||||
bool init(const int maxAgents, const float maxAgentRadius, dtNavMesh* nav);
|
||||
|
||||
/// Sets the shared avoidance configuration for the specified index.
|
||||
/// @param[in] idx The index. [Limits: 0 <= value < #DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS]
|
||||
/// @param[in] params The new configuration.
|
||||
void setObstacleAvoidanceParams(const int idx, const dtObstacleAvoidanceParams* params);
|
||||
|
||||
/// Gets the shared avoidance configuration for the specified index.
|
||||
/// @param[in] idx The index of the configuration to retreive.
|
||||
/// [Limits: 0 <= value < #DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS]
|
||||
/// @return The requested configuration.
|
||||
const dtObstacleAvoidanceParams* getObstacleAvoidanceParams(const int idx) const;
|
||||
|
||||
/// Gets the specified agent from the pool.
|
||||
/// @param[in] idx The agent index. [Limits: 0 <= value < #getAgentCount()]
|
||||
/// @return The requested agent.
|
||||
const dtCrowdAgent* getAgent(const int idx);
|
||||
|
||||
/// The maximum number of agents that can be managed by the object.
|
||||
/// @return The maximum number of agents.
|
||||
const int getAgentCount() const;
|
||||
|
||||
/// Adds a new agent to the crowd.
|
||||
/// @param[in] pos The requested position of the agent. [(x, y, z)]
|
||||
/// @param[in] params The configutation of the agent.
|
||||
/// @return The index of the agent in the agent pool. Or -1 if the agent could not be added.
|
||||
int addAgent(const float* pos, const dtCrowdAgentParams* params);
|
||||
|
||||
/// Updates the specified agent's configuration.
|
||||
/// @param[in] idx The agent index. [Limits: 0 <= value < #getAgentCount()]
|
||||
/// @param[in] params The new agent configuration.
|
||||
void updateAgentParameters(const int idx, const dtCrowdAgentParams* params);
|
||||
|
||||
/// Removes the agent from the crowd.
|
||||
/// @param[in] idx The agent index. [Limits: 0 <= value < #getAgentCount()]
|
||||
void removeAgent(const int idx);
|
||||
|
||||
/// Submits a new move request for the specified agent.
|
||||
/// @param[in] idx The agent index. [Limits: 0 <= value < #getAgentCount()]
|
||||
/// @param[in] ref The position's polygon reference.
|
||||
/// @param[in] pos The position within the polygon. [(x, y, z)]
|
||||
/// @return True if the request was successfully submitted.
|
||||
bool requestMoveTarget(const int idx, dtPolyRef ref, const float* pos);
|
||||
|
||||
/// Sumbits a request to adjust the target position of the specified agent.
|
||||
/// @param[in] idx The agent index. [Limits: 0 <= value < #getAgentCount()]
|
||||
/// @param[in] ref The position's polygon reference.
|
||||
/// @param[in] pos The position within the polygon. [(x, y, z)]
|
||||
/// @return True if the request was successfully submitted.
|
||||
bool adjustMoveTarget(const int idx, dtPolyRef ref, const float* pos);
|
||||
|
||||
/// Gets the active agents int the agent pool.
|
||||
/// @param[out] agents An array of agent pointers. [(#dtCrowdAgent *) * maxAgents]
|
||||
/// @param[in] maxAgents The size of the crowd agent array.
|
||||
/// @return The number of agents returned in @p agents.
|
||||
int getActiveAgents(dtCrowdAgent** agents, const int maxAgents);
|
||||
|
||||
/// Updates the steering and positions of all agents.
|
||||
/// @param[in] dt The time, in seconds, to update the simulation. [Limit: > 0]
|
||||
/// @param[out] debug A debug object to load with debug information. [Opt]
|
||||
void update(const float dt, dtCrowdAgentDebugInfo* debug);
|
||||
|
||||
/// Gets the filter used by the crowd.
|
||||
/// @return The filter used by the crowd.
|
||||
const dtQueryFilter* getFilter() const { return &m_filter; }
|
||||
|
||||
/// Gets the filter used by the crowd.
|
||||
/// @return The filter used by the crowd.
|
||||
dtQueryFilter* getEditableFilter() { return &m_filter; }
|
||||
|
||||
/// Gets the search extents [(x, y, z)] used by the crowd for query operations.
|
||||
/// @return The search extents used by the crowd. [(x, y, z)]
|
||||
const float* getQueryExtents() const { return m_ext; }
|
||||
|
||||
/// Gets the velocity sample count.
|
||||
/// @return The velocity sample count.
|
||||
inline int getVelocitySampleCount() const { return m_velocitySampleCount; }
|
||||
|
||||
/// Gets the crowd's proximity grid.
|
||||
/// @return The crowd's proximity grid.
|
||||
const dtProximityGrid* getGrid() const { return m_grid; }
|
||||
|
||||
/// Gets the crowd's path request queue.
|
||||
/// @return The crowd's path request queue.
|
||||
const dtPathQueue* getPathQueue() const { return &m_pathq; }
|
||||
|
||||
/// Gets the query object used by the crowd.
|
||||
const dtNavMeshQuery* getNavMeshQuery() const { return m_navquery; }
|
||||
};
|
||||
|
||||
/// Allocates a crowd object using the Detour allocator.
|
||||
/// @return A crowd object that is ready for initialization, or null on failure.
|
||||
/// @ingroup crowd
|
||||
dtCrowd* dtAllocCrowd();
|
||||
|
||||
/// Frees the specified crowd object using the Detour allocator.
|
||||
/// @param[in] ptr A crowd object allocated using #dtAllocCrowd
|
||||
/// @ingroup crowd
|
||||
void dtFreeCrowd(dtCrowd* ptr);
|
||||
|
||||
|
||||
#endif // DETOURCROWD_H
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This section contains detailed documentation for members that don't have
|
||||
// a source file. It reduces clutter in the main section of the header.
|
||||
|
||||
/**
|
||||
|
||||
@defgroup crowd Crowd
|
||||
|
||||
Members in this module implement local steering and dynamic avoidance features.
|
||||
|
||||
The crowd is the big beast of the navigation features. It not only handles a
|
||||
lot of the path management for you, but also local steering and dynamic
|
||||
avoidance between members of the crowd. I.e. It can keep your agents from
|
||||
running into each other.
|
||||
|
||||
Main class: #dtCrowd
|
||||
|
||||
The #dtNavMeshQuery and #dtPathCorridor classes provide perfectly good, easy
|
||||
to use path planning features. But in the end they only give you points that
|
||||
your navigation client should be moving toward. When it comes to deciding things
|
||||
like agent velocity and steering to avoid other agents, that is up to you to
|
||||
implement. Unless, of course, you decide to use #dtCrowd.
|
||||
|
||||
Basically, you add an agent to the crowd, providing various configuration
|
||||
settings such as maximum speed and acceleration. You also provide a local
|
||||
target to more toward. The crowd manager then provides, with every update, the
|
||||
new agent position and velocity for the frame. The movement will be
|
||||
constrained to the navigation mesh, and steering will be applied to ensure
|
||||
agents managed by the crowd do not collide with each other.
|
||||
|
||||
This is very powerful feature set. But it comes with limitations.
|
||||
|
||||
The biggest limitation is that you must give control of the agent's position
|
||||
completely over to the crowd manager. You can update things like maximum speed
|
||||
and acceleration. But in order for the crowd manager to do its thing, it can't
|
||||
allow you to constantly be giving it overrides to position and velocity. So
|
||||
you give up direct control of the agent's movement. It belongs to the crowd.
|
||||
|
||||
The second biggest limitation revolves around the fact that the crowd manager
|
||||
deals with local planning. So the agent's target should never be more than
|
||||
256 polygons aways from its current position. If it is, you risk
|
||||
your agent failing to reach its target. So you may still need to do long
|
||||
distance planning and provide the crowd manager with intermediate targets.
|
||||
|
||||
Other significant limitations:
|
||||
|
||||
- All agents using the crowd manager will use the same #dtQueryFilter.
|
||||
- Crowd management is relatively expensive. The maximum agents under crowd
|
||||
management at any one time is between 20 and 30. A good place to start
|
||||
is a maximum of 25 agents for 0.5ms per frame.
|
||||
|
||||
@note This is a summary list of members. Use the index or search
|
||||
feature to find minor members.
|
||||
|
||||
@struct dtCrowdAgentParams
|
||||
@see dtCrowdAgent, dtCrowd::addAgent(), dtCrowd::updateAgentParameters()
|
||||
|
||||
@var dtCrowdAgentParams::obstacleAvoidanceType
|
||||
@par
|
||||
|
||||
#dtCrowd permits agents to use different avoidance configurations. This value
|
||||
is the index of the #dtObstacleAvoidanceParams within the crowd.
|
||||
|
||||
@see dtObstacleAvoidanceParams, dtCrowd::setObstacleAvoidanceParams(),
|
||||
dtCrowd::getObstacleAvoidanceParams()
|
||||
|
||||
@var dtCrowdAgentParams::collisionQueryRange
|
||||
@par
|
||||
|
||||
Collision elements include other agents and navigation mesh boundaries.
|
||||
|
||||
This value is often based on the agent radius and/or maximum speed. E.g. radius * 8
|
||||
|
||||
@var dtCrowdAgentParams::pathOptimizationRange
|
||||
@par
|
||||
|
||||
Only applicalbe if #updateFlags includes the #DT_CROWD_OPTIMIZE_VIS flag.
|
||||
|
||||
This value is often based on the agent radius. E.g. radius * 30
|
||||
|
||||
@see dtPathCorridor::optimizePathVisibility()
|
||||
|
||||
@var dtCrowdAgentParams::separationWeight
|
||||
@par
|
||||
|
||||
A higher value will result in agents trying to stay farther away from each other at
|
||||
the cost of more difficult steering in tight spaces.
|
||||
|
||||
*/
|
@ -21,7 +21,8 @@
|
||||
|
||||
#include "DetourNavMeshQuery.h"
|
||||
|
||||
/// Represents a dynamic polygon corridor used to plan agent movement
|
||||
/// Represents a dynamic polygon corridor used to plan agent movement.
|
||||
/// @ingroup crowd, detour
|
||||
class dtPathCorridor
|
||||
{
|
||||
float m_pos[3];
|
||||
|
@ -218,7 +218,43 @@ static int getNeighbours(const float* pos, const float height, const float range
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
@class dtCrowd
|
||||
@par
|
||||
|
||||
This is the core class of the @ref crowd module. See the @ref crowd documentation for a summary
|
||||
of the crowd features.
|
||||
|
||||
A common method for setting up the crowd is as follows:
|
||||
|
||||
-# Allocate the crowd using #dtAllocCrowd.
|
||||
-# Initialize the crowd using #init().
|
||||
-# Set the avoidance configurations using #setObstacleAvoidanceParams().
|
||||
-# Add agents using #addAgent() and make an initial movement request using #requestMoveTarget().
|
||||
|
||||
A common process for managing the crowd is as follows:
|
||||
|
||||
-# Call #update() to allow the crowd to manage its agents.
|
||||
-# Retrieve agent information using #getActiveAgents().
|
||||
-# Make movement requests using #requestMoveTarget() and #adjustMoveTarget().
|
||||
-# Repeat every frame.
|
||||
|
||||
Some agent configuration settings can be updated using #updateAgentParameters(). But the crowd owns the
|
||||
agent position. So it is not possible to update an active agent's position. If agent position
|
||||
must be fed back into the crowd, the agent must be removed and re-added.
|
||||
|
||||
Notes:
|
||||
|
||||
- Path related information is available for newly added agents only after an #update() has been
|
||||
performed.
|
||||
- Agent objects are kept in a pool and re-used. So it is important when using agent objects to check the value of
|
||||
#dtCrowdAgent::active to determine if the agent is actually in use or not.
|
||||
- This class is meant to provide 'local' movement. There is a limit of 256 polygons in the path corridor.
|
||||
So it is not meant to provide automatic pathfinding services over long distances.
|
||||
|
||||
@see dtAllocCrowd(), dtFreeCrowd(), init(), dtCrowdAgent
|
||||
|
||||
*/
|
||||
|
||||
dtCrowd::dtCrowd() :
|
||||
m_maxAgents(0),
|
||||
@ -273,6 +309,9 @@ void dtCrowd::purge()
|
||||
m_navquery = 0;
|
||||
}
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// May be called more than once to purge and re-initialize the crowd.
|
||||
bool dtCrowd::init(const int maxAgents, const float maxAgentRadius, dtNavMesh* nav)
|
||||
{
|
||||
purge();
|
||||
@ -378,6 +417,9 @@ const int dtCrowd::getAgentCount() const
|
||||
return m_maxAgents;
|
||||
}
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// Agents in the pool may not be in use. Check #dtCrowdAgent.active before using the returned object.
|
||||
const dtCrowdAgent* dtCrowd::getAgent(const int idx)
|
||||
{
|
||||
return &m_agents[idx];
|
||||
@ -390,6 +432,9 @@ void dtCrowd::updateAgentParameters(const int idx, const dtCrowdAgentParams* par
|
||||
memcpy(&m_agents[idx].params, params, sizeof(dtCrowdAgentParams));
|
||||
}
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// The agent's position will be constrained to the surface of the navigation mesh.
|
||||
int dtCrowd::addAgent(const float* pos, const dtCrowdAgentParams* params)
|
||||
{
|
||||
// Find empty slot.
|
||||
@ -439,6 +484,10 @@ int dtCrowd::addAgent(const float* pos, const dtCrowdAgentParams* params)
|
||||
return idx;
|
||||
}
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// The agent is deactivated and will no longer be processed. Its #dtCrowdAgent object
|
||||
/// is not removed from the pool. It is marked as inactive so that it is available for reuse.
|
||||
void dtCrowd::removeAgent(const int idx)
|
||||
{
|
||||
if (idx >= 0 && idx < m_maxAgents)
|
||||
@ -505,7 +554,15 @@ bool dtCrowd::requestMoveTargetReplan(const int idx, dtPolyRef ref, const float*
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// This method is used when a new target is set. Use #adjustMoveTarget() when
|
||||
/// only small local adjustments are needed. (Such as happens when following a
|
||||
/// moving target.)
|
||||
///
|
||||
/// The position will be constrained to the surface of the navigation mesh.
|
||||
///
|
||||
/// The request will be processed during the next #update().
|
||||
bool dtCrowd::requestMoveTarget(const int idx, dtPolyRef ref, const float* pos)
|
||||
{
|
||||
if (idx < 0 || idx > m_maxAgents)
|
||||
@ -545,7 +602,15 @@ bool dtCrowd::requestMoveTarget(const int idx, dtPolyRef ref, const float* pos)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// This method is used when to make small local adjustments to the current
|
||||
/// target. (Such as happens when following a moving target.) Use
|
||||
/// #requestMoveTarget() when a new target is needed.
|
||||
///
|
||||
/// The position will be constrained to the surface of the navigation mesh.
|
||||
///
|
||||
/// The request will be processed during the next #update().
|
||||
bool dtCrowd::adjustMoveTarget(const int idx, dtPolyRef ref, const float* pos)
|
||||
{
|
||||
if (idx < 0 || idx > m_maxAgents)
|
||||
|
@ -293,8 +293,11 @@ int dtPathCorridor::findCorners(float* cornerVerts, unsigned char* cornerFlags,
|
||||
@par
|
||||
|
||||
Inaccurate locomotion or dynamic obstacle avoidance can force the argent position significantly outside the
|
||||
original corridor. Over time this can result in the formation of a non-optimal corridor. This function uses an
|
||||
efficient local visibility search to try to re-optimize the corridor between the current position and @p next.
|
||||
original corridor. Over time this can result in the formation of a non-optimal corridor. Non-optimal paths can
|
||||
also form near the corners of tiles.
|
||||
|
||||
This function uses an efficient local visibility search to try to optimize the corridor
|
||||
between the current position and @p next.
|
||||
|
||||
The corridor will change only if @p next is visible from the current position and moving directly toward the point
|
||||
is better than following the existing path.
|
||||
|
Loading…
x
Reference in New Issue
Block a user