The short answer is that it's all about type safety, and how we navigate type guarantees.
Casting like this:
will throw an error if the value returned from the method isn't convertible to the
But using the
SomeMethodThatReturnsAMoreGeneralType() as TypeIWant
will instead populate the value with
null if the conversion fails. So if there's a legitimate reason you might get a different return type for your particular application, using
as lets you detect and handle that case gracefully, without throwing errors and
There's no significant performance difference between the two in modern C#, so the main function here is to clearly show your intent and trap errors where you want them. If your game absolutely expects
TypeIWant here, then use a cast. If that assumption is ever violated, you'll get the error immediately and can go investigate right at the source.
On the other hand,
as shows that you knowingly expect the type to sometimes be something else, and that this is not immediate cause for concern. It will be the job of the subsequent code to check for nulls where there shouldn't be nulls and fire a corresponding error if they need to.
The last case is due to the fact that even if we write
GameObject.Instantiate, it's still calling
UnityEngine.Object.Instantiate, which is made for cloning anything that derives from
UnityEngine.Object - that means it can't guarantee you're going to get a
GameObject out at the end.
GameObject.Instantiate(GetComponent<Renderer>().sharedMaterial) is also valid syntactically, returning a Material. So we need a cast or
as to convert the return value to a
GameObject before we can store it in a variable with type
Of course you could also skip the cast entirely, and use the generic form or Instantiate/Load if you know in advance what type you want. That way a mismatch is a compile-time error, rather than a runtime error, and can often be faster to catch & correct:
TypeIWant myThing = Instantiate<TypeIWant>(Resources.Load<TypeIWant>(path));
Wherever possible, I like to type my variables according to the most specific type I need from them. So rather than storing a bullet prefab as a GameObject or Transform, I'll give it a
Projectile component and expose a slot for it like:
public Projectile bulletPrefab;
Then I can instantiate it with:
var bullet = Instantiate<Projectile>(bulletPrefab);
Now I have strong type guarantees throughout, without casts, and the Inspector will enforce that whatever I assign to
bulletPrefab has the required component. (Don't worry, Instantiate will still clone the whole prefab, game object, other scripts, child hierarchy, and all - not just a floating Projectile component)