Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by AttentionHorse · Jan 30, 2019 at 03:56 PM · 2d gamegameobjectstagsclosest

Spawn a prefab at the closest GameObject with one of four relevant tags.

I have 4 different tags that I add to a list to know possible spawn locations for my object.

  public List<GameObject>  locationsToSpawn = new List<GameObject>();
  locationsToSpawn.AddRange(GameObject.FindGameObjectsWithTag("tag1"));
  locationsToSpawn.AddRange (GameObject.FindGameObjectsWithTag("tag2")); 
  locationsToSpawn.AddRange(GameObject.FindGameObjectsWithTag("tag3")); 
  locationsToSpawn.AddRange(GameObject.FindGameObjectsWithTag("tag4"));

I want to spawn an new object on the edge of the GameObject in the scene that is closest to my click.

 if (Input.GetMouseButtonDown(0)) 
 { 
     clickPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition); 
     closestObject(); 
     if(closest.tag == "tag1")
     { 
         objectSpawnPosition = closest.transform.position; 
         GameObject objectInstance = Instantiate(spawnUpPrefab, objectSpawnPosition, Quaternion.Euler(new Vector3(0, 0, 0))); 
     } 
     //repeated for the 3 other tags.
 }

This is how I find the closest object (largely stolen from unity documentation)

 public GameObject closestObject()
 {
     float distance = Mathf.Infinity;
     foreach (GameObject go in locationsToSpawn)
     {
         Vector3 diff = go.transform.position - clickPosition;
         float curDistance = diff.sqrMagnitude;
         if (curDistance < distance)
         {
               closest = go;
               distance = curDistance;
         }
     }
 return closest;
 }

I have two major problems. It doesn't always spawn on the closest object, almost ignores tag1 even when pressing directly on that object when one of the others are nearby. Also, I can't figure out how to properly spawn on the edge, as of now I use objectSpawnPosition.y = closest.transform.position.y + A.BCf; to correct the positioning but I feel like there should be a more effective or more precise way.

Thank you!

Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image KISP · Jan 30, 2019 at 05:35 PM 0
Share

You declare the variable "objectSpawnPosition" but you don't use it in the Instantiate call. Where are you using it?

avatar image AttentionHorse KISP · Jan 31, 2019 at 11:22 AM 0
Share

Now that's fixed. Just an error from when I rewrote the names to be more clear when asking for help.

1 Reply

· Add your reply
  • Sort: 
avatar image
1

Answer by Bonfire-Boy · Jan 31, 2019 at 12:19 PM

You're not resetting the distance variable (to eg float.MaxValue) at the start of your search. As a result, your function is not searching for the currently closest location to clickPosition, but for the location that clickPosition has been closest to at some point in time.

To see the effect of not resetting it: imagine that on the first search, you find that the position of clickPositionis identical to that of one of the spawn locations. distance will become set to zero and so, on subsequent searches, (curDistance < distance) will never be true. So subsequent searches will never change the value of closest, regardless of where the clickPosition is.

It's not clear why distance is a member field (assuming it is, you haven't shown us its declaration)... I would normally use a local variable to keep track of the "closest value found so far" in this situation (and then if it's needed outside the function, make that happen at the end of the search). Similarly, why does the function use the non-local closest at all? Better to keep the logic of the search function local. If instead you'd written it this way...

 public GameObject closestObject()
  {
      GameObject closestObjectSoFar = null;
      float closestDistanceSoFar = float.MaxValue;
      foreach (GameObject go in locationsToSpawn)
      {
          Vector3 diff = go.transform.position - clickPosition;
          float curDistance = Mathf.Abs(diff.sqrMagnitude);
          if (curDistance < closestDistanceSoFar )
          {
              closestObjectSoFar = go;
              closestDistanceSoFar = curDistance;
          }
      }
      return closestObjectSoFar ;
  }

And used it this way...

 closest = closestObject(); 
 if (closest == null)
 {
 // throw exception, log error, etc...  
 }

Then you'd have picked up straight away on the fact that your search function is failing.

Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bonfire-Boy · Jan 31, 2019 at 12:22 PM 0
Share

And a $$anonymous$$or point... you don't need to take the absolute value of a squared magnitude.

avatar image AttentionHorse · Jan 31, 2019 at 01:41 PM 0
Share

Yes, I missed including my "float distance = $$anonymous$$athf.Infinity". Now that's included. Thanks for trying to help me with that. The problem isn't really that the search function is failing all the time, it's just not precise enough. I did try your approach though, and as you've set "closestDistanceSoFar = curDistance;" in a "if (curDistance < closestDistanceSoFar )" so it just finds an element once (the incorrect one) and then never changes. I tried correcting this but it did not improve my results unfortunately.

avatar image Bonfire-Boy AttentionHorse · Jan 31, 2019 at 01:55 PM 0
Share

Your comment has made me realise that I'd put go where I should have put clickPosition in my description. I've corrected that. I can't quite see what you mean about the logic, though... closestDistanceSoFar is keeping track of the closest distance so far, so when it's greater than the current distance (that of the spawn location currently being looked at), you do want to update it. I've not tested the code so I can't 100% rule out the possibility that I've got a blind spot.

avatar image AttentionHorse Bonfire-Boy · Jan 31, 2019 at 02:52 PM 0
Share

When reading through your code again I'm not sure what I was referring to either tbh. I think I just made an assumption from the behaviour I encountered when testing your code. No matter where I clicked it would just continue spawning at the gameobject it spawned the first prefab on, not one of the closest ones, but I can't figure out why that would happen.

The code I have now has decent precision sometimes and sometimes it just picks the tag that is 5cm away ins$$anonymous$$d of the one that is 0.5cm away.

Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

116 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How can I detect multiple triggers on same gameobject at once? 3 Answers

Unity3D Shooter: Using tags to switch level after killing all enemies. 1 Answer

Make different sounds play depending on which item collides with player 0 Answers

Collider2D and Z-Axis 0 Answers

How do i destroy a particle when an object is destroyed 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges