Do you have to use GetComponent?

Im a bit confused on how to mimick behavior like transform.

That is i know that if i make a script and i make the integers public and i make the
functions public i can just type

script.function();
or
script.variable = x;

But it seems making a class public doesnt unlock that same functionality (i have to use get component)

I have 2 game objects

torpedoTube
torpedo

torpedo Tube spawns an instance of the prefab torpedo and saves it as a variable
now torpedo prefab has the script torpedoBehavior attached to it in the prefab to ensure
all torpedos come equipped with there behavior scripts.

However i can’t seem to do

MyTorpedo = instantiate(torpedo,…,…);

MyTorpedo.TorpedoBehavior.Fire();

I ahve to use getComponent.

I feel like if the component is there it’s attached it should just be an option to type.

I understand under the hood it would go and find the component. It’s the same thing in the end I get that.

But syntax wise I don’t understand why public variables of public classes can just go
class.variable
but i cant go

gameobject.class

Especially since for common classes (transform)
the behavior already exists.

Is there a way to do this?
Since classes are public be default and thats the only reason i could see for not seeing them i’m not sure.

2 Answers

2

You are misunderstanding what is going on.

GameObject is itself a class. Adding a component to it will not change the definition of the class. The reason you can do GameObject.transform is because transform is defined in GameObject (and actually just wraps a GetComponent call if I recall correctly).

The GameObject class is holding references internally to the instances of classes attached to it and you are accessing them via methods on the GameObject class. You are not altering the GameObject class definition at all.

Imagine a Dictionary. You can do Dictionary.Add(“hello”, null), but this will not allow you to access the string with Dictionary.hello. You can access it via Dictionary[“hello”], but that is using an indexer, which is something different again. The reason (probably) the GameObject class doesn’t implement an indexer is because it would not allow you to add two instances of the same component, and also be slow (strings = bad)

On a side note, I think c# won’t allow you to override the . operator.

+1 Right, however they could have added an indexer that takes a type as parameter. In UntiyScript that would look like this: gameObject[Transform] however in C# it would look quite ugly: gameObject[typeof(Transform)]

But you still wouldn't be able to have two of the same behaviours on one object (although to be fair, that usually does more harm than good...)

Well, it's the exact same behaviour with GetComponent. It only returns the first instance. If you want to access multiple instances you have to use GetComponents ;)

Nope; can't argue with that. Good call :)

transform is a object/component attached to a gameObject. gameObject.transform is not a class, it is a instance of the Transform class. A class declared as public doesn’t make it accessible by the way you describe it.

public class ComponentA : MonoBehaviour {
   //....
}

public class MyGameObject : MonoBehaviour {
   public ComponentA componentA;
   
   //...
}

Only by doing this you will get:

public MyGameObject mgo;

....

mgo.componentA.DoSomething();

Back to your code, if you have attached the torpedoBehaviour to your torpedo gameObject, then:

TorpedoBehaviour tb = Instantiate( torpedo ... ) as TorpedoBehaviour;

tb.Fire();

no i get that what i'm saying is TorpedoBehavior is a component attached to the TorpedoPrefab Now if i spawn a torpedoPrefab the component is already attached of course in the prefab. But basically what i want is Gameobject Torpedo= instantiate(torpedoPrefab(with attached script)....) as GameObject; Torpedo.attachedscript.scriptfunction(); just like Torpedo.transform.position; Now torpedo already does have a TorpedoBehavior attached. But perhaps it doesnt get attached until runtime and thats the issue. Perhaps a RequireComponent would remedy this?

basically i want to be able to have a script attached to an object be accessible via the dot operator instead of having to use getcomponent. (as is the case with transform component) for example even torpedo.addcomponent<torpedoBehavior>(); still won't allow you type torpedo.torpedobehavior

When we say: gameObject.transform What is defined in the GameObject class would be: public class GameObject : .... { public Transform transform; } But if you want a gameObject to be able to do: gameObject.torpedoBehaviour.Fire(); You are right about doing a dot operator overloading. But you need to know these, you will have to re-write the GameObject class and it is quite dangerous to overload the dot operator. So, just use GetComponent<>().

Also using .transform is a shortcut for doing GetComponent< Transform>() which is annoying because it looks like a variable but takes much longer to access.

But in the [documentation][1], transform is listed as variable of the class. [1]: http://docs.unity3d.com/Documentation/ScriptReference/GameObject.html