Как найти объект по позиции unity

Suggest a change

Success!

Thank you for helping us improve the quality of Unity Documentation. Although we cannot accept all submissions, we do read each suggested change from our users and will make updates where applicable.

Close

Submission failed

For some reason your suggested change could not be submitted. Please <a>try again</a> in a few minutes. And thank you for taking the time to help us improve the quality of Unity Documentation.

Close

Your name

Your email

Suggestion*

Cancel

Switch to Manual

Declaration

public static GameObject Find(string name);

Description

Finds a GameObject by name and returns it.

This function only returns active GameObjects. If no GameObject with name can be found, null is returned. If name contains a ‘/’ character, it traverses the hierarchy like a path name.

For performance reasons, it is recommended to not use this function every frame. Instead, cache the result in a member variable at startup. or use GameObject.FindWithTag.

Note: If you wish to find a child GameObject, it is often easier to use Transform.Find.

Note: If the game is running with multiple scenes then Find will search in all of them.

In this article, we will see, How to find gameobject at runtime in unity using C#. I will explain each and every ways of finding game objects at runtime. So if you are interested then let’s begin.

Introduction

There are different ways to find gameobject at runtime in unity, We are gonna cover all of those ways in this article, So let’s start.

Advertisements

So first we will look at what are the actual ways to find gameobject at runtime in unity. So There are several ways of finding gameobject at runtime

  1. Gameobject.Find.
  2. Resources.FindObjectsOfTypeAll.
  3. Find gameobject with tag.
  4. Transform.Find.
  5. transform.GetChild.

For instance, We will find this gameobject (shown in the image below) In different ways.

Find Gameobjects At Runtime In Unity C#
Find Gameobjects At Runtime In Unity C#

Advertisements

As you can see in the above image I have highlighted the “Destroy Obj” Gameobject, And we will be finding this gameobject through this article in different-different ways. So let’s start with our first way of finding gameobject at runtime.

First, we will see how to find gameobject with Gameobject.Find(“”).

1. Find gameobject with Gameobject.Find

 The first way to find gameobject at runtime in unity is the Gameobject.Find. In order to find our gameobject called “Destroy Obj”, Here is a simple code:

private void Start()
{
     GameObject objectToDestroy = GameObject.Find("Destroy Obj");
}

Advertisements

Here I have used this code in the Start function but you can use it where ever you need it, But if possible always try to do it in Start, Awake and OnEnable Function and try to avoid it using in loops or Update Function.

Note :- It will only work if the object that we are finding is active in the hierarchy, If your gameobject is not active in the hierarchy and you want to find it at runtime then you can try the other methods shown below.

But this way to find gameobject at runtime in unity is heavy when you use it in Update method, So try to always use in Start method and take a reference of it in variable and use it wherever you want it.

2. Resources.FindObjectsOfTypeAll

This function can return any type of Unity object that is loaded, including game objects, prefabs, materials, meshes, textures, etc. It will also list internal objects, therefore be careful with the way you handle the returned objects.

So through Resources.FindObjectsOfTypeAll you can also find the list of disabled objects in the scene as well. So here is the simple code of it.

Advertisements

using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class ExampleScript : MonoBehaviour
{
    List<GameObject> GetAllObjectsOnlyInScene()
    {
        List<GameObject> objectsInScene = new List<GameObject>();

        foreach (GameObject go in Resources.FindObjectsOfTypeAll(typeof(GameObject)) as GameObject[])
        {
            if (!EditorUtility.IsPersistent(go.transform.root.gameObject) && !(go.hideFlags == HideFlags.NotEditable || go.hideFlags == HideFlags.HideAndDontSave))
                objectsInScene.Add(go);
        }

        return objectsInScene;
    }
}

This will return all GameObjects in the scene, in List<GameObject> format even if gameobject is disabled.

So this is the another way to find gameobject at runtime in unity.

3. Find gameobject with tag

In this way, You can find the gameobject with tags like “Player” or “Enemy”. Returns one active GameObject tagged with the tag you are looking for. Returns null if no GameObject was found.

Tags must be declared in the tag manager before using them. A UnityException will be thrown if the tag does not exist or an empty string or null is passed as the tag.

 Here is the code for finding gameobject with tag.

private void Start()
{
      GameObject objectToDestroy = GameObject.FindWithTag("Bullet");
      Debug.Log(objectToDestroy.name, objectToDestroy);
}

In the place of “Bullet”, You must replace it with your tag. It won’t find if gameobject is disabled.

4. Transform.Find()

This API will return the transform of the child transform or null if no child will be found. In this way, you can also find disabled gameobject in unity.

GameObject gun = player.transform.Find("Gun").gameObject;

You can also find the child of the child, For instance:-

Find Gameobjects At Runtime Through Transform.Find()
Find Gameobjects At Runtime Through Transform.Find()

Let’s say you want to find the “Cube3” (Highlighted with Blue) and your transform is “Cube” (Highlighted with Red). So It is possible through the ‘/’ character, It will access the Transform in the hierarchy like a pathname. Here is the example code

GameObject cube3 = transform.Find("@Cube (single mesh)/Cube3").gameObject;

This example is according to the image attached above. This way you can find the disabled gameobjects in unity.

5. transform.GetChild(Index)

This is used when we want to get a child by index and it returns a transform of a child by index.

If the transform has no child, or the index argument has a value greater than the number of children then an error will be generated. In this case “Transform child out of bounds” error will be given. The number of children can be provided by childcount.

Let’s see an example of transform.GetChild(). Let’s take the above image example that we used in transform.Find(). So we want to find “Cube 3” again.

So here is the simple code of it.

GameObject cube3 = transform.GetChild(0).GetChild(2).gameObject;

So this is also the great way to find gameobject at runtime in unity.

You can check this in the above image and match the indexes.

So these are the Ways to find gameobject at runtime in unity. And if you know any other way to find gameobject at runtime in unity, So I will be glad if you share that in the comment section below.

Hope guys this was helpful and may have learned something new today, Stay tuned for new topics.

So what way you prefer to find gameobject at runtime? Comment down 

Advertisements

If you have an issue or query you can contact me. Thank You.

When developing games in Unity, one of the most common tasks is to find and interact with game objects. Whether you need to access an active game object, search for a specific tag, or retrieve the first object that matches a certain criterion, Unity provides several methods to accomplish these tasks efficiently. In this article, we will explore different ways to find game objects in Unity using C#.

Do not use these functions in the Update method without a condition. Otherwise, it will search for the object every frame and affect the performance of the game. It’s wise to use them in the Awake or Start function.

The GameObject.Find Method:

The most straightforward method to find a game object is by using the GameObject.Find method. This method takes a string argument, which represents the path name of the object in the hierarchy view.

For example, if you have an object named “Player” nested under an empty object named “Characters,” you can find it using GameObject.Find("Characters/Player"). However, it’s important to note that using GameObject.Find can impact performance, especially if used frequently or in performance-sensitive areas like the Update function.

GameObject.FindWithTag:

To simplify the process of finding objects with a specific tag, Unity provides the GameObject.FindWithTag method. This method takes a string argument representing a tag and returns the first active game object with that tag. Tags can be managed using the Tag Manager in the Unity editor, allowing you to assign meaningful tags to objects for easy identification and retrieval.

Transform.Find and GetComponentInChildren:

If you need to find a child game object of a specific parent object, you can use the Transform.Find method. This method searches for a child object using its path name relative to the parent object. For instance, transform.Find("ChildObjectName") will return the child object with the specified name.

Additionally, if you need to find a component attached to a child object, you can combine GetComponentInChildren with Transform.Find to retrieve the component from the child object.

Object References and Member Variables:

In many cases, you may already have a reference to a game object stored in a member variable. In such scenarios, there is no need to find the object again using any of the aforementioned methods. By assigning the game object to a variable, you can directly access its properties and components without the need for additional searches.

It’s important to mention that finding game objects during runtime incurs a performance cost, especially when performed frequently or in computationally intensive situations. To optimize your game, consider caching object references when possible or using alternative strategies to minimize the number of find operations.

In conclusion, Unity provides various methods to find game objects efficiently. Whether you choose to use the GameObject.Find method, leverage tags and the Tag Manager, or store object references in member variables, understanding the different ways to find game objects in Unity will greatly enhance your game development workflow. Remember to consider performance reasons when determining the most suitable method for your specific use case, and optimize your code accordingly.

Try using Physics.OverlapSphere. You can define a sphere at a Vector3 point you’d like to check for ((2, 4, 0) for example). You can give it a low radius (or maybe even 0, but you’d have to check that, I’m not 100% sure if it works).

It returns an array of all colliders that are touching or are inside of the sphere. Just check if the array is empty (or the length is 0) and if it is, nothing is touching it.

You could use it like this:

Collider[] intersecting = Physics.OverlapSphere(new Vector3(2, 4, 0), 0.01f);
if (intersecting.Length == 0) {
    //code to run if nothing is intersecting as the length is 0
} else {
    //code to run if something is intersecting it
}

or, of course, you could do this:

Collider[] intersecting = Physics.OverlapSphere(new Vector3(2, 4, 0), 0.01);
if (intersecting.Length != 0) {
    //code to run if intersecting
}

Hope this helps!

EDIT: Here’s a function that just returns true if a point intersects with a collider.

bool isObjectHere(Vector3 position)
{
    Collider[] intersecting = Physics.OverlapSphere(position, 0.01f);
    if (intersecting.Length == 0)
    {
        return false;
    }
    else
    {
        return true;
    }
}

There are times when you need to search the Unity hierarchy for particular game objects. Often you need to find them by name, tag or component type. I have found that on occasion I’ve wanted to wanted a more expressive and flexible way of finding game objects. Some years ago when I was attempting to improve my skills in CSS hackery I made an important connection.

I thought: what if I could query a Unity hierarchy using an expressive query language that is like CSS selectors?

Or put another way: what if I could query the hierarchy as if it was some sort of database?

It was thoughts like this that lead to creation of the Scene Query library.

In this article I show various examples of finding game objects in the hierarchy using the native Unity UI. Then I’ll show you how to level up and write advanced queries to pattern match and find specific objects in the scene.

If you want to skip the fluff and checkout the advanced features please jump directly to the Advanced Features section, you can always read the rest of the article later.

Table of Contents generated with DocToc

  • My setup
  • Example code
  • Finding game objects using the Unity API
  • What can’t we do with the Unity API?
  • Finding game objects with the Scene Query API
  • Performance considerations
  • Conclusion

My setup

I am currently using Unity 5.3.4 and Visual Studio Community 2015.

Example code

An example Unity project demonstrating all these techniques can be found on github. Please download this to follow along with the examples.

The core scene query code can be found at its own github repository.

These examples are trivial and rather contrived, however they are derived from real world examples. You’ll see in a number of places I use examples such as finding the player object and connecting a vehicle to multiple pedestrians (possibly so that its AI can avoid them).

Note that all numbered examples below have a working example in the example Unity project.

Finding game objects using the Unity API

Before we get into the scene query language, let’s look how to search for game objects using the native Unity API.

1. Find object by name

This is how to find a single object by name:

var player = GameObject.Find("Player");
Debug.Log("Found game object " + player.name);

Note that the Player object can be anywhere in the hierarchy.

2. Find objects by name

Ok, so Unity doesn’t actually allow you to find multiple objects by name. If it did you might be able to call a function like FindObjects:

var pedestrians = FindObjects("Pedestrian")
foreach (var pedestrian in pedestrians)
{
	Debug.Log("Found game object " + pedestrian.name);
}

Of course that function isn’t a part of the Unity API. But you can implement it yourself easily (with some help from LINQ Where):

public IEnumerable<GameObject> FindObjects(string name)
{
	return GameObject.FindObjectsOfType<GameObject>()
		.Cast<GameObject>()
		.Where(gameObject => gameObject.name == "Pedestrian")
		.ToArray();
} 

3. Find direct child object by name

You can easily find the direct child of a particular parent game object by calling the FindChild method of Transform:

var child = parent.transform.FindChild("Child");
Debug.Log("Found child object: " + child.name);

4. Find objects by tag

If you need to find a collection of game objects based on name your best option in the Unity API is to find by tag. For this to work you need to tag each object using the Unity Editor. Then call FindGameObjectsWithTag to find the collection of tagged game objects:

var pedestrians = GameObject.FindGameObjectsWithTag("Pedestrian");
foreach (var pedestrian in pedestrians)
{
	Debug.Log("Found pedestrian: " + pedestrian.name);
}

5. Find object by type

Finding objects by name is best avoided where possible. It can lead to fragile code. If you find yourself having magic strings in your code you should consider finding by type instead:

var leaderboard = GameObject.FindObjectOfType<Leaderboard>();
Debug.Log("Found leaderboard: " + leaderboard.name);	

This can lead to better code because it will be more type-safe. This kind of code can surive automatic refactoring (for example in Visual Studio).

6. Find objects by type

Unity conveniently gives you a function to find multiple objects by type:

var pedestrians = GameObject.FindObjectsOfType<Pedestrian>();
foreach (var pedestrian in pedestrians)
{
	Debug.Log("Found pedestrian: " + pedestrian.name);
}

I love the fact that you can easily chain LINQ functions on the end of this. For example if you want to sort the objects by name:

var sortedPedestrians = GameObject
	.FindObjectsOfType<Pedestrian>()
	.OrderBy(pedestrian => pedestrian.name);

Of if you want to first filter out certain game objects:

var sortedPedestrians = GameObject
	.FindObjectsOfType<Pedestrian>()
	.Where(pedestrian => PedestrianMatches(pedestrian))
	.OrderBy(pedestrian => pedestrian.name);

What can’t we do with the Unity API?

So what can’t we do with the native Unity API?

  • Well for a start you can’t get multiple objects by name (unless you write your own function, as I demonstrated earlier).
  • It’s not possible to search for an object by name somewhere under another object. As I’ve demonstrated you can find an object directly under a parent, you just can’t find an object in the entire sub-hierarchy.
  • You definitely can’t search for multiple objects by name somewhere under a parent object.
  • You can’t do partial name or wildcard matching, for example you can’t find all objects that have a name starting with Pedestrian.
  • We can search for multiple objects by tag, but we can’t search for them by layer.
  • We can’t combine our queries in sophisticated ways for more advanced searches.

So how do we achieve these feats? Enter the Scene Query library…

Finding game objects with the Scene Query API

The Scene Query library provides basic search facilities like we have already discussed. It also provides numerous advanced features on top of what Unity can already do.

I’ll start by covering much of the same ground and showing you how to do basic stuff with the Scene Query library. We’ll quickly work our way to the more advanced features.

Getting setup

You can copy the code from github and copy it into your project or you can get the dll from nuget.

You can find the complete code in the example Unity project as well under the Scene Query Library folder. Just copy this folder into your own project.

To use the library simply instantiate SceneQuery:

SceneQuery sceneQuery = new SceneQuery();

Basic Features

In the following sections I cover the basic feature of Scene Query. If you are eager to get to the cool stuff please jump straight to the Advanced Features section, you can always come back and read the basics later.

7. Find object by name

Finding a single object by name is achieved through SelectOne:

var player = sceneQuery.SelectOne("Player");
Debug.Log("Found game object " + player.name);

So far there is little difference between Scene Query and the native Unity API (besides the name of the function).

Note that this finds the first object with the requested name. If there are no objects with that name it returns null.

Alternatively you could ExpectOne:

var player = sceneQuery.ExpectOne("Player);

This throws an exception when the requested game object does not exist or when there are more than a single instance of the name object. It can simplify your error handling and make your code more expressive of your intent.

8. Find objects by name

SelectAll finds all objects with a given name:

var pedestrians = sceneQuery.SelectAll("Pedestrian");
foreach (var pedestrian in pedestrians)
{
	Debug.Log("Found game object " + pedestrian.name);
}

Now we are getting somewhere. There is no native Unity function for getting a collection of objects by name.

9. Find object directly under a named parent

Let’s look at something else the Unity API can’t do by itself. We can find an object by its path in the hierarchy:

var child = sceneQuery.SelectOne("Parent/Child");
Debug.Log("Found child object: " + child.name);

Note that the hierarchy path looks similar to a filesystem path. We can address objects by path down to any depth of the hierarchy, for example:

var child = sceneQuery.SelectOne("Parent/Intermediate1/Intermediate2/Child");
Debug.Log("Found child object: " + child.name);

10. Find objects directly under a named parent

You can also search for multiple objects that match a particular path. This example finds all children of Parent that have the name Child:

var children = sceneQuery.SelectAll("Parent/Child");
foreach (var child in children)
{
	Debug.Log("Found child object: " + child.name);
}

11. Find object in sub-hierarchy

We are getting more advanced now. Let’s delve into the Scene Query language. Here I use the > operator to find an object that is somewhere under another named object:

var child = sceneQuery.SelectOne("Parent>Child");
Debug.Log("Found child object: " + child.name);

This finds an object named Child that is somewhere, but not necessarily directly, under an object named Parent. Note that additional spaces don’t matter:

var child = sceneQuery.SelectOne("Parent > Child");

12. Find objects in sub-hierarchy

You can also use the > operator to find multiple objects somewhere under another object:

var children = sceneQuery.SelectAll("Parent>Child");
foreach (var child in children)
{
	Debug.Log("Found child object: " + child.name);
}

13. Find objects by layer or tag

You can find all objects on a particular tag or layer by using the . operator:

var pedestrians = sceneQuery.SelectAll(".Pedestrian");
foreach (var pedestrian in pedestrians)
{
	Debug.Log("Found pedestrian: " + pedestrian.name);
}

That finds all objects that are tagged with Pedestrian.

Note that you can find objects by tag in Unity, you can’t actually find objects by layer natively. The nice thing here is that you get a unified syntax for finding by both tag and layer.

14. Find object by type

Scene query wouldn’t be complete without allowing you to find objects by component type:

var pedestrian = sceneQuery.SelectOne<Pedestrian>();
Debug.Log("Found pedestrian: " + pedestrian.name);

15. Find objects by type

You can also find multiple objects by type:

var pedestrians = sceneQuery.SelectAll<Pedestrian>();
foreach (var pedestrian in pedestrians)
{
	Debug.Log("Found pedestrian: " + pedestrian.name);
}

Of course you can find one or multiple objects by type using the native Unity API, you don’t need Scene Query if that’s all you need. However what you don’t get with Unity is the ability to combine queries, something that I’ll explain soon.

Finding nested objects when you already have the parent object

Scene Query comes with a number of GameObject extension methods. This means you can call the varieties of SelectOne and SelectAll directly on a game object when you want to search the sub-hierarchy beneath that object.

For example, searching for a single sub-hierarchy object:

GameObject parentGameObject = ... some parent object ...
GameObject child = someParentObject.SelectOne("some-child");

Or searching for multiple:

GameObject parentGameObject = ... some parent object ...
var children = someParentObject.SelectAll("some-child");

You can also search a sub-hierarchy type and make use of the other advanced features that are coming up next.

Advanced Features

In the following sections I discuss the more advanced features of the Scene Query library. This is the really cool stuff.

Combining queries

Scene query allows you to combine queries. For example, searching by name and tag:

var pedestriansOnTheRoad = sceneQuery.SelectAll("Pedestrian.Road");

Can you see how it’s starting to look like CSS?

Searching by name and tag directly under a particular parent object:

var pedestriansOnTheRoadInSection1 = sceneQuery.SelectAll("Section1/Pedestrian.Road");

Or searching somewhere in a sub-hierarchy:

var pedestriansOnTheRoadInSection1 = sceneQuery.SelectAll("Section1>Pedestrian.Road");

How about all Pedestrians under objects with the Road tag:

var pedestriansOnTheRoad = sceneQuery.SelectAll(".Road > Pedestrian");

You can also add particular types to the mix. This next example finds all objects with a Pedestrian component that are somewhere under a parent object that is tagged as Road:

var pedestriansOnTheRoad = sceneQuery.SelectAll<Pedestrian>(".Road > ?.*"); 

That last one uses a partial name match, which I’ll discuss in the next section.

What if you want everthing except a particular set of game objects? You can use the ! operator to invert any query:

var everythingButPedestrians = sceneQuery.SelectAll("! .Road > Pedestrian");

There are many potential combinations of queries, This is just a taste of what’s possible.

These advanced queries also work when we already have a parent object and want to search the sub-hierarchy, for example finding non-pedestrians that are on the road:

GameObject road = ... some road game object ...
var nonPedestrians = road.SelectAll("!Pedestrian");

Partial matching and wildcards

Scene Query allows for partial name matching and the use of wildcards.

For example, say you want to find all objects that have Pedestrian in the name:

var pedestrians = sceneQuery.SelectAll("?Pedestrian");

This will find objects named Pedestrian1, Pedestrian2, Pedestrian_Fred, etc.

The ? operator enables regular expression pattern matching. You can use any regular expression to define the names of the objects to match. From the simplest match anything wild card:

 var everything = sceneQuery.SelectAll("?.*");

To much more complicated patterns:

var selectedPedestrians = sceneQuery.SelectAll("?^Pedestrian[0-9]$*");

To make sophisticated use of this you will have to learn more about regular expressions.

Partial matching and wildcards can also be used with tags and layers:

var allRoads = sceneQuery.SelectAll(".?Road");

That finds all objects that have a tag that contains Road, eg Road1, Road2, Road_X etc.

This can also be used with hierarchy paths and the > operator:

var pedestriansOnRoads = sceneQuery.SelectAll("?Road > ?Pedestrian");

That finds all objects with Pedestrian in the name that are somewhere under objects with Road in the name.

The ? operator can also be used with sub-hierarchies:

GameObject road = ... some road game object ...
var pedestrians = road.SelectAll("?Pedestrian");

Combination with scene traversal and LINQ

Scene Query functions can be used with scene traversal and LINQ functions.

This example finds all descendents of any object whose name contains Pedestrian:

var pedestrianDescendents = sceneQuery.SelectAll("?Pedestrian")
	.SelectMany(pedestrian => pedestrian.Descendents())
	.ToArray();  

This example finds all descendents and filters for those that do have a mesh:

var pedestrianMeshes = sceneQuery.SelectAll("?Pedestrian")
	.SelectMany(pedestrian => pedestrian.Descendents())
	.Where(child => child.GetComponent<MeshRenderer>() != null)
	.ToArray(); 

There is so much more you can do with by combining Scene Query, scene traversal and LINQ.

Finding objects with spaces and special characters in the name

Because the Scene Query language is a language (it even has an EBNF grammar spec) it has some problems with particular object names. For example you can’t just have an object name with a space or a question-mark as these tokens have special meaning in the query language.

To represent these kinds of names you must use quotes.

For example let’s say there is a game object with the name Pedestrian A. To query for this object we must enclose it’s name in quotes:

var pedestrian = sceneQuery.SelectOne("'Pedestrian A'");

You can use either single or double quotes, however single quotes are easier to type and clearer in this case as we can include them in the C# string literal without having to use an escape-sequence.

Note that any of the more advanced queries can still be applied:

var pedestrian = 
	sceneQuery.SelectOne("'Road X' > 'Pedestrian A'.HoldingAnApple");

Performance considerations

Querying the scene (no matter how you do it) can be very slow and it’s generally not something you want to do frequently at runtime. It’s best to execute your scene queries at start/load time and cache the results. Just be warned… if you try to do this in an update or render function you might find that your framerate slows to a crawl.

Use these techniques sparingly and at appropriate times.

Conclusion

In this article I’ve overviewed my Scene Query library and how it can be used to query the Unity hierarchy in a way similar to CSS selectors or was if the scene was some kind of database.

I’ve shown the basics of searching for objects using the native Unity API. Then I showed how Scene Query can do this but also that it has so much more to offer. Scene Query is an expressive and flexible language for pattern matching to find game objects.

Hopefully I’ve show how combining queries to specify exactly what you are searching for can be such a powerful technique.

Thanks for reading.

Добавить комментарий