I'd recommend using the public setter over local setting of the variable, simply because there'll be one place - the setter - where all the logic related to validation is handled. But this is only effective if you follow this convention every where within the class and all the derived versions strictly.
One cannot assume that a member variable is not manipulated elsewhere in the class ( or its derived versions, if it is protected). Imagine another programmer debugging an error related to username validation. It can be a pleasant surprise to find out upon search, that all validations take place via the setter - so she doesn't haven't to debug multiple validation logic.