# Part modding guide

The aim of this tutorial is to guide you through the process of creating your first **part mod** for Kerbal Space Program 2. We will go over everything from creating the part's mesh and textures to setting up the part in Unity to be bundled into a KSP2 mod.

The way this tutorial will be structured is as a succession of steps which may link to other tutorials on this wiki, do not hesitate to keep this main page open while perusing the other tutorials. We aim at being as comprehensive as possible to enable you to make any part mod, but this page is still work in progress so stuff might be incomplete and/or subject to change in the future.

## Creating the part asset

The first step in your part mod creation journey is to create the part's "3D asset", meaning its 3D mesh, textures and eventual animations. You can use any software you're comfortable with to do so but here are some guides for some specific software if you desire:

[Modeling the mesh in Blender](/doc/bcb638b8-8995-4c05-ac96-c898247fa1fd)

[Texturing the mesh in Substance 3D Painter](/doc/d6d042c3-6761-4f5c-a8c1-c9ee9f4352d7)

Here are some resources that can be useful for modelling and texturing, regardless of the software you're using:

[Standard part sizes](/doc/3dac0a00-af53-4851-a425-c298e3376ba2)

[Texturing basics](/doc/8b6ab224-f7cf-4dd7-9f10-5741984a84cd)

## Basic Unity part mod project setup

Now that you have created a model and textures for your part, the next step is to set up a Unity project that will be used to configure your part and build the asset bundles that will contain your mod's contents.


1. **Creating the project:** Follow the [Setting up a mod in Unity](/doc/e361c8c3-8fe1-42e6-9596-fb789b913fe0) tutorial to create and set up a project for part modding.
2. **Materials folder:** Inside your mod’s folder, create a folder called Materials. You’ll be storing the textures and materials you need there. E.g., `Assets/MyAwesomeMod/Materials`. This is just to aid in organization.
3. **Parts folder:** Inside your parts pack folder, create a folder called Parts. You’ll be storing the part meshes and related things there. E.g., `Assets/MyAwesomeMod/Parts`. You can have whatever organization you like here, so if you want to group some parts you might create group folders within Parts (e.g., Methalox Engines, Nuclear Engines, Ion Engines, etc.). This is just to aid in organization and is optional.

## Localization

Localizations are read from the mod’s `localizations` folder. One is automatically created for you when you create a new mod in the SDK in the folder `Assets/MyAwesomeMod/Copied/localizations`. Put your CSV files in there.


:::warning
**NOTE!** This is currently required to be exactly this - localization__s__ (plural), not localization (singular), and must be lowercase!

:::

* Create Localization file: Localization files are CSV files following a particular format. These must have lines ending with LF, not CRLF, and they must reference the same `<part_name>` you use in the Part Production process below. There are some other restrictions for content, particularly that if you want a string that contains a “,” that string needs to be enclosed in quotes or the comma will mess with how the strings are parsed. These files are where the part’s Title, Subtitle, Manufacturer, and Description are configured. Here’s an example:

  ```csv
  Key,Type,Desc,English,French
  
  Parts/Title/spark_spt100,Text,,SPT-100,SPT-100
  Parts/Subtitle/spark_spt100,Text,,Hall Effect Thruster with Xenon Tank,Moteur à Effet Hall et Réservoir de Xénon
  Parts/Manufacturer/spark_spt100,Text,,"Stellar Plasma-Assisted Rocket Kinetics, inc.","Stellar Plasma-Assisted Rocket Kinetics, inc."
  Parts/Description/spark_spt100,Text,,"The SPT-100 is the pinnacle in tiny (0.625m-class) Ion engines, providing high Isp and low thrust with an integral toroidal xenon tank. Strap this little guy onto a probe core and be sure to bring plenty of electrons because you're in for a long slow ride to anywhere!","Le SPT-100 a le dessus dans la catégorie des très petits (0.625m) moteurs ioniques, avec une haute impulsion spécifique et une poussée faible ainsi qu'un réservoir toroïdal de xénon intégré. Accrochez ce petit gars à vos sondes et assurez-vous d'avoir du stock d'électrons car vous allez aller de partout bien lentement!"
  
  Parts/Title/spark_x3,Text,,X3 NHT,X3 NHT
  Parts/Subtitle/spark_x3,Text,,Three-Channel Nested Hall Effect Thruster,Moteur à Effet Hall à 3 Canaux Concentriques
  Parts/Manufacturer/spark_x3,Text,,"Stellar Plasma-Assisted Rocket Kinetics, inc.","Stellar Plasma-Assisted Rocket Kinetics, inc."
  Parts/Description/spark_x3,Text,,"The SPARK X3 is the pinnacle in small (1.25m-class) Ion engines, providing high Isp and low thrust. Strap this bad boy onto your large probe or small capsule and be sure to bring plenty of electrons because you're in for a long slow ride to anywhere!","Le SPARK X3 a le dessus dans la catégorie des petits (1.25m) moteurs ioniques, avec une haute impulsion spécifique et une poussée faible ainsi qu'un réservoir toroïdal de xénon intégré. Accrochez ce petit gars à vos grandes sondes et assurez-vous d'avoir du stock d'électrons car vous allez aller de partout bien lentement!"
  ```

## Basic part setup

This part of the tutorial will go over how to create a basic KSP2 part in Unity.


1. **Create Root Part Object:** Create an empty game object under your scene (R-click **Scene**: **Game Object** > **Create Empty**). Name this object the same as your part. Recommended naming scheme: [How to name your part](/doc/092da20b-1189-4de2-be0f-7055cc945286).
2. **Create Model Object:** Create an empty game object under your root part object and name this one `model`.
3. **Create Part Folder:** Create a Part folder named for your part inside your Parts folder. E.g., `Assets/MyAwesomeMod/Parts/MyPart`, or `Assets/MyAwesomeMod/Parts/ThisGroup/MyPart` if you’re grouping parts.

### Mesh setup


1. **Bring in the Mesh:** Drag a copy of your part’s FBX file into the part folder. If you have baked textures for your part that go with the FBX (meaning, they’re based on the UV Unwrap specific to that FBX), then drag those into this same folder along with the FBX.
2. **Create Part Mesh Object:** Drag a copy of the part's FBX from the Part folder in Unity to the `model` object created in step 2. Don’t drag the FBX file from your computer’s files system, you need to use the copy you just placed in step 4. This will create a **prefab** for your part as a child of the model object.
3. **Unpack Prefab:** Right-Click part object: **Prefab > Unpack**.
4. **Remove Unnecessary Things:** Remove any objects that came in with the FBX that you don’t actually need in the game like lights, cameras, empty nodes, etc. If it’s not an actual object you want the game to render, then delete it.
5. **Orient Part:** Your model will appear in the Unity scene oriented as you built it in Blender, but this may not be the way you want it to be oriented in the game. If you need changes to the position, rotation, or scale of the part do those now using the Transform panel within the Inspector Window with your part object selected. For example, to flip a part over just give a rotation of 180 in Z, etc.

### Material setup


1. **Create the material:** Create a material in Unity for each material in Substance Painter (right-click on the project window > **Create > Material**)
2. **Select the KSP2 Shader:** Select all materials. In the **Inspector** window, in **Shader**, select **KSP > Parts > Paintable**.
3. **Apply the textures:** For each material, assign the textures to the **Albedo**, **Metallic**, **Normal**, **Emissive** and **Paintable** channels.
   * For Normal channels, click the **Fix Now** button.
4. **Set properties:** Set **Metallic/Smoothness Map** to 1 and check **Use PaintMask for Paint Smoothness**.
5. **Apply materials:** For each mesh, assign the materials to the corresponding locations. Click on **Apply**.

### Collider setup


1. **Create Collider Object:** R-Click `model` object: Create Empty. Name this object `col`.
2. **Create Collider:** In the Inspector window for the col object click “Add Component”. Search for Mesh Collider and pick it. This will create a Mesh Collider component in the col object. Click the arrowhead to the left of it to expand it and see its properties.
   * **Select Mesh:** In the Mesh Collider properties select the Mesh you want to use. If your FBX is all one object you can pick that, or you can pick a suitable primitive like cube or cylinder, etc.
   * **Position, Rotation, and Scale:** Set the position, rotation, and scale of the mesh to encompass the part. You should see a green mesh represented in the Scene window to help guide you to make sure you’ve got the right position, rotation, and scale.
   * **Convex:** Check “Convex”

### Core Part Data setup


1. **Add Core Part Data:** Select your Root Part Object. In the Inspector Window click “Add Component”. Search for “Core Part Data” and pick that. Open it up and configure as follows:

   
   1. **Part Name:** The Part Name needs to be the same as what you’ve used for the Root Part object, i.e., `my_awesome_mod_my_part` or whatever you used.
   2. **Author:** Use what you like here, typically your KSP Forum screen name or whatever you go by as your modding author name.
   3. **Category:** Select an appropriate category for your part from [Part category](/doc/4c299b08-2a8e-482e-be18-b8a2f9238d89).
   4. **Family:** If you wish to identify a “Family” for your part, this needs to be a particular string. You can find examples here: [Part family](/doc/e6911207-7827-493a-872b-4aa0b6f3f5b7).
   5. **Co Lift, Co Mass, Co Pressure, etc.:** These parameters allow you to set the Center of Lift, Center of Mass, Center of Pressure, etc. Adjust these to get the markers in the Unity scene where they should be for your part. Typically, Co Pressure and Co Lift are in the same place.
   6. **Fuel Cross Feed:** Check if fuel should be able to transit through your part on the way to other parts. Typically set to true, but not always.
   7. **Mass:** Set this in metric tons, not Kg.
   8. **Attach Rules:** Check the types of attachment your part should allow. Checking “Stack” or “Srf Attach” will allow your part to attach in a stack or to a surface. Checking “Allow Stack”, “Allow Srf Attach”, etc. will allow other parts to stack attach or surface attach respectively. *Currently (?) Allow Collision, Allow Dock, Allow Rotate, and Allow Root have no effect in game (check this)*.
   9. **Attach Nodes:** If Stack is checked above, then you need a “top” and a “bottom” node, if Srf Attach is checked above, then you need a “srfAttach” node. Note, node names are case sensitive and having a node is not enough by itself, you do also need the corresponding Attach Rule set true or the node will have no effect. Under Attach Nodes click the + button to add a blank node and configure as needed.

      
       1. **Node ID:** “top”, “bottom”, “srfAttach”, etc. (case sensitive!)
       2. **Node Type:** Select as appropriate. (Stack for Stack, Surface for Surface…)
       3. **Attach Method:** Select Fixed_Joint for Stack and Hinge_Joint for Surface Attach.
       4. **Is Multi Joint:** In general set to True for stack attach to help prevent noodle rockets.
       5. **Multi Joint Max Joint:** *Set to 3 if you set Is Multi Joint to true?*
       6. **Position:** Set as appropriate. Should be on the skin or outside of the part where you would expect to find it on your part in the VAB.
       7. **Orientation:** Set as appropriate. The Orientation vector should be a unit vector (length 1) pointing in the direction of the part that will attach to the node, so pointing away from your part.
       8. **Size:** Affects rigidity of your part. If your part is connected to another part with the same “size” node, then rigidity will be optimal, and otherwise it will be suboptimal.
       9. **Visual Size:** Set the same as Size.
      10. **Is Resource Crossfeed:** Set as needed for this node.
      11. **Is Rigid:** Set as needed for this node.
      12. *Rinse and Repeat:* Subsequent nodes created with the + button will inherit settings from the last node made, so this may accelerate the process as you just need to change the Node Id, Position and Orientation for new nodes that are similar to the previous created node.
2. **Add Module_Color:** You need this to be able to paint your part with base and accent colors. As above, click Add Component and search for Module Color.
3. **Add Module_Drag:** All parts need this. As above, click Add Component and search for Module Color.

## Adding functionality


1. **Add other modules as needed**. For example, if your part is an engine you’ll also need:

   
   1. **thrustTransform object:** Create an empty game object as a child of the root part and name it thrustTransform.
   2. **Throttle VFX Manager:** Configure as needed (?). No need to drag anywhere, it just needs to be a component for the part.
   3. **Flameout VFX Data:** Drag this up to the Flameout VFX property in Module_Engine.
   4. **Module_Gimbal:** Configure details as needed (e.g., Gimbal Range and Gimbal Speed, etc.), then drag this up to the Gimbal property in Module_Engine.
   5. **Module_Generator:** Configure details as needed, then drag this up to the Alternator property in Module_Engine.
   6. **Module_Fairing:** Unless you plan for your engine to only ever be on the very first stage (i.e., a big booster), then you probably want it to have a fairing so it can be used in the second stage and above. Figure 3 shows an example for a working fairing from a Size Small (1.25m-class) engine that was created using this process. Shown below is the corresponding example of the PartComponentModule_Fairing portion of the part JSON. As can be seen in Figure 3, the data fields that need to be populated in the Unity Editor include only a subset of what's in the auto-generated JSON. That said, everything the editor needs is in the example below and presenting it this way makes copy/paste possible where unity editor graphic would not allow that.

      ```json
      {
          "Name": "PartComponentModule_Fairing",
          "ComponentType": "KSP.Sim.impl.PartComponentModule_Fairing, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
          "BehaviourType": "KSP.Modules.Module_Fairing, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
          "ModuleData": [
            {
              "Name": "Data_Fairing",
              "ModuleType": "KSP.Modules.Module_Fairing, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
              "DataType": "KSP.Modules.Data_Fairing, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
              "Data": null,
              "DataObject": {
                "$type": "KSP.Modules.Data_Fairing, Assembly-CSharp",
                "FairingEnabled": {
                  "ContextKey": "FairingEnabled",
                  "storedValue": true
                },
                "FairingConstructionType": {
                  "ContextKey": "FairingConstructionType",
                  "storedValue": "CUSTOM"
                },
                "FloatingNodeEnabled": {
                  "ContextKey": "FloatingNodeEnabled",
                  "storedValue": true
                },
                "Length": {
                  "ContextKey": "Length",
                  "storedValue": -1.0
                },
                "DeployType": {
                  "ContextKey": "DeployType",
                  "storedValue": "Clamshellx4"
                },
                "EjectionForce": {
                  "ContextKey": "EjectionForce",
                  "storedValue": 100.0
                },
                "IsStagingEnabled": {
                  "ContextKey": "IsStagingEnabled",
                  "storedValue": true
                },
                "IsDeployed": {
                  "ContextKey": "IsDeployed",
                  "storedValue": false
                },
                "FloatingNodeSize": 1.0,
                "FloatingAttachNodeTag": "bottom",
                "FloatingNodePosition": {
                  "x": 0.0,
                  "y": 0.0,
                  "z": 0.0
                },
                "FloatingNodeDirection": {
                  "x": 0.0,
                  "y": -1.0,
                  "z": 0.0
                },
                "FloatingNodeIsMultiJoint": false,
                "FloatingNodeMultiJointMaxCount": 3,
                "FloatingNodeMultiJointOffset": 1.0,
                "FairingNode": "top",
                "NoseTip": 0.5,
                "EdgeWarp": 0.02,
                "AberrantNormalLimit": 45.0,
                "LocalUpAxis": {
                  "x": 0.0,
                  "y": -1.0,
                  "z": 0.0
                },
                "Pivot": {
                  "x": 0.0,
                  "y": 0.0,
                  "z": 0.0
                },
                "BaseModelTransformName": "Base",
                "CapRadius": 0.375,
                "BaseRadius": 0.625,
                "CloseRadius": 0.375,
                "MaxRadius": 6.0,
                "SnapThreshold": 0.25,
                "CreateShellColliders": false,
                "NumberOfCollidersPerCrossSection": 12,
                "MinHeightRadiusRatio": 0.07,
                "CrossSectionHeightMin": 0.3,
                "CrossSectionHeightMax": 1.1,
                "AerodynamicallyShieldContents": false,
                "ConeSweepRays": 120,
                "ConeSweepPrecision": 10.0,
                "AmountOfCollidersPerArc": 1,
                "ShouldCapOnAutoGenerate": false,
                "IsCapped": false,
                "IsShroud": true,
                "MassAreaRatio": 0.0,
                "FairingSideCount": 24,
                "FairingLengthSnapIncrement": 0.125,
                "FairingRadiusSnapIncrement": 0.125,
                "FairingSmoothingAngle": 35.0,
                "FairingThickness": 0.025,
                "FairingStartHeight": 0.0,
                "AllowConstructionTypeChange": true,
                "AllowFloatingNodeChange": true,
                "DefaultFairingEnabledToggle": true,
                "DefaultAutoConstruction": true,
                "DefaultDeployType": "Shroud",
                "DefaultFloatingNodeState": true,
                "LengthEditMinimum": 0.0,
                "LengthEditMaximum": 0.001,
                "LengthEditDefault": 1.0,
                "StageToggleDefault": false,
                "MaxAutoFairingTargetRadius": -1,
                "MinAutoFairingTargetRadius": -1,
                "CrossSections": [],
                "MassModifierAmount": 0.0,
                "DragCubeIndex": -1,
                "ModuleType": "KSP.Modules.Module_Fairing, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
                "MassModifier": 0.0,
                "DataType": "KSP.Modules.Data_Fairing, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
                "IsActiveInStagingProp": {
                  "ContextKey": null,
                  "storedValue": false
                }
              }
            }
          ]
      }
      ```

      ![](https://docs.ksp2redux.org/api/files.get?sig=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1cGxvYWRzL2U4YmY4MDA3LWI4OWMtNDJiNy04MzRkLWUwZGQ5NjM2NGM2MC80OTBmZWRhMy05N2Y3LTRjODItYWNkMS1iYWQ5MWU0MDM1M2MvaW1hZ2UucG5nIiwidHlwZSI6ImF0dGFjaG1lbnQiLCJpYXQiOjE3OTM1MDkyMDAsImV4cCI6MTc5MzU5NTYwMH0.0pszLTUZMXvOJHxMoesFsMPugMTsPAoCnnm-ON7Z-nk " =214x384")

      Of the information show above, the parts you will most likely need to customize for your fairing are Base Radius, Cross Section Height Max, and Fairing Thickness - the rest is likely to be the same for all your engines with one other important thing to note. The example above is for an engine that was made in Blender with the nozzle bell facing upwards. If your engine was made with the nozzle bell facing down, then you will need the **Local Up Axis** to be -1 in Y and you will also need set the **Fairing Node** to bottom.

## Final steps


 1. **Apply Options:** Select the root part and in the Inspector window near the top on the **Prefab** line, click the **Overrides** dropdown and pick **Apply All**. If this option is not available, then you’ve got nothing you need to do here. Move along, move along.
 2. **Save Part JSON:** Click **Save Part JSON** button at the bottom of the **Core Part Data** module. This will put the resulting part JSON in the `Assets` folder for your Unity project. You need to do this any time you’ve edited the **Core Part Data** module (or also a module it depends on?).
 3. **Make Prefab:** Grab the root part object and drag it to your mod’s folder within `Assets`.
 4. **Add Part Icon:** Create an icon for your part that the game will use in the parts picker. This needs to be a PNG file with specific dimensions. It should conform to the style used by other parts in the game. However you do this, you need to name the file `<part_name>_icon.png`, and you need to drag that file into the `Assets` folder in Unity. More here: [Creating a part icon](/doc/1f1d6e9f-3c00-4c5a-80c7-e9f1a33e6370)
    * **Convert Icon to Sprite:** Select the part icon in the Assets folder. In the Inspector window, click the pulldown menu for Texture Type and change this from Default to Sprite (2D and UI), then click **Apply**. If this is not done, your lovely icon will not display!
 5. **Make Prefab Addressable:** Select the part’s prefab in the `Assets` folder and in the **Inspector** window check the box for **Addressable**.
 6. **Make JSON Addressable:** Select the part’s JSON in the `Assets` folder and in the **Inspector** window check the box for **Addressable**.
 7. **Make the Icon Addressable:** Select the part’s icon in the `Assets` folder and in the **Inspector** window check the box for **Addressable**.
 8. **Configure Addressable Properties:** In the **Addressables Groups** (**Window → Asset Management → Addressables → Groups**) expand your mod's Group and find your part.
    * **Group Name \\ Addressable Name:** Change the information in the **Group Name** \\ **Addressable Name** from `Assets/<part_name>*` to be just `<part_name>*`. So `Assets/<part_name>.prefab` becomes `<part_name>.prefab`, and so forth. You can leave the `Assets/` part of the path definition alone for each of these, that’s as it should be. The value for the **Addressable Name** needs to be the same as the file name it’s associated with and must not include any path parts. All of these need to be based on the **Part Name** established in the **Core Part Data** module.
    * **Labels:** For the JSON set this to `parts_data`. Leave it blank for the prefab. If `parts_data` is not an option in the dropdown for Labels, then click **Manage Labels**, click the + button to add a new label, and set the **Label Name** to `parts_data`. Click **Save**.
    * **Features (optional):** If the part belongs to one of the [features](/doc/campaign-features-9YIewcIArR) of your mod and not to the full mod, set that feature in the **Features** section of the **Core Part Data** module. This section adds the feature labels to the JSON.
 9. **Build Mod or Build And Test:** In the **Modding → Redux SDK** menu, check your mod’s checkbox and select either **Test Selected Mods In Editor**, or **Build and Test** to have the SDK prepare and deploy your parts pack mod.
10. **Launch Game and Test!** Your mod is off in campaigns until you turn it on. To turn it on, do one of these steps:
    * Before you start a new campaign, select the mod in the **Mods** menu and mark it under **Default Features**.
    * On the new campaign menu, turn the mod on with **Edit Pack**.
11. ***Rinse and Repeat for Additional Parts***