Quickstart - a practical UnityMol tutorial

Table of Contents

1. Introduction

UnityMol is a molecular viewer that can be used in a standard desktop context or in a Virtual Reality (VR) context. For now, there are separate executables for the VR version and for the desktop version, but the same, identical code base is used.

UnityMol is also a molecular visualization platform to prototype and develop new molecular representations and custom interaction metaphores. It is developed mainly in C# in the Unity game engine.

Currently supported molecular input file formats are:

  • PDB/mmCIF/GRO/Mol2/XYZ/SDF (structures)
  • XTC for trajectory files
  • OpenDX for potential maps

This tutorial gives a short introduction to UnityMol 1.1.2 in the form of a simplified documentation / tutorial.

Full Image Full Image Full Image Full Image Full Image Full Image Full Image Full Image Full Image Full Image


2. Interface

UnityMol is currently based on a single main menu window with retractable sub-menus:

Full Image

The top right button with an arrow hides the whole menu.

2.1. Loaded molecule buttons

When loading a molecule, several selections and representations will be created by default (if the showDefaultRep flag is set to on for the load and fetch API functions in the source code):

Full Image

Each loaded molecule will have this overall line above the selections: Full Image

Use the left down arrow to hide all the selection buttons for this molecule.

  • The 1st button (G) is to define groups for moving them together in VR
  • The 2nd button (H) calls a tool to add hydrogens to the molecule. Currently we use Reduce. This can be slow. The recommended option is to manage the PDB file outside of UnityMol
  • The 3rd button (eye symbol) hides or shows every representation of the corresponding molecule, acting as a toggle
  • The 4th button (X) is to delete/unload the molecule

2.2. Selection / Representation buttons

Each selection button can be unfolded to show two input fields:

  • The first one is the name of the selection
  • The second one can be used to enter a selection query using the selection language (see section)

The (+) button allows to add representations to the corresponding selection. The (x) button deletes the selection and all the representations of this selection.

You can set or unset the current selection by clicking on the selection button, which will make the button darker and will show an orange outline around the atoms of the selection. ⚠️ Note that this outline is not updated when reading a trajectory, for now, essentially for performance reasons.

2.3. Representations

First, the eye toggle button hides/shows the corresponding representation. You can delete a representation using the (x) button.

Note: if you modify the selection, you have to click on the eye button to update the representation

By clicking on the representation's label, the menu unfolds and you can tweak the different parameters of the representation :

Full Image

Here is a list of representations available in UnityMol:

  • "hb": HyperBalls (licorice/ball&stick/VDW/smooth)
  • "bondorder": bondorder (based on HyperBalls, uses bond order information to display double/triple bonds on proteins or for XML custom bonds)
  • "c": cartoon (works for protein and DNA; implementation for the coarse-grained Martini force field for proteins is still a work in progress 🚧)
  • "s": surface (EDTSurf and MSMS available, QuickSES is a WIP 🚧)
  • "dxiso": iso-surface (based on an opendx map)
  • "sphere": sphere (mesh based, slower than HyperBalls)
  • "l": lines (higher quality, when the number of atoms is < 10'000)
  • "hbond": hydrogen-bonds (an animated dotted line, computed based on Schrodinger's distance/angle thresholds: distance(H-Acceptor) = 2.8A / angle(Don-H-Acc) = 120 / angle(H-Acc-B) = 90)
  • "hbondtubes": hydrogen-bonds shown as tubes (still tube meshes between atoms, same computation as for hbond)
  • "fl": fieldlines (based on an opendx map and its gradient)
  • "trace": trace (alpha carbon trace)
  • "sugarribbons": sugar representation (WIP 🚧)
  • "sheherasade": Sheherasade representation (WIP 🚧, based on the PhD thesis work of Loic Nolin)
  • "ellipsoid": ellipsoid (using slower HyperBalls shader)
  • "p": points (fast 2D representation; WIP for Apple Silicon/Metal platform 🚧)

3. Python console 🐍

To make the python console appear (or disappear), you have to use the CTRL + <space bar> key combo, or use the top right arrow.

To use it, see the dedicated chapter discussing the .

  • Every action done with UI buttons corresponds to a function or a set of functions of APIPython
  • There are a LOT of options and commands that can be accessed via the console but are not possible from the UI

The console is using IronPython, a C# interpreter that compiles Python but also gives you access to C# objects. This means that you can call C# / Unity functions from the console like in: GameObject.Find("Directional Light")

3.1. Getting started

3.1.1. Loading

Let's load a molecule, make some selections, create some representations and modify their properties.

In the console, type :

s = fetch("1bl8")
print(s)

You can also use the PDBID input field of the menu in the Input sub-menu:

Full Image

This action should show you something close to this:

Full Image

3.1.2. Coloring

Now let us change the color of the cartoon representation created on the 1bl8_protein_or_nucleic selection by clicking on the cartoon line to expand the options and clicking on the By chain button:

Full Image

This is equivalent to typing in the console:

colorByChain("1bl8_protein_or_nucleic","c")

You can also color the full representations using the color picker in the menu, which is equivalent to the following command in the console:

colorSelection("1bl8_protein_or_nucleic", "c", Color.red)

UnityMol provides a lot of different color functions that are not always available in the UI:

colorByAtom("selName", "c")
colorByResidue("selName", "c")
colorByChain("selName", "c")
colorByHydrophobicity("selName", "c")
colorBySequence("selName", "c")
colorByCharge("selName", "c")
colorByResidueType("selName", "c")
colorByResidueCharge("selName", "c")
colorByBfactor("selName", "c")

To modify default values for UnityMol colors, you can modify the preset that is loaded when UnityMol starts by customizing a text file. It is located in StreamingAssets/customUnityMolColors.txt. This files overwrites defaultUnityMolColors.txt that are also loaded at start.

The format is: AtomName #HexadecimalColor radius. For example: H #ffffff 1.2 to set Hydrogen atom colors to white.

3.1.3. Adding representations to selections

We can add an "all-atoms" view by assigning the "HyperBalls" representation as follows: click on the (+) button of the 1bl8_protein_or_nucleic selection button and click on Hyperball in the dropdown menu:

Full Image

This is equivalent to the following console command:

showSelection("1bl8_protein_or_nucleic", "hb")

Note: Sometimes the upper part of the representations menu is cut off at the top of the window and the selection is not available. In that case, open other menu items to push the representation line more to the bottom (for instance the Utils sub-menu) 🚧

Let us now color carbon atoms in the hyperball representation in gray:

colorAtomType("1bl8_protein_or_nucleic", "hb", "C", Color.gray)

Show/hide buttons for representations are calling the showSelection("selName", "repType") and hideSelection("selName", "repType") functions. The delete button is calling deleteRepresentationInSelection("selName", "repType") or deleteRepresentationInSelection("selName").

To hide all the representations of a selection you can call the hideSelection("selName") function.

To hide all representations of a structure you can call hideStructureAllRepresentations("structureName"), the opposite command to reveal/show a representation is showStructureAllRepresentations("structureName").

Alternatively, you can hide specific representations in all the selections based on the representation type. For instance, to hide all cartoon representations, do:

hide("c")

3.1.4. Adding hydrogens with Reduce

Let's use the Reduce method to add hydrogens to this molecule by clicking on the "H" button next to the name of our protein. This is equivalent to execute

addHydrogensReduce("1bl8")

If you don't know the name of the molecule, you can use the s variable storing the UnityMolStructure, which we assigned when we loaded the molecule:

addHydrogensReduce(s.name)

We can also use the last loaded molecule by doing:

addHydrogensReduce(last().name)

Any of these three commands should update the representations to this view:

Full Image

Note that the number of atoms in some selections has changed.

3.1.5. Zooming / Center

To zoom on a part of the molecule, you can double click on any one atom of a given residue, if it is displayed. You can also double click the selection button (since UnityMol 1.1.1). From the console, you can do

centerOnSelection("1bl8_water", lerp=True)

You can also click on a selection to make it the "current selection", then click on the Center on Selection button under the View menu.

3.1.6. Translation / Rotation (desktop)

If you work with the desktop version, you can use the mouse left button to rotate all molecules, zoom in/out with the right button, and translate using the middle button.

If several molecules are loaded, you can select a single molecule for rotation by pressing on the R key, while you click the left mouse button for the rotation. To only translate a single molecule, do the equivalent pressing the T key and using the left mouse button click on the molecule to be translated.

3.2. Selection language

3.2.1. Basic selections

Let's select only a part of the molecule and display it as a transparent surface. There are several ways to create selections:

  • duplicate an existing one by clicking on the copy/paste button Full Image, then edit the content of the selection by clicking on the left arrow to expand the selection options and enter 1bl8 and chain A in the selection query part on the right
  • click on the New selection button in the Utils menu, then again edit the selection contents Full Image
  • use the console to directly create the selection by running
select("1bl8 and chain A", "chainA")

Now let's show the newly created selection as a surface. Click on the (+) button and select Surface (MSMS) or enter the following via the console:

showSelection("chainA", "s", SurfMethod.MSMS)

The surface can be displayed as a wireframe or with a transparent material. You can access these functionalities from the graphical user interface by clicking on the surface label to expand the properties sub-menu, then clicking on the Transparent button. You can also achieve this from the console by entering:

setTransparentSurface("chainA")

or

setTransparentSurface("chainA", 0.30)

Let us now color the surface in red:

colorSelection("chainA", "s", Color.red)

or define the color explicitly via RGB values as in colorSelection("chainA", "s", Color(1.0,0.0,0.0,1.0).

Hide the cartoon representation with

hideSelection("1bl8_protein_or_nucleic", "c")

and change the background color with bg_color(Color.black) or bg_color("black") or:

bg_color(Color(0,0,0,1))

You should have something closely resembling this view:

Full Image

3.2.2. Select in range

To select atoms around 5.0 Angstrom of the water molecule of 1BL8, type:

select("not water and within 5.0 resname HOH", "closeToWat")
showSelection("closeToWat", "l")#show this selection as lines

You can now re-use this selection to create new selections:

select("not closeToWat", "AllButCloseToWat")

For a better overview of all the possibilities of the selection language please see , and the MDAnalysis documentation, here.

3.3. Automation

3.3.1. Saving command history

To save the current selections and representations in order to be able to share them or reload the commands, you can click on the Utils -> Save script button. This will save all the commands that were executed, using the UI or the console. Some optimization work can be done to clear unnecessary commands by inspecting and editing this file by hand.

You can also call the corresponding command from the console to save the history of commands:

saveHistoryScript("mypath.py")

You can reload the file containing a list of commands by executing the following function or by clicking on the Load Script button from the same Utils menu.

loadHistoryScript("mypath.py")

3.3.2. Taking pictures/videos

You can take a screenshot by clicking on the Save image button in the View menu. This will create a folder called UnityMolScreenshots on your desktop and save the image there, with a 1080p resolution. You can also use the console command with additional options:

screenshot("mypath.png", 1920, 1080, transparentBG=False)

Videos can be taken via commands as well. To start recording, use:

startVideo("mypath.mp4", 1920, 1080, 60)

and when finished, recording can be stopped with:

stopVideo()

For a more complete example of a script to render an animation, take a look at this script.

Please see for more information.

3.3.3. Scripting

The UnityMol console combined to the Python API provides a way to perform simple actions, but also develop more complicated and convoluted scripts.

For example, let's clean all loaded molecules by doing reset(), then load PDB-ID 3EAM without displaying a representation fetch("3eam", showDefaultRep=False):

reset()
fetch("3eam", showDefaultRep=False)

We are going to create a selection by chain, then color each chain:

s = last() #Get the lastly loaded structure
colors = [Color(1,0,0,1), Color(1, 1, 0, 1), Color(1,1,1,1), Color(0,1,1,1), Color(0,0,1,1)] #Create a list of colors
idC = 0
#Loop over the chains of the molecule:
for c in s.currentModel.chains.Values:
    # Create a selection for the chain:
    sel = select(s.name+" and chain "+c.name, "Chain"+c.name)
    showSelection(sel.name, "c") #Show the selection as a cartoon
    colorSelection(sel.name, "c", colors[min(idC, len(colors)-1)])
    idC+=1

For a complete set of all API commands please read this page !

4. Trajectory / Model Player

UnityMol supports loading XTC trajectories using libxdrfile2. The first time a trajectory is loaded, a binary .offset file is created to store the position of each frame in the file. This allows to "jump" within the file without loading the whole trajectory in memory.

To load a trajectory, press the Load button from the Input menu and set the file filters to Trajectory files, or use the following syntax in the python interpreter:

loadTraj("structureName", "mypathToXTCFile.xtc")

By default, when using the Load button, UnityMol associates the trajectory data with the last loaded molecule.

The following sub-menu should be displayed under the loaded molecule UI row:

Full Image

A similar menu is displayed when a molecule with several models is loaded. There are two ways to load a molecular file with several models. By default, UnityMol parses a PDB/mmCIF/GRO file with the setting modelsAsTraj = True, meaning that the first model is read and only the new positions of the next frames are stored. The second way is to store each model in a distinct UnityMolModel data structure.

UnityMol allows to have models with different numbers of atoms for the same molecule only if the modelsAsTraj flag is set to false.

The smooth button interpolates between 2 frames using a linear interpolation. Cubic interpolation uses 4 frames to interpolate between n-1 to n+2 frames. This feature can be enabled with:

last().xdr.cubicInterpolation = True

The average window button activates averaging all the frames between the current frame n and the n + WindowSize frames.

Note that smoothing and averaging should be fast because it is implemented using the C# Burst compiler, featuring a multi-threaded and SIMD accelerated computation.

5. Effects (desktop)

Currently, UnityMol has 3 effects that you can activate in desktop mode:

5.1. Depth cueing / Fog :

Full Image

Related functions are:

enableDepthCueing()
disableDepthCueing()
setDepthCueingStart(0.5)
setDepthCueingDensity(0.1)

5.2. Depth of field / Bokeh effect:

Full Image

Related functions are:

enableDOF()
disableDOF()
setDOFAperture(0.1)
setDOFFocalLength(0.1)
setDOFFocusDistance(0.1)

Note: when the DOF effect is activated, clicking on a molecule does not trigger a selection, but changes the DOF focus distance.

5.3. Outline:

Full Image

Related functions are:

enableOutline()
disableOutline()
setOutlineThickness(10.0)

6. Aligning 2 proteins

UnityMol uses the CEAlign algorithm from here. It is an algorithm that performs well for low sequence similarity and still remains fast. It only uses alpha carbons to align the second argument (mobile) of the function cealign onto the first argument of the function (target).

As an example, load 2 proteins and display them as cartoon:

s1 = fetch("3eam", showDefaultRep=False)
s2 = fetch("3ei0", showDefaultRep=False)
show("c")
colorSelection(s1.ToSelectionName(), "c", Color.red)
colorSelection(s2.ToSelectionName(), "c", Color.blue)

You should obtain something like this:

Full Image

Clicking on Run CEAlign from the Utils menu applies CEAlign on the 2 lastly loaded molecules. This GUI command is equivalent to

cealign(s1.ToSelectionName(), s2.ToSelectionName())

In the example given above, the result of the alignment is shown below.

Full Image

7. Bounding boxes

You can show the bounding box of the loaded molecule by doing:

showBoundingBox("structureName")

Full Image

It can be hidden again with hideBoundingBox("structureName").

8. Overwriting topology (bonding) information (PSF / TOP / XML)

8.1. PSF

You can load bonding information from a PSF topology file (see NAMD protein structure file example) using the following syntax:

loadPSFTopology("structureName", "mypathToPSFfile.psf")

8.2. TOP

Similarly, you can load a TOP topology file (see Gromacs topology file specifications) to overwrite bonding information and update all representations:

loadTOPTopology("structureName", "mypathToTOPfile.top")

8.3. XML

UnityMol provides another simple way to load covalent and non-covalent bonds information using an XML format:

<Bonds>
  <Bond from="0" to="1" order="2.0" type="covalent"/>
</Bonds>

This example code links the first atom of the loaded molecule in the order of the loaded file to the second one by a double covalent bond.

Possible bond types are: covalent or db_geom, hbond or h-bond or hbond_weak, halogen, ionic, aromatic, hydrophobic, carbonyl.

This information can be manipulated from the Python console:

loadBondsXML("structureName", "pathToXMLFile.xml")
overrideBondsWithXML("structureName")
unloadCustomBonds("structureName", modelId)

8.4. Restoring UnityMol computed topology

After loading a topology from a PSF/TOP/XML file, you can restore the bonds computed by UnityMol at load time by doing:

restoreBonds("structureName")

9. Secondary structure assignation

When loading a protein with load() or fetch(), the default behaviour is to use the secondary structure information from the file and use the DSSP algorithm when there is none. You can force DSSP to be run:

fetch("1kx2", forceDSSP=True)

You can run DSSP on a loaded molecule by doing:

switchSSAssignmentMethod("structureName", forceDSSP=True)

10. Annotations

There are several types of annotation in UnityMol to add labels, objects, lines and measurements to atoms. To add a transparent sphere around an atom:

annotateAtom("structureName", atomId)

To add a transparent sphere not attached to an atom, use

annotateSphere(worldP=Vector3(0,0,0), scale=1.0)

You can also add some label to an atom:

annotateAtomText("structureName", atomId, "My text")

or not attached to an atom:

annotateWorldText(Vector3(0,0,0), 1.0, "My text", Color.white)

To add text in 2D, you can use

annotate2DText(screenP=Vector2(0.5, 0.5), scale=1.0, text="My text", textCol=Color.white)

where the screen position is defined by (0,0) = bottom-left and (1,1) = top-right.

To add a line:

annotateLine("structureName", atomId, "structureName2", atomId2)

and not attached to an atom:

annotateWorldLine(Vector3(0,0,0), Vector3(3,0,0), 1.0, Color.white)

11. Measurements

Measurements are using annotations to display lines and text on atoms. To make such measurements in desktop mode:

  • press M and click on atoms to compute a distance/angle/torsion angle based on the setting of UnityMolMain.measureMode
  • Clicking on the Measurement mode button in the Utils menu cycles through the modes
  • The button calls the setMeasureMode() function to change UnityMolMain.measureMode. The command syntax is setMeasureMode(mode) where mode is
    • 0 = distance,
    • 1 = angle,
    • 2 = torsion angle

In VR, pressing the touchpad button while aiming the target atom should trigger measurements.

You can also play a sonar sound at a position in the scene to localize an atom or an object. Achieve this using the playSoundAtPosition(Vector3(10,0,0)) command.

12. Interactive Molecular Dynamics (IMD)

Connection to a running simulation using the IMD protocol is established via the IMD menu. You can also call the corresponding function from the console:

connectIMD("structureName", "127.0.0.1", 8888)

for a simulation running on the localhost on the 8888 port. Disconnection using the console:

disconnectIMD("structureName")

By default, UnityMol uses the last loaded molecule when clicking on the IMD connect button.

During IMD, you can grab an atom or several atoms by click & dragging the mouse in desktop or the controller in VR.

The IMD protocol is implemented using MDDriver since UnityMol 1.1.2.

13. Docking mode

The UnityMol team collaborated with the Levitt lab at Stanford University to build an interactive docking mode in UnityMol, available in VR. It uses the AMBER forcefield to interactively compute the potential energy of the system. For more information please read .

14. Export to OBJ/FBX

One can export the current representations of a structure using one of these functions:

exportRepsToOBJFile("structureName", "outputpath.obj")

or

exportRepsToFBXFile("structureName", "outputpath.fbx")
  • Note that this implementatiom currently ignores point, hbond and bond-order representations
  • For HyperBalls representations, a custom algorithm extracts a mesh based on current hyperballs parameters, this approach can lead to a mesh that is slightly different from the actual representations in UnityMol. It also produces large meshes.

The file in FBX format is a binary file that is lighter than the OBJ text file format.

15. Startup commands or Command Line Interface

UnityMol has a command line interface with a few supported arguments:

  • -d <directoryPath>: change the current directory to the one in <directoryPath>.
  • -i <filename1> [<filename2>,...]: load one or several files supported by UnityMol.
  • -v or --version: print the UnityMol version.
  • -r or --remoteControl: Start Unitymol with a TCP Server listening to receiving external commands.
  • -c or --commons: Load automatically the python module UnityMolCommons.py found in Streaming Assets.

You can directly load a molecular file or a command file (previously saved from UnityMol or edited as a custom script) when launching UnityMol from a terminal:

./UnityMol -i /path/to/UMolState.py

The above executes the UMolState.py script.

Below an example loading two structures, with trajectory data information for the second one:

./UnityMol -i /path/to/1kx2.pdb /path/to/1bl8.pdb /path/to/1bl8_traj.xtc

To fetch a PDB file from the internet when starting UnityMol you can do:

./UnityMol -i 3eam

You can also set the working directory with the -d flag, to easily load local files with the following syntax:

./UnityMol -d /path/to/folder

16. More information

If you need help or have any question regarding UnityMol and it's usage, please send an email to unitymol at gmail.com. We are also active on Twitter/X as @UnityMol.

Author: Marc Baaden

Created: 2025-12-03 Mer 19:03

Validate