Subsystem: Visibility - Adam-Poppenheimer/Civ-Clone GitHub Wiki
The Visibility subsystem implements two main features: Determining which cells a particular civilization can see, and which they've explored.
At the start of the game, almost the entire world is unexplored, its contents unknown. Civilizations can explore that map by sending units out into the world. As units move, they explore cells within their visibility range, whose basic layout remains known for the rest of the game. Units project vision out to their visibility range, which allows their civilization to see foreign units and cities in those cells. A similar thing occurs with cultural boundaries: A civilization automatically discovers all cells within 1 hex of a cell within their borders, and has visibility over that cell, too.
MapResources have additional visibility restrictions beyond that. Certain resources (like Iron and Horses) require certain technologies to be researched before they become visible on the map. Thus an explored and visible cell can have a resource on it without the civilization in question knowing about it.
Visibility is built from 3 main classes: (I)ExplorationCanon, (I)VisibilityCanon, and VisibilityResponder. It also has its own DI installer (VisibilityInstaller), its own signals (VIsibilitySignals) and a pair of enums to switch between various visibility and exploration modes useful for development and debugging.
ExplorationCanon keeps track of which cells each Civilization has explored. It provides a handful of methods for querying and changing cell exploration status and emits messages through some elements of VisibilitySignals.
VisibilityCanon keeps track of two things: the visibility of IHexCells to ICivilizations, and the visibility of IResourceDefinitions to ICivilizations. IncreaseCellVisibilityToCiv() and DecreaseCellVisibilityToCiv() changes the number of entities that are currently seeing the cell. It's important for units, whose vision of various cells changes constantly. This construction exists so that, when a unit loses sight of a cell, the unit's Civilization doesn't if there's another source of vision nearby. For resource visibility, IsResourceVisible() performs a relatively simple check that mostly queries the technologies a particular civ possesses. It doesn't take an ICivilization as an argument, instead determining whether the resource should be visible to whoever's looking at the screen right now.
Both VisibilityCanon and ExplorationCanon can operate on a number of different modes, which exist as settable properties on the corresponding interfaces. For exploration, you can choose between recording the exploration of the active civ, or letting all cells be explored. For VisibilityCanon, you can switch between tracking the vision of the active civ, making all cells visible, or making all cells hidden (though possibly still explored).
The main (and almost only) consumer of IVisibilityCanon and IExplorationCanon is the VisibilityResponder class, which listens to a number of unit, city, civ, and core signals to determine when visibility needs to be reset. The current implementation is somewhat aggressive. It clears IVisibilityCanon and then iterates through every city and unit in the game, adding their visibility and exploration data back in. Then it refreshes the visibility of every single cell. It does this in a Unity Coroutine so that it can wait a few frames for, say, topology generation to settle so it doesn't interrupt certain important processes.