Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Adding a script to a selected gameobjects through other script it's adding the script twice ?

Discussion in 'Scripting' started by SharonL75, Oct 10, 2020.

  1. SharonL75

    SharonL75

    Joined:
    Aug 13, 2020
    Posts:
    91
    Code (csharp):
    1.  
    2. using System;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using UnityEditor;
    6. using UnityEngine;
    7.  
    8. public class GenerateAutomaticGuid : Editor
    9. {
    10.    [MenuItem("GameObject/Generate Guid", false, 11)]
    11.    private static void GenerateGuid()
    12.    {
    13.        foreach (GameObject o in Selection.objects)
    14.        {
    15.            o.AddComponent<GenerateGuid>();
    16.            o.GetComponent<GenerateGuid>().GenerateGuidNum();
    17.            o.tag = "My Unique ID";
    18.        }
    19.    }
    20. }
    21.  
    For example I'm selecting two gameobjects in the hierarchy right click and GenerateGuid I use a break point and it's making a loop on each object in the list Selection.objects twice so each object in the list have the script GenerateGuid twice. And I want it to add the script to each object once only.

    This is the GenerateGuid script :

    Code (csharp):
    1.  
    2. using System;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using UnityEngine;
    6.  
    7. public class GenerateGuid : MonoBehaviour, IStateQuery
    8. {
    9.    public string uniqueGuidID;
    10.    public SaveLoad saveLoad;
    11.    public GameObject naviParent;
    12.  
    13.    private Guid guidID;
    14.    private bool isNaviChildOfKid = false;
    15.  
    16.    public void GenerateGuidNum()
    17.    {
    18.        guidID = Guid.NewGuid();
    19.        uniqueGuidID = guidID.ToString();
    20.    }
    21.  
    22.    private State m_state = new State();
    23.  
    24.    public Guid UniqueId => Guid.Parse("E0B03C9C-9680-4E02-B06B-E227831CB33F");
    25.  
    26.    private class State
    27.    {
    28.        public bool naviInHand;
    29.    }
    30.  
    31.    public string GetState()
    32.    {
    33.        return JsonUtility.ToJson(m_state);
    34.    }
    35.  
    36.    public void SetState(string jsonString)
    37.    {
    38.        m_state = JsonUtility.FromJson<State>(jsonString);
    39.  
    40.        if (m_state.naviInHand == true)
    41.        {
    42.            transform.GetComponent<InteractableItem>().distance = 0;
    43.            transform.parent = GameObject.Find("Navi Parent").transform;//rig_f_middle;
    44.            transform.localPosition = GameObject.Find("Navi Parent").transform.localPosition;
    45.            transform.localRotation = Quaternion.identity;
    46.            transform.localScale = new Vector3(0.001f, 0.001f, 0.001f);
    47.        }
    48.    }
    49.  
    50.    private void Update()
    51.    {
    52.        if(transform.IsChildOf(naviParent.transform) == false && isNaviChildOfKid == false)
    53.        {
    54.            m_state.naviInHand = true;
    55.            saveLoad.Save();
    56.  
    57.            isNaviChildOfKid = true;
    58.        }
    59.    }
    60. }
    61.  
    A screenshot of all the places I'm calling the GenerateGuid :



    I added a screenshot to my question of where I'm calling the GenerateGuid script or using. In two places I'm doing GetComponent to get this script and use it. In other two places are in the GenerateAutomaticGuid editor script. And I'm not calling anywhere to GenerateAutomaticGuid just using it with right click mouse when selecting objects.


    And I used a breakpoint and if for example I selected two items in the hierarchy and did right click with the mouse and selected tp GenerateGuid it will loop 4 times in the foreach loop even if there are only two items.
     
    Last edited: Oct 10, 2020
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,519
    If you select 2 items, 2 items will be in the selection list.

    Then if you right-click, it will apply what you do to each item.

    So for each item (of which there are 2), you are iterating all selected items (2).. hence ... 4!

    Top script, remove line 13, see if it does more what you expect. You don't need to iterate selections, Unity is doing it for you because that's what you had selected when you right-clicked.
     
    SharonL75 likes this.
  3. SharonL75

    SharonL75

    Joined:
    Aug 13, 2020
    Posts:
    91
    If I will remove line 13 the foreach loop then the variable 'o' of GameObject in the fforeach will not be xist then how do I iterate over the selected objects ? Or how I use them ?
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,519
    You shouldn't iterate over the items. That's what Unity does for you, calling that function for each item.

    EDIT: I'm confused... Disregard the above. Put some Debug.Log() breakpoints in above the for() loop... how many times is that function being called when you hit the menu item?
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,519
    Also, these lines:

    Code (csharp):
    1. o.AddComponent<GenerateGuid>();
    2. o.GetComponent<GenerateGuid>();
    Try break it apart and do:

    Code (csharp):
    1. var g = o.GetComponent<GenerateGuid>();
    2. if (!g) g = o.AddComponent<GenerateGuid>();
    3. g.GenerateGuidNum();
    That way if there IS one, it will never add a fresh one.

    And in all cases it will refresh the GUID.