The implementation of printf in some shells (bash, ksh, zsh, at least; even in sh emulation mode) understands \xHH as the hexadecimal number HH. This is however an extension to the standard printf specification.
What's required by the POSIX standard is that printf recognize \ooo, where ooo is a one, two, or three digit octal number in the format argument and \0ooo in arguments meant for the %b format directive (to match echo behaviour).
The shell that stands in for /bin/sh on your system is most likely dash (or, less likely, yash), which understands octal (like all standard shells), but does not understand hexadecimal, when used with printf.
The hexadecimal number 30 is 60 in octal, so
$ sh -c 'printf "%b\n" "$1"' sh '\060'
0
Or, if you don't want to pass the octal number as an argument but instead want to use it as a static literal:
$ sh -c 'printf "\60\n"'
0
(Note the difference here to the sh -c statement in your question: the whole printf statement, including its arguments, are part of the string given as the option-argument to the sh utility's -c option. I'm assuming what you have in your question is a simple typo.)
The reason your script managed to print a 0 character correctly is either because you had a #!-line in the script that pointed to the bash shell executable, or you had no such line at all and instead ran the script from an interactive bash shell. The bash shell, when executing a shell script with no #! line, will use bash to run it (see Which shell interpreter runs a script with no shebang? for more about this detail).
When you run the script with an explicit interpreter, as in sh myScript.sh, the #! line, if there is one, will be ignored.
\060sh myScript.sh, then you have explicitly told sh (i.e. dash) to execute the text of your script itself. The shebang (because it starts with#) is just a comment in that case. The#!is a "magic number" which is only actioned when the file containing it is executed via the execve() system call.