So the shader you have has two passes, the depth only pass and the regular transparent color pass. The order is important in that the depth only pass must render before the color pass for the effect to work as the depth buffer needs to have the object there to reject the “hidden” transparent parts.
This gets a little weird with multiple objects & materials. In some situations Unity will render both passes of a single object before rendering the next object. Sometimes if two objects use the exact same material it’ll render the first pass of both objects, then the second pass of both objects. If it did that, it’d produce the effect you want. But in this case you’re using transparent objects, skinned meshes, and separate materials, all of which tend to make Unity use the “both passes one object at a time” path instead of the “one pass at a time for all objects” path.
So to do what you want you’ll actually have to force Unity to render the passes in the order you want. There’s a few ways to do this.
You can merge all of the meshes into one mesh & one material. Not really easy to do with skinned meshes if you want things to be flexible, or if you want to be able to adjust material properties per object, but it does solve the problem by removing the issue entirely.
You can split up the multi-pass shader into two shaders & materials, one that only does the depth write and one that is the regular transparent color. Actually, you’ll have to do this for all of the next handful of ways to fix it as it comes down to how you implement rendering.
If your meshes will each always only ever have one material, you can assign both materials to the same renderer and set the depth only material to an lower queue than the transparent material. You’ll get a warning in the inspector about this, but you can ignore that. It’s just saying you’re rendering the object twice … which is what you want. If you need to support meshes that may have multiple materials, you can’t do this as there’s a bug that any index over the mesh’s material count only ever re-renders the part of the mesh the first material uses.
So, if you do need multiple materials, or you want a little more control, you need to use separate renderer components & game objects. At that point you can use the materials’ render queue like before, or you can get a little more control and make use of sorting groups and renderer components’ sorting order. The sorting order isn’t exposed to the inspector for mesh and skinned mesh renderer components, but it’s assignable via script. Just be aware you have to assign it manually via script on awake / start as it won’t be saved on the renderer component. But you can set all of the ghost objects to be a child of a gameobject with a SortingGroup component and then make sure the depth only game objects have a lower sorting order set than the color game objects. Useful if you only want ghosts in a small area to sort like this, but still allow other transparent objects to sort behind & in front. Less useful if your ghosts are going to be spread out everywhere.
One thing to be mindful of for any of the above options is other transparent effects can be affected by the depth pass too. If a transparent effect renders after a depth only pass, it too can be occluded by it. This means you may have to have your ghosts always render on top of all transparency, or under it, all the time.
Which brings me to one last option. You could render a custom depth pass of only the ghosts using a replacement shader or command buffers, and then sample the resulting depth texture in the ghost shader to reject hidden fragments. The benefit of this approach is you can sort with other transparent effects better, and without the need to worry about all of the above multi-object setup.