Sail Controller
Quick Start
Calculates lift and drag forces based on wind conditions, sail geometry, and angle of attack.
Prerequisites
Before setting up a sailing ship, ensure you have:
- A ship with
WaterObjectcomponent andRigidbody(follow the Ship Controller guide first) AdvancedShipControllercomponent on the ship (for input handling)- Input bindings set up (see the Input guide)
Setting Up Wind Generation
- Create an empty GameObject in your scene and name it
WindGenerator. - Add the
WindGeneratorcomponent to it. - Configure the wind parameters:
Base Direction- Primary wind direction in degrees (0 = north/+Z axis)Base Speed- Average wind speed in m/s (typical: 5-20 m/s)Max Direction Variation- Angular deviation during gusts (15-45 degrees)Max Speed Variation- Speed deviation from base speedMin/Max Variation Interval- Time between wind changes
Note: Only one WindGenerator should exist per scene as it uses a singleton pattern.
Creating a Sail Preset
- Right-click in the Project window and select
Create > NWH > DWP2 > SailPreset. - Name the preset (e.g., "SquareSail" or "LateenSail").
- Configure the aerodynamic curves:
Lift Coefficient Vs AoA Curve- How lift varies with angle of attackDrag Coefficient Vs AoA Curve- How drag varies with angle of attackLift ScaleandDrag Scale- Global force multipliers
The preset includes default curves suitable for most sail types. Different sail designs (square, lateen, bermuda) can be represented by adjusting these curves.
Setting Up the Sail
The sail is defined by four corner transforms arranged in a clockwise pattern:
Create four empty GameObjects as children of your ship to represent sail corners:
Corner_A- Bottom front (bottom left for square sails)Corner_B- Top front (top left for square sails)Corner_C- Top rear (top right for square sails)Corner_D- Bottom rear (bottom right for square sails)
Position these corners to define your sail shape. For a simple square sail:
- Place A and D at the bottom of the mast
- Place B and C at the top of the mast
- Adjust the spacing to create the desired sail width and height
Add the
SailControllercomponent to a child GameObject of your ship (the one with theRigidbody).Assign the corner transforms to the SailController:
- Drag
Corner_Ato fielda - Drag
Corner_Bto fieldb - Drag
Corner_Cto fieldc - Drag
Corner_Dto fieldd
- Drag
Assign the
Sail Presetyou created earlier.Adjust
Air Densityif needed (default 1.225 kg/m³ is standard sea level).
Note: Corner transforms can be attached to different parents to enable sail furling or complex rigging. For example, attach top corners to a rotating boom for realistic sail control.
Adding Sail Rotation (Optional)
To allow player-controlled sail rotation:
Create a GameObject as a child of your ship (e.g., "SailBoom").
Parent the sail corner transforms that should rotate with the boom (typically the rear corners C and D).
Add the
SailRotatorcomponent to the boom GameObject.Configure:
Rotation Axis- Local axis to rotate around (default: Y-axis)Rotation Speed- Rotation speed in degrees per second
Add a
RotateSailinput axis in Unity's Input Manager:- Positive button: D or Right Arrow
- Negative button: A or Left Arrow
Note: The SailRotator reads input from the parent AdvancedShipController component.
Testing the Setup
- Press play and select your ship using the
Vkey. - The sail should now generate force based on wind conditions.
- Use the scene view with Gizmos enabled to see:
- Sail corners (white spheres)
- Sail directions (red = right, green = up, blue = forward)
- True wind (green arrow)
- Apparent wind (yellow arrow)
- Sail force (red arrow)
- Ship velocity (magenta arrow)
How It Works
Apparent Wind Calculation
The sail system calculates apparent wind - the wind experienced by the moving vessel. Apparent wind combines the true wind and the ship's velocity, which is why a ship can sail faster than the wind itself and why wind direction changes as the ship moves.
Force Generation
The sail generates two types of forces:
Lift Force - Acts perpendicular to the sail surface
- Direction determined by the sail's right vector
- Magnitude based on lift coefficient curve at current angle of attack
- Primary propulsion force
Drag Force - Acts in the direction of apparent wind
- Always opposes relative motion through air
- Magnitude based on drag coefficient curve at current angle of attack
Total force depends on air density, apparent wind speed, and sail area.
Angle of Attack
The angle between the sail's forward direction and the apparent wind determines the coefficients:
- 0° to ±45° - Efficient sailing angles with high lift
- ±45° to ±90° - Reduced efficiency, transitioning to drag-dominated
- ±90° to ±180° - Luffing (sail flapping), mostly drag
Heel Compensation
The system compensates for vessel heel (roll) by scaling forces based on sail verticality. This prevents excessive force generation when the sail is nearly horizontal.
Field Explanations
Geometry
a,b,c,d- Four corner transforms defining the sail shape. Must be assigned in clockwise order: front-bottom, front-top, rear-top, rear-bottom. These can be parented to different GameObjects to enable sail furling or complex rigging.
Physics
Sail Preset- ScriptableObject containing lift and drag coefficient curves versus angle of attack. Different sail types (square, lateen, bermuda) require different presets.Air Density- Air density in kg/m³ used in force calculations. Standard sea level is 1.225. Can be used as a global force multiplier to tune overall sail power without modifying the preset curves.
Calculated Properties (Runtime)
The following properties are calculated each frame and visible in the inspector during play mode:
Sail Geometry:
Sail Center- Surface-weighted center point where forces are appliedSail Area- Total sail surface area in m²Sail Forward- Forward direction vector of the sailSail Up- Up direction vector of the sailSail Right- Right direction vector (perpendicular to sail plane)
Wind & Forces:
True Wind- Environmental wind from WindGeneratorShip Velocity- Current vessel velocityApparent Wind- Wind relative to the moving ship (True Wind - Ship Velocity)Angle Of Attack- Angle between sail forward and apparent windSail Force- Total aerodynamic force vector applied to the ship
Notes and Tips
Multi-Sail Setups
- Add multiple
SailControllercomponents to create ships with multiple sails (main sail, jib, mizzen, etc.) - Each sail can have its own preset and corner transforms
- Each sail calculates forces independently
Triangular Sails
For triangular sails (like a lateen or bermuda rig):
- Position one corner at the same location as another (e.g., A and D both at the boom)
- The sail area calculation will still work correctly
- Alternatively, use very short edge length between paired corners
Sail Furling
To implement furling:
- Attach top corners to one parent GameObject
- Attach bottom corners to another parent GameObject
- Animate the distance between these parent objects
- As corners move closer together, sail area automatically reduces
- Forces scale proportionally with area
Performance
- Sail physics run in
FixedUpdate()at physics timestep rate - Gizmo drawing only occurs in editor, not in builds
- Wind generation uses coroutines for smooth transitions
Debugging
Enable Gizmos in the Scene view to visualize:
- Sail shape and corners
- Wind vectors
- Force vectors
- Sail orientation axes
The inspector shows real-time debug info during play mode:
- Current angle of attack
- Force magnitude
- Force vector
Common Issues
Sail not generating force:
- Check that
WindGeneratorexists in scene - Verify
SailPresetis assigned - Ensure all four corner transforms are assigned
- Check that wind speed is non-zero
Incorrect force direction:
- Verify corner assignment order (a, b, c, d clockwise)
- Check sail orientation using gizmo arrows
- Ensure
SailForwardpoints in the expected direction
Sail rotating incorrectly:
- Check
SailRotatorrotation axis direction - Use negative axis values to reverse rotation
- Verify input binding for
RotateSailaxis