You can actually do one better. If it's the
Test2 component you care about, then make that the type of the inspector variable you expose:
private int bye = 1;
public Test2 playerTestScript;
playerTestScript.hello *= bye;
This way you have absolutely no searching to do at runtime. Everything is wired-up in the inspector, and the type information lets the editor enforce valid references.
(In the example in the question, if the
player GameObject existed but did not have a
Test2 component attached, the editor would still let you assign the reference but you'd get a
NullReferenceException at runtime when you try to access the
Test2 instance that isn't there. Also, since the type is shown in the field, this advertises to someone unfamiliar with the script exactly what kinds of inputs it needs, making wiring it up less error-prone.)
Overall, I would strongly recommend against looking up GameObjects by name whenever it can be avoided. It's brittle if you ever want to re-use the script in a different context, or want to have two instances referencing different objects, and generally makes it very easy to accidentally introduce bugs when renaming, or changing from objects loaded with the scene to those spawned at runtime (which have their name altered when
Instantiate()d), or dealing with
Destroy()ed objects (which still get found by name until the next frame).
Wiring up a reference in the inspector is a bit of work, but no more work than naming an object a very specific string, and unlike the named approach what you need to do is advertised in the inspector fields, rather than hiding in the code.
Lastly, if the component you need to reference will be living on the same object, there's another pattern I like to use:
public class DependentComponent : MonoBehaviour
_prerequisite = GetComponent<PrerequisiteComponent>();
(This is great to use with Renderers, Colliders, Rigidbodies, etc. for scripts that need them)
This is the one case where I prefer a script to wire-up itself: when it can unambiguously identify the component it needs (because it's on the same object) and the
[RequireComponent()] attribute lets the editor enforce this prerequisite for us, so the level designer doesn't have to remember it.