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

u can use tags and distinguish between them.

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 coming 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.

5 Answers

5

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.

Kinda 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...

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.

You can also do it the Unity’s drag&drop way :smiley:

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.

Yeah, hate doing it that way, but it works I guess... ;)

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.

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];
}

This should be the top answer, tbh.

Thanks a lot man! I tried every solution and that code used to delete the original copy and not the one which has been loaded from another scene due to which the references were empty on the loaded copy of the object. Tried this code and it worked! Again, thanks a lot!

this worked like charm thanks for the help

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.