Yes: to avoid having to escape special characters. Lazy programmers will just drop what the user types, straight into the code somewhere and this is what leads to injection attacks.
Even if it's not used maliciously, allowing the user to type characters that will conflict somewhere else can be more hassle than necessary. For example, if you decide to create a filesystem directory per user, to store their uploads in, then the username must conform to directory naming rules on that OS (e.g. no \/:*?"<>| on Windows).
Once you've avoided clashes like the directory naming one, and stripped out "';% and // to avoid injection attacks, you have removed most punctuation, and "why does someone even need punctuation in their user name"?
It was far easier to write a quick regex to validate usernames against [a-zA-Z0-9_] and be done with it, than faff about with figuring out all the possible punctuation that will not clash, or mapping them to other characters in some way.
Then, like many things in computing, as soon as enough people start having just letters, numbers and underscores for usernames, and people start making usernames to that spec, it became the de facto standard and self perpetuates!