-
Notifications
You must be signed in to change notification settings - Fork 2
Description
Vessel Rework and Simulation Roadmap
1. Executive Summary & Goals
The current vessel simulation architecture, where all vessels are always loaded as single, monolithic rigid bodies, presents significant limitations in performance, physical fidelity, and gameplay possibilities. This document outlines a comprehensive rework of the vessel system to address these limitations.
The primary goals of this rework are:
- Performance & Scalability: Move from an "all-vessels-loaded" model to an on-demand "bubble" where only nearby vessels are physically simulated. This is critical for supporting complex career saves with many vessels.
- Physical Fidelity: Evolve vessels from single rigid bodies into multi-body systems connected by joints. This will enable more realistic structural mechanics, flexing, and failures.
- Gameplay Flexibility: The new architecture will support more complex vessel designs, docking, and construction mechanics.
- Maintainability: Decouple the part connectivity graph from the Unity
GameObjecthierarchy to create a more robust and easier-to-manage system.
2. Core Architectural Changes
2.1. Vessel Structure: From Monolith to Multi-Body "Islands"
The fundamental concept of a Vessel will be redefined. The hierarchy will shift from a tree of parts to a collection of physics clusters.
- Vessel: A logical container that owns a list of
VesselIslands. It is responsible for high-level state, metadata, and trajectory simulation. - Vessel Island: A group of parts that are rigidly connected and share a single
Rigidbody. All parts within an island are considered a single, perfectly rigid body. Structural flexing and articulation only occur between islands via joints. - Part (Logic): A pure data class holding state, resources, and references to specific
VesselComponents. - Part View (GameObject): The visual and collider representation (
MonoBehaviour) that exists only when the vessel is fully loaded. - No "Root Part": The concept of a specific "Root Part" that dictates the hierarchy of transforms is removed. The vessel is a graph of connected islands.
2.2. Part Connectivity Graph
The logical connection between parts will be separated from the visual GameObject hierarchy.
- Attachment Graph: A directed graph will represent all part-to-part connections. An edge will exist from a parent part's
FAttachNodeto a child part'sFAttachNode. - Graph Traversal: Algorithms (BFS/DFS) will traverse this graph to detect "Rigid Clusters". A
VesselIslandis effectively the runtime result of such a cluster. - Dynamic Splitting: When a joint breaks or a decoupler fires, the cluster detection re-runs. If the graph splits into discontinuous sub-graphs, new
Vessels andVesselIslands are created automatically.
2.3. GameObject Hierarchy Rework
To support the island model and improve performance, the GameObject hierarchy will be standardized and flattened.
- New Structure:
Vessel (root GameObject with Vessel component) ├── Island 0 (GameObject with Rigidbody and IPhysicsTransform) │ ├── PartView A (Mesh, Colliders) │ ├── PartView B (...) │ └── PartView C (...) └── Island 1 (GameObject with Rigidbody and IPhysicsTransform) ├── PartView D (...) └── PartView E (...) - All parts within an island are siblings in the hierarchy, parented to the island's
GameObject. The islands are, in turn, siblings parented to the mainVesselobject.
3. Physics & Simulation Rework
3.1. Composite Reference Frame Transform
The HybridReferenceFrameTransform will be replaced by a CompositeReferenceFrameTransform capable of handling a cloud of rigidbodies.
-
Absolute Mode (On-Rails):
- Aggregate State: The trajectory system simulates the Center of Mass (CoM) of the entire vessel cluster.
- Calculation: When switching to Absolute Mode, the system iterates all Islands to compute the Mass-Weighted Average Position and Velocity.
- Relative Storage: A "Main" island (e.g., largest mass) is selected. The relative positions and rotations of all other islands are stored relative to this Main island. Only the Main island is virtually tracked; others are assumed rigidly attached.
-
Scene Mode (Physics):
- Restoration: The system instantiates the
GameObjects. It applies the Absolute Velocity to the "Main"Rigidbody. - Offset Restoration: Secondary islands are restored based on their stored relative offsets to the Main island.
- Velocity Dampening (Crucial): Upon loading physics, relative velocities between islands must be zeroed out (treated as a rigid whole) to prevent immediate physics explosions caused by slight drift or floating point errors. This zeroing must occur in the non-inertial frame to preserve angular momentum.
- Restoration: The system instantiates the
3.2. On-Demand Vessel Loading ("Vessel Bubbles")
To dramatically improve performance, vessels will be loaded and unloaded dynamically based on their proximity to an observer (e.g., the active vessel).
- Packing (Unload): Runtime state is serialized to
VesselData.GameObjects are destroyed. TheVessellogical object remains alive in memory to handle resource consumption or background logic. - Unpacking (Load):
VesselDatais deserialized.PartViewprefabs are instantiated. Joints are reconstructed. - Loading Logic:
- A configurable load/unload distance will determine the "physics bubble".
- Loading/Unloading is asynchronous to prevent frame drops.
- Hysteresis: A buffer zone (e.g., load at 2.5km, unload at 3.0km) will be used to prevent rapid loading/unloading cycles.
3.3. Vessel Simulation States
A vessel will exist in one of several simulation states to manage performance and stability.
Physical: The vessel is fully loaded in the physics bubble, with activeRigidbodys and components. This is the only state where a vessel can be actively controlled or interact with other objects.Physicsless(On-Rails): The vessel'sGameObjectis loaded and visible, but allRigidbodys are kinematic. Its position is updated directly by the trajectory system. This is for visible but non-interactive vessels outside the immediate physics bubble.Background(Unloaded): The vessel exists only as data. Its trajectory is still simulated, but noGameObjectis present in the scene.VesselComponents may still receive ticks (e.g., for resource processing).
3.4. Far Vessel Pinning
Landed, stationary, or distant vessels can be "pinned" to the surface of a celestial body to save performance.
- Pinning Condition: A vessel is eligible for pinning if it is outside a certain range of the active vessel. Contrary to initial thoughts about only pinning stationary vessels, it's safer to pin any distant vessel to prevent physics instability when its
GameObjectis unloaded (e.g., falling through terrain). - Mechanism: When pinned, its state (velocity, angular velocity, etc.) is saved to a serializable variable. The
ReferenceFrameTransformis replaced with aPinnedReferenceFrameTransform. - Unpinning: A vessel is unpinned and reloaded into a
Physicalstate when it enters the physics bubble. Its saved velocity and other parameters are restored, ensuring continuity of motion.
3.5. Asynchronous Simulation Pipeline
To manage the increased computational load of multi-body physics, on-demand loading, and other complex systems, the simulation loop will be re-architected to run asynchronously. This will move heavy calculations off the main thread, preventing physics stutter and ensuring a responsive user experience. The full details of this architecture are outlined in the Asynchronous Simulation Architecture document. This system is built around two key concepts:
-
A Dual-Loop Model: The
AsyncSimulationManagerorchestrates two parallel loops:- Fixed Update Loop (
IAsyncFixedSimSystem): For physics-critical tasks (e.g., short-term trajectories, resource flow) that must be synchronized with theFixedUpdatephysics step. - Update Loop (
IAsyncUpdateSimSystem): For non-critical, long-running tasks (e.g., map view trajectory prediction, career mode processing) that should not block the main thread.
- Fixed Update Loop (
-
The "Prepare-Perform-Apply" Pattern: Each simulation step is broken into three phases, managed by callbacks in a
PlayerLoophook:- Prepare (Main Thread, Pre-Physics): Gather data from live
GameObjects into thread-safe snapshots. - Perform (Background Thread): Run all heavy computations using only the snapshot data.
- Apply (Main Thread, Post-Physics): Apply the simulation results back to the live
GameObjects, correcting their state after the physics step.
- Prepare (Main Thread, Pre-Physics): Gather data from live
4. Serialization Overhaul
The vessel save format must be updated to support the new architecture.
- Proposed File Structure: For a single vessel, the data will be split into multiple files within its save directory:
_vessel.json: Contains the top-levelVesselmetadata, simulation state flags, and a list of its islands.islands.json: An array of island definitions, including each island'sRigidbodystate.parts.json: A flat list of all serialized part data.graph.json: Defines the attachment graph, storing connections betweenFAttachNodes by referencing part and node IDs.
5. Component & API Changes
-
VesselComponentSystem (Logic vs View):- Current: Components like
FRocketEngineinherit fromMonoBehaviourand mix logic with Unity transforms. - Target: Introduce a pure C#
VesselComponentbase class. This contains the logic (e.g., consuming fuel, calculating thrust). It has a lifecycle (OnLoad,OnFixedUpdate,OnUnload) managed by aVesselComponentSystem. - View: The visual aspect (particle effects, sound sources, transform positions) remains on a
MonoBehaviour(thePartView). - Interaction: When Loaded, the
VesselComponentacquires a reference to itsPartView. When Unloaded, it releases the reference but maintains its data state.
- Current: Components like
-
Refactor
Vessel.cs:- Remove
RequireComponent(typeof(Rigidbody)). - Remove
IPhysicsTransformimplementation from the Vessel itself; delegate it toVesselIslands.
- Remove
6. Analysis of Current Implementation & Gaps
The proposed rework introduces several fundamental changes that are inconsistent with the current implementation. These areas will require significant refactoring.
-
Vessel&IPhysicsTransformCoupling: Currently, theVesselcomponent assumes it coexists on the sameGameObjectwith a singleIPhysicsTransformthat manages a singleRigidbody.- Conflict: In the new model, the
Vesselcomponent will be a manager for multiple "islands." TheIPhysicsTransformandRigidbodycomponents will move to the islandGameObjects. - Resolution: The
Vesselclass must be refactored to manage a collection of islands and their respective physics bodies.Vessel.PhysicsTransformwill likely be deprecated or changed to refer to the "root" island's transform.
- Conflict: In the new model, the
-
VesselHierarchyUtils& Separation Logic: The currentVesselHierarchyUtils.SetParentmethod is entirely based onTransformparenting and single-body physics.- Conflict: This logic is incompatible with the attachment graph and multi-body island model. A simple reparenting can no longer split a vessel.
- Resolution: Vessel separation must be completely re-implemented. The new process will be:
- Graph Operation: A separation event (e.g., decoupler firing) severs an edge in the attachment graph.
- Island Discovery: A graph traversal algorithm (like Breadth-First Search) determines the new sets of connected parts.
- Island Creation: If the separation results in a new, disconnected set of parts, a new
IslandGameObjectis created. - Physics Realignment: The separated parts are moved in the
GameObjecthierarchy to their new island. New mass, CoM, and inertia tensors are calculated for all affected islands (the original and the new one). - Vessel Creation: If the new island is not connected to any other island in the original vessel via a joint, a new
Vesselobject is created to manage it. - Conservation of Momentum: On separation, the linear and angular momentum of the system must be conserved. The new velocities and angular velocities of the resulting bodies must be calculated based on the pre-separation state and the masses/inertia tensors of the new bodies.
-
Mass & Inertia Calculation: The current
Vessel.RecalculateMassaggregates mass from allIHasMasscomponents in the hierarchy and applies it to a singleRigidbody.- Conflict: This is no longer valid. Physics properties must be calculated per-island.
- Resolution: The mass calculation logic must be adapted to run for each island, iterating only over the parts belonging to that island. The
Vesselclass will delegate these calculations to its islands.
7. Implementation Roadmap
This rework will be implemented in phases to ensure stability at each step.
-
Phase 1: Foundational Refactor (Single Island First)
- Implement the attachment graph system, decoupling part logic from the
Transformhierarchy. This graph must provide a clear, public API for a part to query its logical parent. - Update the
Vesselclass and construction system to use the attachment graph, while still assuming a single island andRigidbody. - Implement the new multi-file serialization format for single-island vessels. This must support saving and loading both standard parts from
GameData(by reference) and any procedural parts like resource pipes (by value) created in the VAB. For temporary/unbaked procedural parts in the editor, a dynamic asset ID scheme (e.g., "proc::@<json_params>") should be investigated. - Implement high-fidelity inertia tensor calculation from part meshes to ensure accurate rotational physics for complex shapes.
- Implement the attachment graph system, decoupling part logic from the
-
Phase 2: Component System Refactor
- Create
VesselComponentabstract base class andVesselComponentSystemmanager. - Refactor
IHasMass,IResourceContainer, etc., to work onVesselComponent. - Convert major components (
FRocketEngine) to inherit fromVesselComponent, separating Logic (Data) from View (GameObject).
- Create
-
Phase 3: Multi-Body Physics
- Introduce the "Island" concept. Modify the
Vesselclass to manage multiple islands. - Implement
PhysXjoint creation and management between islands based on attachment node types. - Create the
CompositeReferenceFrameTransformto handle on-rails and physics simulation for multi-body vessels using mass-weighted averages. - Update separation logic (
VesselHierarchyUtilsreplacement) to correctly split islands and create new vessels, ensuring conservation of momentum.
- Introduce the "Island" concept. Modify the
-
Phase 4: On-Demand Loading
- Implement the "vessel stub" system and the
VesselManagerlogic for tracking all vessels in a timeline. - Create the "physics bubble" logic for loading/unloading vessel
GameObjects asynchronously. - Define and implement the
Physical,Physicsless, andBackgroundsimulation states. - Implement the "Pack" (Serialize/Destroy) and "Unpack" (Deserialize/Instantiate) logic using the
VesselComponentdata state.
- Implement the "vessel stub" system and the
-
Phase 5: Optimizations & Future Work
- Implement the
Far Vessel Pinningsystem. - (Post-release) Investigate a lightweight background processing system for unloaded vessels to handle things like resource consumption without loading their
GameObjects. - Implement a VAB "Part Swapping" tool, enabled by the attachment graph, to allow one-click replacement of parts that share the same attachment node topology.
- Implement the
8. Recommended Ancillary Refactors & Fixes
While overhauling the vessel system, it is opportune to address several related areas of the codebase. These changes, while not strictly part of the core rework, will improve maintainability, performance, and alignment with the new architecture.
-
Deprecate and Remove Obsolete Code:
- What: The
FBulkConnectionand commented-outFBulkContainer_Spherecomponents are marked as obsolete. - Why: They have been superseded by the
IBuildsFlowNetworksystem (FResourceConnection_FlowPipe,FResourceContainer_FlowTank). Leaving them in the codebase creates confusion. - Action: Physically remove the obsolete files from the project.
- What: The
-
Adapt Control Systems for Multi-Body Physics:
- What: The core avionics component (
FAttitudeAvionics) produces a high-level attitude command (e.g., "pitch up"). Downstream components likeFGimbalActuatorControllerandFReactionControlControllerare responsible for translating this command into specific physical actions (gimbal deflection, RCS thrust) relative to a designatedFControlFrame. - Why: In a multi-body vessel, applying forces and torques to achieve a desired rotation is no longer trivial. A simple PID loop that assumes a single rigid body can induce or worsen oscillations between islands. The controllers that actuate physical devices must become aware that they are part of a multi-body system.
- Action: Refactor actuator controllers (
FGimbalActuatorController, etc.) to correctly distribute control authority across multiple, potentially moving, physics islands. The logic must intelligently calculate the required forces and torques on each island to achieve the vessel-wide attitude command without causing instability. This may involve more advanced control algorithms or simply a more robust definition of how theFControlFrameis used in a multi-body context.
- What: The core avionics component (
-
Generalize Force Application:
- What: Components like
FRocketEngineapply forces directly tovessel.PhysicsTransform. - Why: In the new model, forces must be applied to the specific
Rigidbodyof the island that the part belongs to. - Action: Refactor all force-producing components. Add a mechanism for each part to cache a reference to its parent island's
IPhysicsTransformandRigidbody, and direct all force/torque applications there.
- What: Components like
-
Define Resource Flow Across Joints:
- What: The
IBuildsFlowNetworksystem connects resource containers via explicit components likeFResourceConnection_FlowPipe. - Why: With vessels splitting into multiple islands or even new vessels, the behavior of these connections must be explicitly defined.
- Action: The established rule is that if a pipe connects two parts, resources will flow regardless of whether they are on the same or different (but joint-connected) islands. To handle vessel separation, new event listeners must be created. These listeners will subscribe to island split events (
ON_AFTER_VESSEL_ISLAND_SPLIT) and automatically sever anyFResourceConnectioncomponents that now span two disconnected vessels. A future enhancement could also sever connections if a joint flexes beyond a certain structural limit, simulating a pipe breaking.
- What: The
-
Modernize Manager Interactions with Unloaded Vessels:
- What: Systems like
ActiveVesselManagerandAllLoadedVesselsPOIGettercurrently operate on the assumption that all vessels are fully loadedGameObjects (VesselManager.LoadedVessels). - Why: With the new on-demand loading system, these managers will need to work with "vessel stubs."
- Action:
- Refactor
VesselManagerto manage both stubs and fully loadedVesselinstances. - Update
ActiveVesselManagerto handle cases where the active "vessel" might just be a stub, and ensure it is always loaded. - Modify
AllLoadedVesselsPOIGetterto source its points of interest from the trajectory data of all vessel stubs, not just loaded GameObjects, to ensure terrain LOD is generated correctly for approaching vessels.
- Refactor
- What: Systems like
-
Review Physics Synchronization via
PlayerLoop:- What: Several
ReferenceFrameTransformimplementations inject logic directly into Unity'sPlayerLoopfor precise synchronization with the physics step. - Why: This is a powerful but complex and potentially fragile technique. The major refactor of physics components is a good time to review this.
- Action: Re-evaluate if this is the most robust and maintainable solution. Investigate if newer Unity APIs or a different combination of
MonoBehaviourexecution order and events could achieve the same result with less complexity.
- What: Several
-
General Code Cleanup:
- What: The codebase contains several
#warningpragmas and// TODOcomments. - Why: A major rework is the perfect opportunity for housekeeping.
- Action: Audit all warnings and to-do items within the files being modified for the vessel rework. Address them, remove them if obsolete, or create new roadmap items if they represent larger tasks. For example, the
IResourceContainerinterface has a warning suggesting it should be moved.
- What: The codebase contains several