• 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 corporate_snack · Mar 16, 2013 at 07:52 AM · javascriptarraytagfor-loopiterate

"For"-Loop only works for final element in array

Update: After playing around with it a little, I discovered that the script seems to only work for the last element in the array. I put three blocks into the array, and even when I switched around their order, whichever one was the third element in the array would be impassible, and the others could be moved through. I still have no clue what the cause of this is.

I also moved the line...

walls = GameObject.FindGameObjectsWithTag("wall");

...into a Start() function, as some comments recommended. This doesn't seem to have changed anything, but I understand why it's better this way. Thanks in advance for any help.

Original Question:

I'm having problems with a For Loop I'm using in a custom "collision" system. I put that word in quotes because I'm implementing kind of grid-based movement, and I'm not using any physics. In my game, I have one "player" block (with dimensions 1x1x1) and multiple "wall" blocks (also with dimensions 1x1x1). The "wall" blocks are static, and the "player" block moves around by increments of 1 unit. Below, I've provided some code I wrote that detects whether the "player" block is next to a "wall" block, and sets a flag that won't allow the "player" block to move in that direction when the arrow key is pressed.

When I have one "wall" block in a scene, the script works fine, and the "player" block cannot move through it. I wanted to have more than one "wall" block, though -- in fact, I want to be able to place as many as I want and have the code apply to them automatically -- so I edited the code to iterate through all instances of "wall" blocks when determining if the "player" block was next to one. To do this, I added a "wall" tag to my "wall" block prefab, and made an array that includes all objects with that tag. This part seems to work fine -- when I start up the game, I can see all the "wall" blocks listed in the array, so they have all been detected successfully.

The problem is this: When there is more than one "wall" block in a scene, only the first "wall" block is impassible. There is no discernable difference between two "wall" blocks aside from their position, and both have the "wall" tag that includes them in the array -- which is being iterated through -- so I thought that both would be impassible. However, while the "player" block cannot move through one "wall" block, the other one allows the "player" to move straight through it, as if the code is ignoring any more than one object.

The full code is below. Any help is much appreciated!

 #pragma strict
 
 var player : Transform;
 var speed : float = 5;
 var walls : GameObject[];
 
 var right_move = true;
 var left_move = true;
 var up_move = true;
 var down_move = true;

 function Start() {

         walls = GameObject.FindGameObjectsWithTag("wall");

 }

 function Update() {

 //All this determines whether or not the "player" block is on any side of a "wall"
 //block and sets respective variables to false if it is.

     for (var wall : GameObject in walls) {
         
         if (player.position.x + 1 == wall.transform.position.x
             && player.position.z == wall.transform.position.z)
                 right_move = false;
         else right_move = true;
         
         if (player.position.x - 1 == wall.transform.position.x
             && player.position.z == wall.transform.position.z)
                 left_move = false;
         else left_move = true;
         
         if (player.position.z + 1 == wall.transform.position.z
             && player.position.x == wall.transform.position.x)
                 up_move = false;
         else up_move = true;
         
         if (player.position.z - 1 == wall.transform.position.z
             && player.position.x == wall.transform.position.x)
                 down_move = false;
         else down_move = true;
     
     }
 }    
 
 while(true) yield CoUpdate();
  
 function CoUpdate() {
 
     if (Input.GetKey(KeyCode.RightArrow)
         && right_move == true)
             yield Move(Vector3.right);
                         
     if (Input.GetKey(KeyCode.LeftArrow)
         && left_move == true)
             yield Move(Vector3.left);
                     
     if (Input.GetKey(KeyCode.UpArrow)
         && up_move == true)
             yield Move(Vector3.forward);
     
     if (Input.GetKey(KeyCode.DownArrow)
         && down_move == true)
             yield Move(Vector3.back);
                     
     else 
         yield;
 
 }
  
 function Move(distance : Vector3) {
     var pt = player.transform;
     var goal = pt.position + distance;
     while (pt.position != goal) {
         pt.position = Vector3.MoveTowards(pt.position, goal, speed * Time.deltaTime);
         yield;
     }
 }
Comment
Add comment · Show 3
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 robertbu · Mar 16, 2013 at 08:03 AM 0
Share

Print out the length of 'walls' to make absolutely certain that all the walls objects are in the list. If you are creating it in code, you need to make sure of he order the scripts are executing in order for FindGameObjectsWithTag() to find all of the walls.

avatar image Kleptomaniac · Mar 16, 2013 at 01:29 PM 0
Share

As @robertbu said, watch your execution order. You are filling your array outside of any local scope, which I'm pretty sure equates to when the script initialises or Awake() (I believe). Some of the GameObjects you are trying to fill your array with may not exist yet. Trying putting your FindGameObjectsWithTag() method in Start(). :)

avatar image corporate_snack · Mar 16, 2013 at 04:10 PM 0
Share

Thanks for the responses. I tried moving walls = GameObject.FindGameObjectsWithTag("wall"); into Start(), and even into Update(), but in both situations, only one "wall" block was impassible, and the other seemed to be ignored.

When I playtest the scene, I can keep the "player" object (which has the script on it) in the inspector, and I see the "size" of the walls array increase to whatever number of "wall" blocks I have, so I'm pretty sure it's filling the array. It seems like the problem is with the loop itself...

1 Reply

· Add your reply
  • Sort: 
avatar image
0

Answer by whydoidoit · Mar 17, 2013 at 07:25 AM

Well you are comparing floats using an == operator when you check the positions .x .y and .z

Floating points can be compared to 0, but many other values will not be accurate enough for a == test.

The normal approach it to take number a from number b and compare it with a very small value:

   if((player.position.z - 1 - wall.transform.position.z) < 0.0001f) { //Do something }
   
Comment
Add comment · Show 3 · 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 corporate_snack · Mar 17, 2013 at 09:23 PM 0
Share

Thanks for posting. I made these changes you mentioned, and while they produced (what I assume is) more robust accuracy in making the "wall" blocks impassible, still only one of the "wall" blocks was affected by the code, and the others could be moved straight through -- and again it was the last block in the array that was impassible. I believe the problem may be in the construction of the loop itself, but I can't imagine what it could be.

avatar image whydoidoit · Mar 17, 2013 at 10:39 PM 0
Share

The way you are going about this is certainly odd - especially given the accuracy of floats.

You would be better off storing your position in integers and then converting it to a Vector3 to display the objects if you want to use ifs like that.

You could also try using $$anonymous$$athf.RoundToInt() on each of the coordinates...

avatar image corporate_snack · Mar 17, 2013 at 10:46 PM 0
Share

Thanks, I'll try that stuff out! For the record, I'm pretty new to program$$anonymous$$g and to Unity, so if something I do seems odd, it's probably because it's the only way I know how to do it! If there's a better way to get the same results ("wall" blocks being impassible) then I'd love to hear it.

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.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

12 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

Related Questions

Turn all objects in the array to make same thing 0 Answers

Check whether all game objects with a tag have been destroyed 2 Answers

Loop Through Entire Array - Simon Game 1 Answer

Tower defense, turret aiming wrong. 1 Answer

have array target person of most priority/stick with top prior 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