- Home /
How to compare if two gameObjects are the same?
I´m trying to make a game about visual memory. Random a game object appears and after 5 seconds disappear and another one appear. The goal is the player select that game object if is equal to the last one. How can i compare the fist game object and the one that players click? Any suggestions???
Thanks
Question may be old but i need an answer for this too. Following.
He basicly asks if we able to compare two gameobject depending on are they same or not.
if (firstObject.transform == secondObject.transform) { Debug.Log ("the same"); }
Answer by Mouton · Jun 06, 2015 at 03:03 PM
[Edit:] Changed the code to match your needs + some further informations below
What the OP needs is not comparing if two GameObject references point to the same GameObject but compare if the "Visual Informations" are the same.
In order to do so, you can add a component to all the clickable GameObjects with a logic to check if the visual information matches to the reference one
In my example, I will use a Picture, but you can do the same with a sound, a phrase, anything that should be considered similar by humans.
public class ReferencePicture: Monobehaviour
{
public ClickablePicture matchingPicture;
void Start()
{
MatchANewPicture();
}
public void MatchANewPicture()
{
if (matchingPicture != null)
{
matchingPicture.referencePicture = null;
matchingPicture = null;
}
// there may be new pictures since we last checked
ClickablePicture[] clickablePictures = GameObject.FindObjectsOfType<ClickablePicture>()
ClickablePicture matchingPicture = clickablePictures[Random.Range(0, clickablePictures.Length)];
matchingPicture.referencePicture = this;
}
// We don't want the pictures to get different,
// so we change both reference & matching
void OnChangePicture(Material material)
{
this.GetComponent<Renderer>().material = material;
matchingPicture.GetComponent<Renderer>().material = material;
// if you want to do some further job inside 'ClickablePicture' class
// matchingPicture.OnChangePicture(material);
}
}
With such a ReferencePicture class, the ClickablePicture class gets trivial:
public class ClickablePicture : Monobehaviour
{
public ReferencePicture referencePicture;
public void OnClick()
{
if (reference == null)
Debug.Log("Wrong !");
else
{
Debug.Log("Correct !");
referencePicture.MatchANewPicture();
}
}
}
Now you have a safe Reference / Clickable connection set very easily.
You are right, they can't have more then one GameObject, but two different GameObjects' Transforms can be equal.
Not correct. Transforms are of reference type. When you compare two references, you compare their adresses in memory, not their value. This is why we say they are reference type and not value type. It wouldn't be efficient to compare if the position, rotation & scale of your transforms are the same.
GameObject firstObject = new GameObject ();
GameObject clickedFirstObject = firstObject;
Debug.Log (firstObject == clickedFirstObject); // true
Debug.Log (firstObject.transform == clickedFirstObject.transform); // true
GameObject clickedOtherObject = new GameObject ();
firstObject.transform.position = new Vector3 (1, 2, 3);
firstObject.transform.rotation = new Quaternion (0.1f, 0.2f, 0.3f, 0f);
firstObject.transform.localScale = new Vector3 (1, 2, 3);
clickedOtherObject.transform.position = firstObject.transform.position;
clickedOtherObject.transform.rotation = firstObject.transform.rotation;
clickedOtherObject.transform.localScale = firstObject.transform.localScale;
Debug.Log (firstObject.transform == clickedOtherObject.transform); // false
Debug.Log (firstObject.transform == clickedFirstObject.transform); // still true
To be sure, we double check with the method Object.ReferenceEquals(a, b) and the result are the same (this is pretty much what the "==" operator does for a reference type)
Debug.Log (Object.ReferenceEquals (firstObject, clickedOtherObject)); // false
Debug.Log (Object.ReferenceEquals (firstObject, clickedFirstObject)); // true
And this is true with every reference type. The "==" operator is overloaded so reference types compare their reference (thing they point in memory). Now, let's consider this:
int a = 1;
int b = 1;
Debug.Log (a == b); // not the same reference, but true
Debug.Log (Object.ReferenceEquals (a, b)); // of course, this is false
int is a value type, so the "==" operator is overloaded so value types compare their value.
Why does reference types works that way ? Because an addresse in memory is a relatively small data to store, and you don't want to copy a 100MB class whenever you want to use it, so when you do "objA = objB", you just create a new reference. However, using GameObject.Instantiate(objA) will create a new instance using it's own memory and getting it's own reference.
I hope it will help to make the distinction between an object, it's value and it's reference. You should also consider to visit these links.
Answer by starikcetin · Jun 06, 2015 at 06:36 PM
I'm experimenting since morning and these are results I got so far.
When you compare two gameobjects directly with "==" operator, it only returns true if they are exactly same object (they must refer to "same instance" of "same object"). It's even returning false if you are comparing two different instances of same object (for example two clones from same prefab).
When you use GetType(), it always returns true as they are all type of "GameObject".
And comparing transforms are a whole different thing.
So actually, you can not get a "true" for not-same-instanced gameobjects (this means they are completely the same thing, so it would be better to use "gameobject" instead "gameobjets") unless you "tweak" a bit.
For my project, i personally decided to compare names. As my gameobjects coming from same prefab, their name are all same ((Clone)PrefabName), but if yours are not named same, then you can use tags, or maybe you can find another solution for this.
Best wishes.
1 - Comparing two game object as such:
GameObject a,b;
if(a == b){}
means you are comparing the address in memory. If both references are the same object then you get true, else you get false;
a = b;
if(a == b){// true}
a = new GameObject();
b = new GameObject();
if(a == b){// false}
using GetType means you are comparing the type of two objects. Using GetType you create a new object of type Type and then it is compared with another object of type Type. In this case, it is not the address that is compared but the content. So two GameObjects would return true.
Type typeA = a.GetType();
Type typeB = b.GetType();
if(a == b){ // true }
As you said, none of those are your solution. In my opinion, I would consider using prefabs and a public enum.
public enum ItemType{ None, TypeA, TypeB, TypeC}
public class $$anonymous$$yObject : $$anonymous$$onoBehaviour{
[SerializeField] private ItemType objectType = ObjectType.None;
public ItemType Item { get { return objectType; } }
public bool CompareObject($$anonymous$$yObject other){
return other.Item == this.Item;
}
}
This way you can have prefabs on which you set the type via inspector.
Compare the GameObjects name is a slow operation, as long as you don't have many objects it is okay. But it is a bad habit, and you should reconsider it right now. The sooner you learn it the good way, the better.
String comparisons, such as GameObject.Find() or A.name == B.name are pretty unefficient. In order to do their job, they have to check if the first character of A match the first character of B, if it's true, they check for the second character, and that until the end of the strings for all the objects in your scene ! There is another side effect: you can't change your object name without changing the string in your code, and vice-versa. And the compiler won't say you there is a problem until it reaches it.
For relatively small projects you will be fine until your project grows bigger as you expected. Then you'll have to gather your code for all those string comparisons.
Check for references, types or enum. You'll thank yourself !
I'm writing a tower defense game, so there won't be huge amounts of objects, but next time i will obey your suggestions. Thanks!
Hi Joan You can make use of Tags.Also tags can be changed at runtime Below steps may help you
Create a gameobject give a tag to it(Eg:"Box")
Randomly create another gameobject with the same tag that was created previously("Box")
When user clicks on the object then check with the gameobject's tag with the current tag that you looking for!
This is just a simple approach. Hope this $$anonymous$$ay Help you. Thank You Nsk
Your answer
Follow this Question
Related Questions
How to compare if two gameObjects are the same? 4 Answers
Making a randomizer script for a basic "Runner" game... 1 Answer
How to make objects appear randomly around a spot 2 Answers
Random Time question 2 Answers
Randomly spawn a trigger area 1 Answer