-1

Many times I find myself in the need of checking which type of componenent am I handling to make the corresponding operations.

For example:

bool isFooAType = someGameObject.GetComponent<FooA>() != null;
bool isFooBType = someGameObject.GetComponent<FooB>() != null;

if (isFooAType) {
    FooA myFooA = someGameObject.GetComponent<FooA>();
    //FooA Operations....

}
if (isFooBType) {
    FooA myFooB = someGameObject.GetComponent<FooB>();
    //FooB Operations....

}

Is there a more condensed or more elegant way to determine the flow of execution depending on the component type to handle the corresponding operations and even maybe avoid doing GetComponent twice (one to check if its null + get again to operate the component in the code successively)?

rustyBucketBay
  • 4,320
  • 3
  • 17
  • 47
  • What are the operations? Could you perhaps use an interface? – ProgrammingLlama Jun 24 '21 at 07:00
  • 4
    You could use [`TryGetComponent`](https://docs.unity3d.com/ScriptReference/GameObject.TryGetComponent.html) – Ackdari Jun 24 '21 at 07:01
  • oh my god, that was kind of what I was looking for, thanks a lot – rustyBucketBay Jun 24 '21 at 07:04
  • the question in inspired in how nullchecks can be done in [Javascript](https://stackoverflow.com/questions/6003884/how-do-i-check-for-null-values-in-javascript) – rustyBucketBay Jun 24 '21 at 07:06
  • 1
    You called the function twice, once to get the `isFooAType` and a second one inside the `if (isFooAType)`. That was a problem. You should either use the function Ackdari commented or something like: `FooA compA = someGameObject.GetComponent();` and then `bool isFooAType = (compA != null);` – Cleptus Jun 24 '21 at 07:10
  • thanks @Cleptus, yes I was aware of that option. Like that you can avoid the double `GetComponent` but still need to check twice. `TryGetComponent` is what I was after, as both check can be done at once, moreover you avoid memory allocation in the editor, as explained [here](https://www.jiadongchen.com/2020/05/using-trygetcomponent-instead-of-getcomponent-to-avoid-memory-allocation-in-the-editor/). – rustyBucketBay Jun 24 '21 at 07:15
  • note that for `TryGetComponent` to be available, needs to be available in the updated API in the Unity 2019.2 version – rustyBucketBay Jun 24 '21 at 07:16

1 Answers1

2

As mentioned there is TryGetComponent so you do simply

if (someGameObject.TryGetComponent<FooA>(out var fooA)) 
{
    fooA.DoSomething();
}
if (someGameObject.TryGetComponent<FooB>(out var fooB)) 
{
    fooB.DoSomehtingElse();
}

If this is not available (and only then) e.g. due to older Unity versions rather still make the call ONCE and do

var fooA = someGameObject.GetComponent<FooA>();
var fooB = someGameObject.GetComponent<FooB>();

if (fooA) 
{
    fooA.DoSomething();
}
if (fooB) 
{
    fooB.DoSomehtingElse();
}

In general you might want both to be exclusive by using else if.

And in particular if both are basically implementing the same method you would rather use a common base class or interface and have only one single TryGetComponent or GetComponent call.

derHugo
  • 83,094
  • 9
  • 75
  • 115
  • I am wondering if the `if` avaluates regarding `null` or regarding the type's [default value](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/default-values). I will check that out. Thanks for any comments and for the answer. – rustyBucketBay Jun 24 '21 at 07:57
  • @rustyBucketBay oh you can easily look this up in the source code for [`==`](https://github.com/Unity-Technologies/UnityCsReference/blob/61f92bd79ae862c4465d35270f9d1d57befd1761/Runtime/Export/Scripting/UnityEngineObject.bindings.cs#L390) and [`implicit bool operator`](https://github.com/Unity-Technologies/UnityCsReference/blob/61f92bd79ae862c4465d35270f9d1d57befd1761/Runtime/Export/Scripting/UnityEngineObject.bindings.cs#L98) ;) -> for comparing against actual `null` they cast to `System.Object` and use `== null` on that – derHugo Jun 24 '21 at 08:01