Skip to content

Adding Life to Your World

GrandAdmiralCrunch edited this page Oct 30, 2026 · 1 revision

Adding Life to Your World

This tutorial walks a planet-pack author through giving a custom world (Kopernicus or otherwise) its own ecosystem: a tree of life, a few animated species, a fossil, and optionally a panspermia link to Kerbin. You don't need any C# or 3D art to start: procedural creatures are built and animated by the plugin.

The running example is a made-up planet called Verdan. Swap in your own body's name.

Full key-by-key reference: the Modder's Guide. This page is the guided tour.


1. Plan the tree first

Before writing configs, sketch your world's tree of life on paper. Players reveal it branch by branch, so it is the backbone of the experience.

Protoverdia (Domain)                 the root: everything on Verdan descends from it
├── Hexambulata (Phylum)             six-legged walkers
│   └── Reed Scuttler                a herd grazer
└── Aeronauta (Phylum)               gas-filled sky drifters
    └── Skybell                      a glowing gasbag

Good trees:

  • have 3 to 6 levels. Too flat and there is nothing to reveal; too deep and players never get there.
  • give each branch at least one discoverable species or fossil. A branch with nothing under it can never be revealed (the validator will tell you).
  • tell a story. The era and description of each clade show in the Field Guide once it is named.

2. Where the files go

Put your configs anywhere in your own mod folder. Xenobiology finds them by node type:

GameData/MyPlanetPack/
    Xenobiology/Verdan.cfg                         your XENO_* nodes
    PluginData/Silhouettes/verdan_scuttler.png     field-guide outlines (see step 7)
    PluginData/Portraits/verdan_scuttler.png       optional portraits

If Xenobiology isn't installed, KSP just ignores the unknown nodes, so you can ship them unconditionally. If the body isn't installed, Xenobiology skips that biosphere quietly.

3. The biosphere

One XENO_BIOSPHERE per world says "this body has life".

XENO_BIOSPHERE
{
    name = verdan_biosphere
    body = Verdan                    // the CelestialBody name, as Kopernicus names it
    displayName = Verdanian Biosphere
    rootClade = verdan_protobiota
    spawnDensity = 1                 // 0.5 = sparser, 2 = busier than Kerbin
    description = Verdan's shallow, warm seas gave rise to life about two billion years ago.
}

Set extinct = true for a dead world: nothing spawns alive, but fossils can still be studied (stock Duna works this way).

4. The clades (branches)

Each XENO_CLADE is one branch. parent must be another clade in the same biosphere; the root has no parent.

XENO_CLADE
{
    name = verdan_hexapoda
    parent = verdan_protobiota
    biosphere = verdan_biosphere
    displayName = Hexambulata
    rank = Phylum                    // free text
    era = ~600 million years ago
    revealThreshold = 2              // evidence needed before the branch is named
    color = 0.7,0.6,0.3,1
    description = Six-legged walkers that crawled out of the shallows.
}

How evidence works

A clade's evidence is:

  • +1 for every discovered species anywhere below it;
  • +evidence for every studied fossil type that names it (or a clade below it) in evidenceFor;
  • +1 for each species or fossil type analysed in a lab.

With any evidence the branch shows as "Unknown lineage"; at revealThreshold it is named. Set thresholds so they are reachable but not instant: a branch with two species and one fossil under it might use 2 or 3.

5. The species

Each XENO_LIFEFORM is a species. The essentials are where it lives, how it behaves and what it looks like.

XENO_LIFEFORM
{
    name = verdan_scuttler
    body = Verdan
    clade = verdan_hexapoda
    displayName = Reed Scuttler
    scientificName = Hexapes calamicola
    description = A knee-high grazer that lives in herds along the lakeshores.

    habitat = Ground                 // Ground, Water, Underwater, Air, Flyer
    biomes = Lowlands, Shores        // your body's biome names; spaces and case are ignored
    activeTime = Day                 // Any, Day, Night
    temperament = Skittish           // Skittish, Passive, Curious, Territorial
    groupSize = 3, 8                 // a herd of 3 to 8
    size = 0.8                       // length in metres
    speed = 1.5
    fleeSpeed = 6
    scienceValue = 12
    silhouette = MyPlanetPack/Textures/Silhouettes/verdan_scuttler

    PROCEDURAL
    {
        bodyPlan = Hexapod           // Quadruped, Hexapod, Serpent, Avian, Fish, Floater, Blob
        color = 0.45,0.55,0.3,1
        accentColor = 0.8,0.7,0.35,1
        bodyLength = 1
        legLength = 0.4
        headSize = 0.25
        eyes = 4
    }
}

Choosing a habitat

habitat use for key extras
Ground walkers amphibious, swims, walkOnWater, BURROW {}
Flyer birds and anything that walks, takes off and lands FLIGHT {}, swims for waterfowl
Air things that never land: drifters, kites minAltitude/maxAltitude above ground, circling
Water surface swimmers waterline
Underwater fish, squid, deep-sea life minAltitude/maxAltitude = depth band, seafloor

Gas giants: with no terrain or ocean, minAltitude/maxAltitude are absolute altitudes, and creatures only appear around vessels flying inside that band.

Making it feel alive

Optional blocks add behaviour without code: SLEEP, FLIGHT, ATTACK, ROAR, BURROW, MOUNT (rideable), SOUNDS, EMITTER (spores, bubbles, glowing motes, steam), PLUME, LIGHT (reacts to lamps), LEAP, BURST and more. diet and lifeStageOf add "Feeds on" and larva/adult links to the Field Guide. See the Modder's Guide for each block's keys.

Spawning knobs

  • rarity: weight against other species that could live in the same spot.
  • territoryChance (default 0.6): chance a ~3 km territory holds the species at all. Lower = patchier.
  • The spawnDensity of the biosphere scales the whole world.

6. Fossils

Fossils give players something to find on dead or quiet worlds, and they are how you hint at extinct branches that have no living species.

XENO_FOSSIL
{
    name = verdan_trackway
    body = Verdan
    displayName = Six-toed Trackway
    form = Trackway                  // Shell, Bones, Trackway, Stromatolite, Amber
    kind = Trace fossil
    biomes = Lowlands
    evidenceFor = verdan_hexapoda    // clade and/or panspermia names
    evidence = 1
    age = ~550 million years
    scienceValue = 15
    description = Footprints in rippled mudstone: the earliest walkers on Verdan.
}

A whole extinct branch (a clade with no species) can be revealed by fossils alone.

7. Field Guide images

Every species and fossil should have a silhouette (shown before discovery, and as an outline after).

  • Point silhouette at <YourMod>/Textures/Silhouettes/<name>. The actual PNG lives in <YourMod>/PluginData/Silhouettes/<name>.png, which KSP does not load into memory; the plugin reads it only when the Field Guide needs it.
  • Let the tool draw them for procedural species:
    python GameData/Xenobiology/Tools/xeno_tool.py outlines GameData
    
    Existing files are kept, so you can hand-paint replacements.
  • portrait works the same way (Textures/Portraits/... → PluginData/Portraits/...), shown once the species is discovered.

Never put loose PNGs elsewhere under GameData: KSP loads every one as a texture.

8. Panspermia (optional)

Connect your world to another one. Here Verdan's life is descended from Kerbin's oceans:

XENO_PANSPERMIA
{
    name = verdan_seeding
    displayName = The Long Fall
    sourceClade = kerbin_thalassobiota   // any clade on another world
    targetBiosphere = verdan_biosphere
    mechanism = Impact ejecta (Kerbin to Verdan)
    age = ~2 billion years ago
    revealThreshold = 2
    description = Spray from a great ocean impact on Kerbin crossed the void and fell into Verdan's warm seas.
}

A panspermia event's evidence is +1 when the source clade is named, +1 when the target clade (by default your root) is named, plus any fossils that list the event's name in evidenceFor. Without fossils the most it can reach is 2, so a threshold of 3 needs at least one fossil pointing at it. The validator catches this (it caught it while this page was being written).

To link to stock worlds, browse the trees with xeno_tool.py tree GameData kerbin_biosphere.

9. Validate

python GameData/Xenobiology/Tools/xeno_tool.py validate GameData
python GameData/Xenobiology/Tools/xeno_tool.py tree     GameData verdan_biosphere

The validator checks broken parent/clade/evidenceFor links, clades in the wrong biosphere, thresholds that can never be reached, missing look nodes and more. tree prints the whole tree:

<~~ The Long Fall from clade kerbin_thalassobiota
[Domain] Protoverdia  (reveal 2)
  [Phylum] Aeronauta  (reveal 1)
    - Skybell (Air)
  [Phylum] Hexambulata  (reveal 2)
    - Reed Scuttler (Ground)

10. Test in game

  1. Launch KSP and check KSP.log for lines starting with [Xenobiology]. The database summary says how many of your nodes loaded; skipped or broken ones are listed.
  2. Fly (or cheat) to your world and go on EVA in one of your species' biomes.
  3. Press Alt+F8 for the debug window: it lists config problems, shows which species can live where you are standing, and can spawn any creature or fossil next to you.
  4. Press O near a creature to observe it, and open the Field Guide to watch the tree fill in.

Going further

  • Custom models: replace PROCEDURAL with a MODEL {} block pointing at your own .mu with idle/walk/run/alert clips. Keep the PROCEDURAL block too: it is the fallback if the model fails to load. Follow the polygon budgets and DDS texture rules in the Modder's Guide.
  • Lairs (XENO_LAIR): a fixed cave, nest or reef with resident creatures.
  • Features (XENO_FEATURE): geysers and fumaroles that a species can gather around.
  • Microbiology Expansion: give the biosphere a microbeClade and its microbes become leaves on your tree.
  • Patching stock content: every node can be edited with ModuleManager, e.g. @XENO_LIFEFORM[kerbin_*]:FINAL { @rarity *= 0.5 }.

Complete example

Everything above in one file. It passes the validator as-is.

// GameData/MyPlanetPack/Xenobiology/Verdan.cfg
XENO_BIOSPHERE
{
    name = verdan_biosphere
    body = Verdan
    displayName = Verdanian Biosphere
    rootClade = verdan_protobiota
    spawnDensity = 1
    description = Verdan's shallow, warm seas gave rise to life about two billion years ago.
}

XENO_CLADE
{
    name = verdan_protobiota
    biosphere = verdan_biosphere
    displayName = Protoverdia
    rank = Domain
    era = ~2 billion years ago
    revealThreshold = 2
    color = 0.4,0.7,0.5,1
    description = The common ancestor of everything that lives on Verdan.
}

XENO_CLADE
{
    name = verdan_hexapoda
    parent = verdan_protobiota
    biosphere = verdan_biosphere
    displayName = Hexambulata
    rank = Phylum
    era = ~600 million years ago
    revealThreshold = 2
    color = 0.7,0.6,0.3,1
    description = Six-legged walkers that crawled out of the shallows.
}

XENO_CLADE
{
    name = verdan_aeronauta
    parent = verdan_protobiota
    biosphere = verdan_biosphere
    displayName = Aeronauta
    rank = Phylum
    era = ~400 million years ago
    revealThreshold = 1
    color = 0.5,0.6,0.9,1
    description = Gas-filled drifters that left the sea for the sky.
}

XENO_LIFEFORM
{
    name = verdan_scuttler
    body = Verdan
    clade = verdan_hexapoda
    displayName = Reed Scuttler
    scientificName = Hexapes calamicola
    description = A knee-high grazer that lives in herds along the lakeshores.
    habitat = Ground
    biomes = Lowlands, Shores
    activeTime = Day
    temperament = Skittish
    groupSize = 3, 8
    rarity = 1
    size = 0.8
    speed = 1.5
    fleeSpeed = 6
    scienceValue = 12
    silhouette = MyPlanetPack/Textures/Silhouettes/verdan_scuttler
    PROCEDURAL
    {
        bodyPlan = Hexapod
        color = 0.45,0.55,0.3,1
        accentColor = 0.8,0.7,0.35,1
        bodyLength = 1
        legLength = 0.4
        headSize = 0.25
        eyes = 4
    }
}

XENO_LIFEFORM
{
    name = verdan_skybell
    body = Verdan
    clade = verdan_aeronauta
    displayName = Skybell
    description = A translucent gasbag that drifts over the highlands, glowing faintly at night.
    habitat = Air
    biomes = Highlands, Mountains
    temperament = Passive
    minAltitude = 40
    maxAltitude = 160
    size = 3
    speed = 2
    circling = false
    scienceValue = 20
    silhouette = MyPlanetPack/Textures/Silhouettes/verdan_skybell
    PROCEDURAL
    {
        bodyPlan = Floater
        color = 0.7,0.8,0.95,0.8
        glowColor = 0.3,0.6,1,1
    }
}

XENO_FOSSIL
{
    name = verdan_trackway
    body = Verdan
    displayName = Six-toed Trackway
    form = Trackway
    kind = Trace fossil
    biomes = Lowlands
    evidenceFor = verdan_hexapoda
    evidence = 1
    age = ~550 million years
    scienceValue = 15
    description = Footprints in rippled mudstone: the earliest walkers on Verdan.
}

// Optional: Verdan's life came from Kerbin's oceans
XENO_PANSPERMIA
{
    name = verdan_seeding
    displayName = The Long Fall
    sourceClade = kerbin_thalassobiota
    targetBiosphere = verdan_biosphere
    mechanism = Impact ejecta (Kerbin to Verdan)
    age = ~2 billion years ago
    revealThreshold = 2
    description = Spray from a great ocean impact on Kerbin crossed the void and fell into Verdan's warm seas.
}