mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-17 22:03:56 -07:00
Abort formation-walking on any message from UnitMotion.
Units in formation can occasionally request many short paths (and thus introduce crippling lag) if their offset is obstructed. This particularly happen when the formation is idle, since the offset then always remains obstructed. To prevent this, it is OK to immediately stop pathing on any motion message (obstructed, failure, success). This does not break formation movement since messages are only sent when the formation controller is not moving (this finishes what was started in0535eb9b92). Ideally, this hack could be removed if the short-pathfinder was quick enough / units were better at aborting. Fixes concern raised by Freagarach ona7da40ac2f. Refs #5624 in that the max-short-path range is the source of the lag. Reviewed By: Angen Differential Revision: https://code.wildfiregames.com/D2871 This was SVN commit r23867.
This commit is contained in:
parent
2ef3fd7a77
commit
f489ab3a16
2 changed files with 40 additions and 26 deletions
|
|
@ -1384,17 +1384,12 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||
// Occurs when the unit has reached its destination and the controller
|
||||
// is done moving. The controller is notified.
|
||||
"MovementUpdate": function(msg) {
|
||||
// We're supposed to be walking in formation,
|
||||
// but the controller has no position -> abort.
|
||||
let cmpControllerPosition = Engine.QueryInterface(this.formationController, IID_Position);
|
||||
if (!cmpControllerPosition || !cmpControllerPosition.IsInWorld())
|
||||
{
|
||||
this.FinishOrder();
|
||||
return;
|
||||
}
|
||||
if (!msg.likelyFailure && !msg.likelySuccess)
|
||||
return;
|
||||
|
||||
// When walking in formation, we'll only get notified in case of failure
|
||||
// if the formation controller has stopped walking.
|
||||
// Formations can start lagging a lot if many entities request short path
|
||||
// so prefer to finish order early than retry pathing.
|
||||
// (see https://code.wildfiregames.com/rP23806)
|
||||
// (if the message is likelyFailure of likelySuccess, we also want to stop).
|
||||
this.FinishOrder();
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -483,10 +483,10 @@ private:
|
|||
return m_MoveRequest.m_Type == MoveRequest::OFFSET;
|
||||
}
|
||||
|
||||
bool IsFormationControllerNotMoving() const
|
||||
bool IsFormationControllerMoving() const
|
||||
{
|
||||
CmpPtr<ICmpUnitMotion> cmpControllerMotion(GetSimContext(), m_MoveRequest.m_Entity);
|
||||
return cmpControllerMotion && !cmpControllerMotion->IsMoveRequested();
|
||||
return cmpControllerMotion && cmpControllerMotion->IsMoveRequested();
|
||||
}
|
||||
|
||||
entity_id_t GetGroup() const
|
||||
|
|
@ -501,6 +501,12 @@ private:
|
|||
*/
|
||||
void MoveFailed()
|
||||
{
|
||||
// Don't notify if we are a formation member in a moving formation - we can occasionally be stuck for a long time
|
||||
// if our current offset is unreachable, but we don't want to end up stuck.
|
||||
// (If the formation controller has stopped moving however, we can safely message).
|
||||
if (IsFormationMember() && IsFormationControllerMoving())
|
||||
return;
|
||||
|
||||
CMessageMotionUpdate msg(CMessageMotionUpdate::LIKELY_FAILURE);
|
||||
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg);
|
||||
}
|
||||
|
|
@ -512,10 +518,33 @@ private:
|
|||
*/
|
||||
void MoveSucceeded()
|
||||
{
|
||||
// Don't notify if we are a formation member in a moving formation - we can occasionally be stuck for a long time
|
||||
// if our current offset is unreachable, but we don't want to end up stuck.
|
||||
// (If the formation controller has stopped moving however, we can safely message).
|
||||
if (IsFormationMember() && IsFormationControllerMoving())
|
||||
return;
|
||||
|
||||
CMessageMotionUpdate msg(CMessageMotionUpdate::LIKELY_SUCCESS);
|
||||
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Warns other components that our current movement was obstructed (i.e. we failed to move this turn).
|
||||
* This should only be called before the actual movement in a given turn, or units might both move and try to do things
|
||||
* on the same turn, leading to gliding units.
|
||||
*/
|
||||
void MoveObstructed()
|
||||
{
|
||||
// Don't notify if we are a formation member in a moving formation - we can occasionally be stuck for a long time
|
||||
// if our current offset is unreachable, but we don't want to end up stuck.
|
||||
// (If the formation controller has stopped moving however, we can safely message).
|
||||
if (IsFormationMember() && IsFormationControllerMoving())
|
||||
return;
|
||||
|
||||
CMessageMotionUpdate msg(CMessageMotionUpdate::OBSTRUCTED);
|
||||
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the number of failed path computations and notify other components if required.
|
||||
*/
|
||||
|
|
@ -761,17 +790,10 @@ void CCmpUnitMotion::PathResult(u32 ticket, const WaypointPath& path)
|
|||
}
|
||||
|
||||
if (m_FailedPathComputations >= 1)
|
||||
{
|
||||
// Inform other components - we might be ordered to stop, and computeGoal will then fail and return early.
|
||||
CMessageMotionUpdate msg(CMessageMotionUpdate::OBSTRUCTED);
|
||||
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg);
|
||||
}
|
||||
MoveObstructed();
|
||||
|
||||
// Don't notify if we are a formation member - we can occasionally be stuck for a long time
|
||||
// if our current offset is unreachable.
|
||||
// Unless the formationcontroller has reached final destination and we are stuck
|
||||
if (!IsFormationMember() || IsFormationControllerNotMoving())
|
||||
IncrementFailedPathComputationAndMaybeNotify();
|
||||
IncrementFailedPathComputationAndMaybeNotify();
|
||||
|
||||
// If there's no waypoints then we couldn't get near the target
|
||||
// If we're globally following a long path, try to remove the next waypoint,
|
||||
|
|
@ -1013,11 +1035,8 @@ bool CCmpUnitMotion::HandleObstructedMove()
|
|||
return false;
|
||||
|
||||
if (m_FailedPathComputations >= 1)
|
||||
{
|
||||
// Inform other components - we might be ordered to stop, and computeGoal will then fail and return early.
|
||||
CMessageMotionUpdate msg(CMessageMotionUpdate::OBSTRUCTED);
|
||||
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg);
|
||||
}
|
||||
MoveObstructed();
|
||||
|
||||
CFixedVector2D pos = cmpPosition->GetPosition2D();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue