Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 11 Next capture
2021 2022 2023
1 capture
11 Jun 22 - 11 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 B4ttleCat · Jul 22, 2015 at 03:29 PM · c#positionarrays

[C#] Check position of multiple GameObjects with mouse click position

Hey guys,

I'm really new to programming and I've been bashing my head against the wall with this. I've searched for existing questions/answers but seeing as I don't fully understand this, they're of very little help as I get errors I have no idea how to fix.

The goal: (Imagine a Plants vs Zombies style game) When placing a defender, first check to see if there's already a defender in that square. If not, place a defender. If so, communicate that it's not allowed.

My question: How do I store the positions of the objects in the placedDefenders array and then check them against the position of the mouse click (roundedPos)?

I have the GameObject array working properly, but then figuring out how to get the positions of those objects is where I come undone (let alone checking them against the mouse click position).

Here's my script, I've deleted all the crud where I was trying to store the positions in another array because it was getting very sloppy. I hope it makes sense.

I appreciate any help.

 using UnityEngine;
 using System.Collections;
 
 public class DefenderSpawner : MonoBehaviour {
 
     Camera myCamera;
     GameObject defenderParent;
 
     void Start () {
         myCamera = Camera.main;
         defenderParent = GameObject.Find ("Defenders");
         
         if (defenderParent == null) {
             defenderParent = new GameObject ("Defenders");
         }
     }
 
     void OnMouseDown () {
         // Coordinate stuff
         Vector2 rawPos = CalculateWorldPointOfMouseClick ();
         Vector2 roundedPos = SnapToGrid (rawPos);
 
         // Arrays for placement checking
         Vector3[] placedDefenderPositions;
         GameObject[] placedDefenders;
 
         placedDefenders = GameObject.FindGameObjectsWithTag ("Defender");
 
         // Instantiate Defender and parent it in hierarchy
         GameObject defender = Instantiate (Button.selectedDefender, roundedPos, Quaternion.identity) as GameObject;
         defender.transform.parent = defenderParent.transform;
     }
 
     Vector2 SnapToGrid (Vector2 rawWorldPos) {
         float newX = Mathf.RoundToInt (rawWorldPos.x);
         float newY = Mathf.RoundToInt (rawWorldPos.y);
 
         return new Vector2 (newX, newY);
     }
 
     Vector2 CalculateWorldPointOfMouseClick () {
         float mouseX = Input.mousePosition.x;
         float mouseY = Input.mousePosition.y;
         float distanceFromCamera = 10f;
 
         Vector3 cameraPoints = new Vector3 (mouseX, mouseY, distanceFromCamera);
         Vector2 worldPos = myCamera.ScreenToWorldPoint (cameraPoints);
 
         return worldPos;
     }
 }

Comment
Add comment
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

1 Reply

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by alexi123454 · Jul 22, 2015 at 03:37 PM

You can get the position of any gameObject in Unity by calling theGameObject.transform.position. This gives you the world-space position of the object. You could check them against the mouse position by doing a for loop like so:

 for (int i=0;i<placedDefenders.Length;i++)
 {
      Vector3 objectPosition = placedDefenders[i].transform.position;
      Vector2 objectPosition2D = new Vector2(objectPosition.x, objectPosition.y);
      
      if (SnapToGrid(objectPosition2D) == roundedPos)
      {
           //One of the defenders is in this spot!
           NotifyPlayerFunction();
           break;
      }
 }
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 B4ttleCat · Jul 23, 2015 at 01:29 AM 0
Share

Thank you very much for the reply, alexi123454. I didn't know how to convert the Vector3 to the Vector2 and the roundedPos check makes sense to me in seeing it, but I wouldn't have been able to come up with that myself.

Below is my updated On$$anonymous$$ouseDown method. I've just added debug logs to figure out how it works and while it logs out correctly, it's still placing the defender in an occupied spot. If I move the instantiate code into the for loop it doesn't log anything or spawn the defender, either way. I tried adding the instantiate code to an else statement but that didn't work either. I suspect it's to do with me not understanding how a break works. Would you $$anonymous$$d explaining where I would instantiate the defender, please?

     void On$$anonymous$$ouseDown () {
         // Coordinate stuff
         Vector2 rawPos = CalculateWorldPointOf$$anonymous$$ouseClick ();
         Vector2 roundedPos = SnapToGrid (rawPos);
 
         // Arrays for placement checking
         GameObject[] placedDefenders;
         placedDefenders = GameObject.FindGameObjectsWithTag ("Defender");
 
         for (int i=0; i<placedDefenders.Length; i++) {
             Vector3 objectPosition = placedDefenders [i].transform.position;
             Vector2 objectPosition2D = new Vector2 (objectPosition.x, objectPosition.y);
             
             if (SnapToGrid (objectPosition2D) == roundedPos) {
                 //One of the defenders is in this spot!
                 //NotifyPlayerFunction();
                 Debug.Log ("Placement is bad");
                 break;
             }
         }
         // Instantiate Defender and parent it in hierarchy        
         GameObject defender = Instantiate (Button.selectedDefender, roundedPos, Quaternion.identity) as GameObject;
         defender.transform.parent = defenderParent.transform;
         Debug.Log ("Placement is fine");
     }


avatar image alexi123454 · Jul 23, 2015 at 01:40 AM 1
Share

Break is just a keyword that will break out of any loop that the program is currently in. In the case of the code I wrote for you, the break statement would exit the for loop after an object has been found, meaning it doesn't have to check the rest of the objects.

The reason your code is still spawning the defender in the occupied spot is because, even after it finds that the placement is bad, the function continues along, and still spawns the defender afterward.

The easiest way to solve this would be to replace "break;" with "return;". This will cause the function to stop, rather than just the for loop, meaning that if an object is found it the spot, the program will never actually get to the point where the defender is spawned.

avatar image alexi123454 · Jul 23, 2015 at 01:48 AM 1
Share

For the sake of clean code, I would also split up some of the stuff that you function is doing. Try something like this:

 void On$$anonymous$$ouseDown () 
 {
          // Coordinate stuff
          Vector2 rawPos = CalculateWorldPointOf$$anonymous$$ouseClick ();
          Vector2 roundedPos = SnapToGrid (rawPos);
  
          // Arrays for placement checking
          GameObject[] placedDefenders;
          placedDefenders = GameObject.FindGameObjectsWithTag ("Defender");
  
          for (int i=0; i<placedDefenders.Length; i++) 
          {
              Vector3 objectPosition = placedDefenders [i].transform.position;
              Vector2 objectPosition2D = new Vector2 (objectPosition.x, objectPosition.y);
              
              if (SnapToGrid (objectPosition2D) == roundedPos) 
              {
                  BadPlacement();
                  return;
              }
          }
          GoodPlacement();
      }
 
 void BadPlacement()
 {
     Debug.log("Placement is bad");
 }
 
 void GoodPlacement(Vector2 aPosition)
 {
     Debug.log("Placement is good");
     GameObject defender = (GameObject)Instantiate(Button.selectedDefender, aPosition, Quaternion.identity);
     defender.transform.parent = defenderParent.transform;
 }


Generally, it's a good idea to make a function only do one thing. This way, you have one function to do the position check, and then one function to handle the spawning of the object. This also allows you to put different functionality easily (if you want to pop up a text box saying "Hey, you can't put a defender there!" or something like that).

avatar image B4ttleCat · Jul 23, 2015 at 03:53 AM 0
Share

Thank you very much for the effort and explanations. After passing roundedPos into GoodPlacement() it works perfectly.

I really appreciate the time you took to not only solve my issue but make everything clear as well.

avatar image B4ttleCat · Jul 23, 2015 at 03:58 AM 0
Share

Just out of curiosity, is it possible to only mark your most recent reply as the answer?

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

3 People are following this question.

avatar image avatar image avatar image

Related Questions

Multiple Cars not working 1 Answer

Distribute terrain in zones 3 Answers

How do I smoothly sync players position over the network in Unity3D(UNet) without bugs? 0 Answers

Locating proper gameObject to which player has to jump 1 Answer

How to get the position that is closest to a target within a given radius 0 Answers


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