Erlang was at one point the only way to get this sort of structure, though.
Now it isn't. Multiple languages like Go have lightweight coroutine-y type things; if the isolation isn't perfect, you can fix it with programming discipline. There's also Pony, and Rust which has its own thing which is in its own way far stronger than what Erlang offers. Async/await languages are very amenable to setting up lots of little process-like things, to the point that arguably it's the only sane way to structure your programs in such languages. There is a real change in Erlang being almost the only thing on offer, to merely being one choice of a whole bunch and no longer being impressive enough to justify the lockin. (Not that Erlang uniquely has lock in; all languages have lock simply by virtue of the fact that once code is written in X you can't just change it to Y one day. But it's not worth the lock in anymore.)
It still is though! Isolated processes with asynchronous, dynamic message passing requires really heavy libraries in most other languages. Rust is completely different, I can't fathom why you'd compare them in this way.
Message buses solve the message passing requirement. You can get a whole range of solutions from "just sling vaguely JSON stuff around" to "here's a whole strongly typed protocol", with a whole array of options on persistence, clustering, language support, etc., a whole array of options around how synchronous they are and what guarantees they provide, rather than Erlang's one exact solution,
You're kind of demonstrating my exact point here... it isn't that the exact Erlang solution shows up in other languages, the point is that the problem space that Erlang covers is now covered in plenty of other languages, in all sorts of ways, many of them better for some task than Erlang's one point in the space that was selected very, very early in the exploration process. This was not the case 20 years ago. It is now. And I don't particularly think Erlang's coverings of the problem space are the best. People not already deep into Erlang aren't evaluating whether or not some solution is exactly like Erlang, they're evaluating whether the solution is a good solution on its own terms, and once you remove the "must be exactly like Erlang" clause there are a lot of better choices for every element of Erlang, except arguably, the integration of all of them together.
You can write distributed coroutines in assembly with enough programming discipline. What is interesting in a language is not what it lets you do, it's what it prevents you from doing.
On one level yes, they have constructs that you can use to accomplish some of the same goals as the tools Erlang provides, but some people (me) like the specific programming model that Erlang provides for dealing with these problems. The concurrency characteristics of the systems I hack on every day would be much harder to model without GenServers. It's not particularly surprising that Erlang is not the only way to solve a problem in software engineering, there is no silver bullet.
I've written much more C# than I have Elixir in my time as a developer and the fact remains that I prefer functional programming and I like using OTP. I don't see what the "wide variety of other things that are superior" are in languages that aren't Erlang. The ecosystem is stronger and the tooling is better, but those are not intrinsic to the design of the language. Tooling kind of is, with static languages, I suppose. Lack of static types are the one thing that bother me a lot about Elixir.