Recent Changes - Search:

Main.SideBar (edit)

PmWiki

UnitsInUnitsEnterUnitPlugin

This page belongs to the UnitsInUnits "use-case".

On this page mostly the "EnterUnitPlugin" side is explained, i.e. what happens in the unit that enters another unit. Note that this not only covers class "EnterUnitPlugin", but also e.g. the UnitMover that takes care of large parts of the work. The UnitMover code essentially complements the EnterUnitPlugin code.

The EnterUnitPlugin is a plugin that every mobile unit has. However it may be very well possible, that such a unit can not enter any unit storage at all - this is decided by the UnitStoragePlugin.

The plugin handles both entering and leaving, because I believe they are tightly coupled, they are somewhat similar concepts, are executed by the same object and influenced (mostly) be the same objects (but "EnterAndLeaveUnitPlugin" sounds really bad).

However while I think the code of both concepts should be close to each other, I think they need to be developed/planned/explained separately - they heavily differ in details. This has in particular proven to be true for airplanes: they always must move while entering (i.e. still flying), but can stand still and turn like normal ground units while leaving.
Both concepts can be seen as state machines and this is how they have been developed.

Entering

Below is the final state machine diagram that was used for implementing the "entering" code.

Some comments:

  • While a unit is in "MovingToStoragePoint" state, it assumes that the storing unit is standing still. The storing unit must not move in that time!
    Of course that is relevant for transportation (i.e. mobile) units only.
  • Before someone asks why we have two "EnterPoints" (EPs): Usually EP1==EP2 and an "aggressive" implementation may skip the "MovingToEP2" state (i.e. go to the "MovingToStoragePoint" in the same advance call where it reached "MovingToEP2").
    There is however a difference for airports: here the EP1 is meant to be further away from the airport and EP2 is where it starts to lose height (i.e. to start landing). The distance between EP1 and EP2 should be chosen by the storage so, that the entering unit will be rotated in the correct direction once it reached EP2. This is required, because airplanes cannot rotate without moving.
  • When the "WaitForPermission" state is left successfully, the unit enters the "MovingToEP2" state. However once it reached EP2, it has to check for permission again: it must check whether the enter permission may have been revoked while the unit was moving to EP2.
    If the unit is at EP2 (and correctly rotated) and the enter permission is still valid, the unit enters the storage. At this point, the enter permission can't be revoked anymore.
  • Once the unit is inside the unit, moving must never fail. Therefore MovingToStoragePoint must not check whether the unit has arrived at the destination point - once the moving path has been completed, the unit must be at the destination point.
    • As a consequence stopMoving() must not be called on the unit while it is in MovingToStoragePoint

Note in particular the "moving must never fail" condition while a unit is inside a unit. This is very important:

  • when a landing aircraft "stops", it suddenly "hangs in the air", because the EnterUnitPlugin and it's UnitMover already have the control over the unit and there we can't have some kind of "moveIdle()" method.
  • error handling would be a pain in the ass, if errors would be possible. If we assume that moving always succeeds, then we can "fix" errors afterwards. For example if a unit by some reason could not move the desired distance in advance call n, then advance call n+1 can simply assume it did move and move it one step further. The effect would be (in worst case) a small "jump" of the unit. If we had to do error handling, we would probably have to write a whole dedicated UnitMover for moving inside units (the UnitMoverInsideUnit is currently essentially just a slightly extended "normal" UnitMover).
  • when a unit stops while entering/leaving, no other unit can enter/leave anymore, until that unit resumes the process: the path out is blocked (technically speaking the path is not blocked, because we have no collision detection here. however you can see on UnitStoragePlugin page, that no other unit can get a leave permission while a unit is entering/leaving)

Leaving

Leaving a unit is mostly similar to entering above. Some things however changed. The diagram:

Some comments:

  • As you can see in (*3), it is yet undecided whether "MovingToOutside" might be aborted sometimes (i.e. while the unit is still on the ground). It makes things more difficult, but might be a handy feature.
  • We don't need multiple different "MovingToOutside" states: an "EnterPoint" in the entering state machine was required only, because we need to move the unit close to the storage before we can start the actual entering. The "EnterPoint1" and "EnterPoint2" states are required only for rotating a unit that cannot stop moving in the desired direction before entering. Both is not required when leaving, as the unit already is at a defined position (the storage position) and can be rotated easily (since it still is on the ground).

UnitMover

The UnitMover class is what contains the actual moving code of the unit. For moving inside a unit it obviously must be modified to meet certain special requirements:

  • The entering unit must never collide with the storing unit
  • Ideally two units inside a unit must never collide with each other (to simplify moving, pathfinding and error handling greatly)
  • Planes must be able to
    • stop moving
    • move on the ground
    • change their z position, i.e. must be able to land and to take off again
  • The unit must use a predefined path provided by the UnitStoragePlugin only.

Most of these can easily be implemented in a normal UnitMover by checking for certain conditions. However the "planes must be able to move on the ground" is tricky because of the current UnitMover design, which provides a dedicated UnitMover for aircrafts.
Therefore a UnitMoverInsideUnit has been created, which derives from UnitMoverLand and adds some code for flying units: in particular landing and taking off.

This UnitMoverInsideUnit

  • retrieves it's pathpoints from the EnterUnitPlugin (every mobile unit has one, so this can safely be done)
  • is used instead of the "normal" unit mover of the unit, as soon as setIsInsideUnit(true) was called on the unit. The unit reverts to the normal mover again once setIsInsideUnit(false) is called.
Edit - History - Print - Recent Changes - Search
Page last modified on November 21, 2006, at 00:26