You essentially have two lines with the equations:
\$a(t)=a_0 + t*v_a\$
\$b(t)=b_0 + t*v_b\$
where \$a_0, b_0, v_a, v_b\$ are vectors with the same dimension and unit (meters for \$a_0\$ and \$b_0\$ and meters per second for \$v_a\$ and \$v_b\$).
\$a(t)\$ and \$b(t)\$ are the positions of your objects at time \$t\$ (in seconds if using the units above).
Distance over time is calculated by subtracting the positions and taking the length of the vector:
\$d(t)=\left|a(t)-b(t)\right|=\left|a_0-b_0+t*(v_a-v_b)\right|\$
This has to be differentiated to get the closing speed (The multiplication used is the dot-product):
\$c(t)=d'(t)=\frac{(v_a-v_b)*((v_a-vb)*t+a_0-b_0)}{\left|(v_a-v_b)*t+a_0-b_0\right|}\$
The value of \$c(t)\$ is a scalar.
You probably want the closing speed at t = 0 (i.e. now), so it can be simplified further:
\$c(0)=d'(0)=\frac{(v_a-v_b)*(a_0-b_0)}{\left|a_0-b_0\right|}\$
Unit of the result is the same as the components of the original velocity vectors. It is negative if the objects get closer to each other and positive if the distance increases. If you want it the other way around you have to multiply by -1.
\$current closing speed=-c(0)=-\frac{(v_a-v_b)*(a_0-b_0)}{\left|a_0-b_0\right|}\$
Note that this works for all dimensions.
Every matrix-/vector-math library will support all of the necessary operations.
Depending on its design this can be written as a single line of code.
However you may prefer to store \$a_0 - b_0\$ in a temporary variable.
In Pseudocode this may look like this
val tmp = a.position - b.position
return -((a.velocity - b.velocity).dot(tmp)/tmp.length)