/// <summary> /// Checks if this tile contains an agent that obstructs the given agent. /// </summary> /// <param name="inAgent">Agent to check obstruction for.</param> /// <param name="outObstructingAgent">Found agent that is obstructing.</param> /// <returns>Whether or not an obstruction was found.</returns> public bool IsObstructed(NavTileAgent inAgent, out NavTileAgent outObstructingAgent) { NavTileAgentManager manager = NavTileManager.Instance.AgentManager; outObstructingAgent = null; foreach (NavTileAgent agent in OccupyingAgents) { if (manager.GetValue(inAgent.AgentType, agent.AgentType)) { outObstructingAgent = agent; return(true); } } return(false); }
/// <summary> /// Recursive function to check agents which this agent is waiting on. /// /// There are a few situations where the agent should abort waiting. /// /// 1. When this agent is waiting on an agent which is ultimately waiting for this agent. /// 2. When this agent is waiting for an agent which is involved in a circular conflict either itself, or some subsequent agent. /// 3. When this agent is waiting for a waiting agent which is ultimately waiting for a stationary agent. /// 4. When this agent is waiting for an agent who might be waiting, but its conflict handling setting is lower and therefor will never move again. /// /// Some of these options can be solved just by letting others solve their conflicts first. /// </summary> /// <param name="inNextNode">The next node this agent might traverse to.</param> /// <param name="inObstructingAgent">The obstructing agent encountered.</param> /// <param name="inCheckedAgents">All Checked agents including the obstructed agent.</param> private EConflictStatus CheckWaitingOccuypingAgents(PathNode inNextNode, NavTileAgent inObstructingAgent, List <NavTileAgent> inCheckedAgents, ref EAbortReason refAbortReason) { // Get all agents occupying the tile which the obstructing agent is waiting for, sorted per MovementStatus. Dictionary <EMovementStatus, List <NavTileAgent> > sortedAgents = inObstructingAgent.WaitingForTile.GetSortedOccupyingAgents(inObstructingAgent); List <NavTileAgent> agents; // Check if there are any stationary agents. If so, abort this path. if (sortedAgents.TryGetValue(EMovementStatus.Stationary, out agents)) { refAbortReason = EAbortReason.EncounteredStationaryAgent; return(EConflictStatus.Abort); } else if (sortedAgents.TryGetValue(EMovementStatus.Waiting, out agents)) // Check if there are any waiting agents. { foreach (NavTileAgent agent in agents) { // Is the agent found this agent or has it already been checked? Abort path if (agent == this || inCheckedAgents.Contains(agent)) { refAbortReason = EAbortReason.EncounteredCircularConflict; return(EConflictStatus.Abort); } // Add the agent to the list inCheckedAgents.Add(agent); // Do this again. return(CheckWaitingOccuypingAgents(inNextNode, agent, inCheckedAgents, ref refAbortReason)); } } else // No entries of waiting or stationary agents. { // Set the timer to be used later and specify which tile this agent is waiting for. _didEncounterObstruction = true; _obstructionTimer = _waitAfterFreeTile; _waitingForTile = NavTileManager.Instance.SurfaceManager.Data.GetTileData(inNextNode.TilePosition); } return(EConflictStatus.Processing); }
/// <summary> /// Gets all occupying and obstructing agents ordered per status in a dictionary. /// </summary> /// <param name="inAgent">Agent to check obstruction for.</param> /// <returns>Dictionary containing all obstructing agents order per status.</returns> public Dictionary <NavTileAgent.EMovementStatus, List <NavTileAgent> > GetSortedOccupyingAgents(NavTileAgent inAgent) { Dictionary <NavTileAgent.EMovementStatus, List <NavTileAgent> > dic = new Dictionary <NavTileAgent.EMovementStatus, List <NavTileAgent> >(); NavTileAgentManager manager = NavTileManager.Instance.AgentManager; foreach (NavTileAgent agent in OccupyingAgents) { if (manager.GetValue(inAgent.AgentType, agent.AgentType)) { List <NavTileAgent> agents; if (dic.TryGetValue(agent.MovementStatus, out agents)) { agents.Add(agent); } else { agents = new List <NavTileAgent>() { agent }; dic.Add(agent.MovementStatus, agents); } } } return(dic); }
private void Awake() { _agent = GetComponent <NavTileAgent>(); _agent.AutoTraversePath = true; }
/// <summary> /// Checks whether the perpendicular tiles of a diagonal movement are obstructed. /// /// E.g. in the case of AB tiles, where an agent traverses over tiles A, positions B1 and B2 get checked for an obstructing agent. /// BA /// </summary> private bool IsPerpendicularObstructed(Vector2Int inCurrentTilePosition, Vector2Int inNextNodeTilePosition, out NavTileAgent outObstructingAgent) { outObstructingAgent = null; Vector2Int horizontalPosition = new Vector2Int(inCurrentTilePosition.x, inNextNodeTilePosition.y); Vector2Int verticalPosition = new Vector2Int(inNextNodeTilePosition.x, inCurrentTilePosition.y); TileData horizontalTileData = NavTileManager.Instance.SurfaceManager.Data.GetTileData(horizontalPosition); TileData verticalTileData = NavTileManager.Instance.SurfaceManager.Data.GetTileData(verticalPosition); NavTileAgent obstructingAgent; // Check whether there is an agent which is walking across the two relevant tiles. if (horizontalTileData.IsObstructed(this, out obstructingAgent) && obstructingAgent.GetPreviousPositionInPath() == verticalPosition || verticalTileData.IsObstructed(this, out obstructingAgent) && obstructingAgent.GetPreviousPositionInPath() == horizontalPosition) { outObstructingAgent = obstructingAgent; return(true); } return(false); }
private void OnEnable() { // Fields. _autoTraversePathProperty = serializedObject.FindProperty("AutoTraversePath"); _areaMaskProperty = serializedObject.FindProperty("_areaMask"); _agentTypeProperty = serializedObject.FindProperty("_agentType"); _speedProperty = serializedObject.FindProperty("_speed"); _diagonalAllowedProperty = serializedObject.FindProperty("_diagonalAllowed"); _cutCornersProperty = serializedObject.FindProperty("_cutCorners"); _ignoreTileCostProperty = serializedObject.FindProperty("_ignoreTileCost"); _conflictOptionProperty = serializedObject.FindProperty("_conflictOption"); _waitAfterFreeTileProperty = serializedObject.FindProperty("_waitAfterFreeTile"); _debugEnabledProperty = serializedObject.FindProperty("_debugEnabled"); _debugLineColorProperty = serializedObject.FindProperty("_debugLineColor"); // Animation settings. _animatorProperty = serializedObject.FindProperty("LinkedAnimator"); _preserveAnimDirectionProperty = serializedObject.FindProperty("_preserveAnimDirection"); _horizontalAnimParamProperty = serializedObject.FindProperty("_animationHorizontalParameter"); _verticalAnimParamProperty = serializedObject.FindProperty("_animationVerticalParameter"); _speedAnimParamProperty = serializedObject.FindProperty("_animationSpeedParameter"); // Area settings. _onAreaChangeUnityEvent = serializedObject.FindProperty("OnAreaChangeUnityEvent"); _areaSettingsListProperty = serializedObject.FindProperty("_areaSettingsList"); // Path callbacks. _onPathFoundUnityEventProperty = serializedObject.FindProperty("OnPathFoundUnityEvent"); _onPathNotFoundUnityEventProperty = serializedObject.FindProperty("OnPathNotFoundUnityEvent"); _onPathAbortedUnityEventProperty = serializedObject.FindProperty("OnPathAbortedUnityEvent"); _onPathFinishedUnityEventProperty = serializedObject.FindProperty("OnPathFinishedUnityEvent"); _areaAnimationsReorderableList = new ReorderableList(serializedObject, _areaSettingsListProperty, false, false, false, false) { drawHeaderCallback = DrawAreaAnimationsListHeader, drawElementCallback = DrawAreaAnimationsListElement, elementHeight = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing, footerHeight = 0 }; _areaSpeedsReorderableList = new ReorderableList(serializedObject, _areaSettingsListProperty, false, false, false, false) { drawHeaderCallback = DrawAreaSpeedsListHeader, drawElementCallback = DrawAreaSpeedsListElement, elementHeight = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing, footerHeight = 0 }; // Default animator to self if possible. for (int i = 0; i < targets.Length; i++) { NavTileAgent anAgent = (NavTileAgent)targets[i]; if (anAgent.LinkedAnimator == null) { anAgent.LinkedAnimator = anAgent.GetComponent <Animator>(); } } UpdateAreaSettingsList(); LoadEditorPrefs(); }