Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

How can I find the game objects belonging to my player/bot without being directly attached?

Discussion in 'Scripting' started by Braineeee, Dec 11, 2015.

  1. Braineeee

    Braineeee

    Joined:
    Nov 9, 2014
    Posts:
    1,211
    So I'm working to create a simple kind of modular gun firing system.

    My player has a few guns on him (he's a spacecraft). His hierarchy is like so:

    GamecontrollerHierarchy.JPG

    Each Gun object has a bulletspawn empty gameobject beneath it which acts as a place for the bullet to spawn. On these bulletspawns are MouseFire C# script objects, with a small function which manages the bullet creation for pooling and setting the active/inactive on them.

    The Guns empty gameObject only contains a fireGuns script. It manages the timing and calling Fire() on each gun which needs to fire when.

    Every ship is controlled by either a camera orientation (the ship is made to follow the motions of the camera/game controller) or a game controller (for AI). The generic script FlightControl gets its input from either the player via a script called getinput, or optionally from an BotBehavior script.

    That input is used to compute the new position/orientation of the camera/game controller. The red/blue circled lines are my game controller/cameras. The player/bot they are assigned to are highlighted in yellow just beneath them. These game controllers are simply assigned a new position offset from the ship position, every Update().

    Now the problem is this: I want to be able to create a new AI or player at will. I don't want to have to limit the number of AI or players at this point. To do that I need to be able to find the related game controller game object which is not attached to the main player/ai at all.

    Yet to initialize the Flightcontrol script I need a reference to the camera or gamecontroller **belonging** to that player or AI. I haven't found a way to get a reference to it. I was thinking of something like: GameObject.FindGameObjectsWithTag("GameController"), then searching that array for the correct game controller. That solution is however quite elusive.

    So my question is: How do I find the game object related to my player or bot?


    and wow. I was going to post this in the Answers section but that isn't working either. I can't post anything because the Add topics feature doesn't work. I'm gonna have to do something about these things... so lazy :p
     
  2. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,744
    Long post, short answer:

    Code (csharp):
    1. Gun[] myGuns = GetComponentsInChildren<Gun>();
     
    Munchy2007 likes this.
  3. Braineeee

    Braineeee

    Joined:
    Nov 9, 2014
    Posts:
    1,211
    It is a long post. The solution is not as simple as you think, and that won't work. Let this demonstrate what I mean:

    GameHierarchyExample.JPG

    I need to find whats in the Orange box. There will be many other objects like it with the same names/tags. I could add a variable to each gamecontroller which could identify it, and use that to find the right one. Maybe I'll try that... I just didn't want to create a script explicitly for one field.
     
  4. Sose

    Sose

    Joined:
    Dec 10, 2015
    Posts:
    27
    If you need to find the MainCamera, can't you do GameObject.Find("MainCamera")? Also is there necessarily a reason to have the controller for MainPlayer in a separate non-parent GameObject in the scene?
     
  5. Braineeee

    Braineeee

    Joined:
    Nov 9, 2014
    Posts:
    1,211
    Nope. I've tagged all my game controller's as "GameController", specifically because there should be no difference between how a camera and an empty object behave. The FlightControl script can take input from virtually anything via the TakeInput() foo. The camera or in case of a bot can control its own flight behavior by calling takeinput() with args. In this scheme the camera's orientation determines what direction the ship will fly in.

    I just tried the ID thing. It did not work out as I expected.

    Maybe I should just group them beneath another empty game object. I was thinking if that happened then I would have to do all my movements locally... maybe not. IDK.
    It would be hard to spawn these without them being part of one prefab though, too. They are separate prefabs. I'll have to try that.

    OH and lastly, they are currently separate because in previous versions attaching one beneath the other caused undesired behavior. They have to be separated or at least on the same level.
     
  6. Sose

    Sose

    Joined:
    Dec 10, 2015
    Posts:
    27
    So I understand that there are 2 FlightControl scrips in your whole scene? One for player, one for all the enemies? Or do the enemies control themselves? Anyways..

    I thought GameObject.Find(string name) searched for names, not tags. So in your case you apparently need to find either "MainCamera" or "ControlEmpty"? I'm not sure I understand what the actual problem is.

    And when it comes to parenting things, children's transforms will depend on their parent's transform. But if your parent's transform is (0,0,0), then it's effectively the same as having it parented straight to the scene
     
  7. ThermalFusion

    ThermalFusion

    Joined:
    May 1, 2011
    Posts:
    906
    I don't think I'm getting the problem.
    Are you creating more enemies by instantiating Enemy? If you are you can get your reference to the instantiated enemy when you are instantiating it. Otherwise just assign the references in the inspector?
     
  8. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    There are a bunch of ways to approach this.

    Statics and singletons will work on a small project.

    For larger systems you want to pass in the references when you create the object. Check out the factory pattern. Whatever object creates the enemies is also responsible for setting up the references.

    The other option is to have each enemy create its own stuff as needed.
     
  9. Braineeee

    Braineeee

    Joined:
    Nov 9, 2014
    Posts:
    1,211
    I think I'll try that @BoredMormon. TBH guys it may have been my fault but I really hate it when people misunderstand me, especially when I went through a lot just trying to explain it. At least BoredMormon got it :p

    Maybe I'll just turn this in to the "Help me with my project" thread. I would rather not start another thread for a similar or the same project/problem.

    Right now I'm getting this: HelpWithUnityNeeded.JPG


    On this line of code and I don't know why:

    Code (CSharp):
    1.         deezNuts = gameObject;
    2.         gunTrans = new List<Transform>(); //    NOTE: Always, always, ALWAYS declare a new object like this! Or you'll get a null reference!
    3.         GameObject[] temp = deezNuts.GetComponentsInChildren<GameObject>(true); //Find the guns
    4. /*THE LINE ABOVE IS THE PROBLEM*/
    5.         Utility.displayMessage("There are: " + temp.Length + "Objects for the GunController script!");
    6.         for (int p = 0; p != temp.Length; p++)
    7.         {
    8.             guns.Add(temp[p].GetComponent<Gun>());
    9.             gunTrans.Add(temp[p].GetComponentInParent<Transform>()); //Add the transform for each gun to the gunTrans List
    10.         }
    11.         Utility.displayMessage("Just Experimenting.");
    12.         gunNumb = 0;
    13.  
    The "deezNuts" object is was put in place because I was playing around trying to find the source of the problem before I began googling/asking for a solution. Its just a GameObject.

    I'm guessing you can't do this that way??

    The exception is rather esoteric and doesn't make sense to me. GameObject is a valid argument, at least with Unity and VS doesn't flag it. I even gave it a boolean value to see what it did (nothing) even though I don't know what its purpose is!
     
  10. Sose

    Sose

    Joined:
    Dec 10, 2015
    Posts:
    27
    You can't use GetComponent() to find GameObjects as GameObjects are not components, they are the bags that hold all the components! If you want to get the children GameObjects of a GameObject, maybe try searching for Transform components as every GameObject is guaranteed to have one. Try something like this maybe..

    Code (csharp):
    1.  
    2. Transform[] childrenTransforms = GetComponentsInChildren<Transform>();
    3. // note, I think the first element ([0]) will always be the gameobject of this script
    4. // so just to get children, maybe start looping from [1]
    5. Debug.Log(childrenTransforms[0].gameObject.name); //in my test case, prints the owner of the script
    6.  
    7. for(var i = 1; i < childrenTransforms.Length; i++)
    8. {
    9.    var trans = childrenTransforms[i];
    10.  
    11.    Debug.Log(trans.gameObject.name);
    12.    guns.Add(trans.gameObject); //adds the _GameObject_ to guns. Is Guns a script or are they GameObjects..?
    13.    gunTrans.Add(trans);
    14. }
    15.  
    Funnily enough I didn't find a method to search for children gameobjects directly in the unity scripting API. Granted I didn't look too hard but seems weird
     
  11. Braineeee

    Braineeee

    Joined:
    Nov 9, 2014
    Posts:
    1,211
    Yeah. That's what made it so hard to find an answer, but I managed to find one. Thank you!