- Home /
How to distinguish between multiple components of same type
Lets say I have a "torso" GameObject and I use 2 hinge joint components to attach a left and right arm.
Now, in script, I want to control each hinge joint separately.
How can I set things up so that in my code I can distinguish between the hinge joint for the left arm and the hinge joint for the right arm.
-Jeff Weber
But I don't see a way to set a component tag in the editor and I don't see a GetComponentByTag method.
@mohanrao164 Tags don't go on components.. read the question.
I presume this is purely for example purposes, but note that the "normal" way to structure a skeletal structure would put the joint components on the arms, not the torso, such that each Rigidbody has just one joint, regardless of how many appendages join to it.
The question was partially for example purposes as I see this co$$anonymous$$g up in other situataions, but it is also specific to something I'm trying to do. I'll try to design my bodies the way you suggest.
Answer by Joshua · Sep 02, 2011 at 12:37 PM
You can only distinguish between several instances of the same class by their properties and variables, so in this case the second body they´re connected to.
you could also add the hingejoints through scripting and cache them, especially if the connected bodies also have multiple hinges, but in your case joshua's anwer should do it
Yeah, saving a referencing is definitely the normal way to do it. Unity makes it sometimes impossible to do things the normal way though, for instance here - you'd need to know the position and rotation, etc of the joints beforehand.
$$anonymous$$inda wish the "tag" property on components was exposed in the inspector and there was a GetComponentByTag method. Oh well, I think I can work around it by checking the attached body as Joshua suggests. Or by composing my character differently as suggested above by Warwick. Thanks all.
@JeffWeber: Components don't have tags or names. The component class have those properties but they just return the name or tag of the GameObject it's attached to.
Actually, you can distinguish between multiple instances...
Answer by RyanFaeScotland · Mar 14, 2015 at 01:13 AM
I've got 2 Audio Sources connected to my main camera, one for music and one for the only sfx in my simple game which is called "Blop".
When I create the object that is going to trigger the sound effect I get a reference to the correct Audio Source from the camera thus:
public class MyClass : MonoBehaviour {
private AudioSource source;
// Use this for initialization
void Start () {
foreach (AudioSource aSource in Camera.main.GetComponents<AudioSource>())
{
if(aSource.clip.name.Equals("Blop")){
source = aSource;
break;
}
}
}
I can't guarantee it's the best way as I am just cutting my teeth with Unity but it is simple and sometimes that's all you need.
Nice solution. It could also be:
void Start () {
aSource = Camera.main.GetComponents<AudioSource>()[indexFromAudiosource];
}
But, depend of the index of the Audiosources.
Regards.
Answer by Bunny83 · Sep 02, 2011 at 02:42 PM
You can also do it the Unity's drag&drop way :D
If you have a script of your character just add two public variables of type HingeJoint. Now you can drag-drop the two joints onto those variables.
I'm not a fan of that way. Under some circumstances Unity can loose those references so i usually aviod too complex inspector-reference-setups. But for such small things it should be no problem.
the most common way to lose reference is if the referenced object in the drag & drop (exposed variable) is not in the object's hierarchy and you try instantiating the prefab on another scene.
I like it cause it's great for testing, sometimes I do it this way and on script I put if(!object) GameObject.Find("object"), this way I can cache and keep it simple on short projects, but it's still sloppier than instantiating through scripting
It's tricky if the component controlling the two HingeJoints is on a different GameObject. Then you need to open them in two different Inspector windows (and use the lock icon) to be able to drag between them.
Yes drag&drop is prone to lost references, but can be more easily used by non-coders.
Answer by Ertug · Jul 13, 2014 at 10:05 AM
You can define variables for a specific type of component that you later wish to refer to. In my case I defined FixedJoint variables:
var newFixedJoint1 : FixedJoint;
var newFixedJoint2 : FixedJoint;
Then I used these variables to define FixedJoints that I added to myGameObject:
newFixedJoint1 = myGameObject.AddComponent(FixedJoint);
newFixedJoint2 = myGameObject.AddComponent(FixedJoint);
And then later I was able to refer to those FixedJoint components separately like this:
newFixedJoint1.connectedBody = someGameObject.rigidbody;
newFixedJoint2.connectedBody = someOtherGameObject.rigidbody;
That's JavaScript but you can use this method as a solution I think.
Answer by ransomink · Jan 14, 2018 at 06:58 PM
You can distinguish between multiple components by using GetComponents.
HingeJoint[] hingeJoints;
void Awake()
{
hingeJoints = GetComponents<HingeJoint>();
}
They will be placed in order from top-to-bottom. If the first hinge joint is the left arm you'll use hingeJoints[0]
and hingeJoint[1]
for the right arm.
Alternatively, you can reference them for easier access, like so:
HingeJoint[] hingeJoints;
HingeJoint leftArm;
HingeJoint rightArm;
void Awake()
{
hingeJoints = GetComponents<HingeJoint>();
leftArm = hingeJoint[0];
rightArm = hingeJoint[1];
}
At the time the question was asked (and the other answers were posted) Unity did not return a particular order in the GetComponents call. The order preserving comes with Unity 5.x i think. However it's still a better approach to assign the components in the inspector to the right slots / variables