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 K4nickel · Jul 31, 2019 at 10:43 PM · movement scriptforeach

Foreach Board Game Movement Bug

To make it short I am really exhausted from trying to fix it, I am trying to create my own movement system. I have some white sprites as tiles for my player to move on with a distance of 3 between them and my player which is the black sprite. In the bottom right there is a controller to move the player, but you can only move in a direction if a tile lies there. But my code doesn't work and only lets me go up at one specific tile, the one that lies at y = 0. Here is my code and a screenshot, I hope you can help me, I will go to sleep now .-.

 ![{
     Vector3 moveX = new Vector3(3.0f,0,0);
     Vector3 moveY = new Vector3(0,3.0f,0);
 
     GameObject[] tiles;
 
     public void MoveUp()
     {
         GameObject.Find("Player1").transform.position += moveY;
         CheckTiles();
     }
 
     public void MoveDown()
     {
         GameObject.Find("Player1").transform.position -= moveY;
         CheckTiles();
     }
 
     public void MoveLeft()
     {
         GameObject.Find("Player1").transform.position -= moveX;
         CheckTiles();
     }
 
     public void MoveRight()
     {
         GameObject.Find("Player1").transform.position += moveX;
         CheckTiles();
     }
 
     void Start()
     {
         tiles = GameObject.FindGameObjectsWithTag("tile");
         CheckTiles();
     }
 
     public void CheckTiles()
     {
         foreach (GameObject go in tiles)
         {
             if ((go.transform.position.y <= (GameObject.Find("Player1").transform.position.y + 4)) && (go.transform.position.y >= (GameObject.Find("Player1").transform.position.y + 2)))
             {
                 GameObject.Find("MoveUp").GetComponent<Button>().interactable = true;
             }
             else
             {
                 GameObject.Find("MoveUp").GetComponent<Button>().interactable = false;
             }
         }][1]


[1]: /storage/temp/143839-foreachbug.png

foreachbug.png (7.3 kB)
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
0
Best Answer

Answer by SirPaddow · Aug 01, 2019 at 12:40 AM

The problem is that you assign the value inside the foreach, meaning that you are in fact assigning true or false depending only on the last item of the foreach. What you want in fact is "If it's true for at least one tile, I want it the button to be interactable".

Something like this should work better:

     public void CheckTiles()
     {
         bool enableMoveUp = false;
         foreach (GameObject go in tiles)
         {
             if ((go.transform.position.y <= (GameObject.Find("Player1").transform.position.y + 4)) && (go.transform.position.y >= (GameObject.Find("Player1").transform.position.y + 2)))
             {
                 enableMoveUp = true;
             }
         }
         GameObject.Find("MoveUp").GetComponent<Button>().interactable = enableMoveUp;
     }

Unrelated advice:

  • you should really try to avoid this "Find" function all the time. Can't you have a Player attribute in your class, as you did for the tiles?

  • it would probably be more efficient and more intuitive to keep a table for your board, and compare indexes rather than world positions.

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 K4nickel · Aug 01, 2019 at 12:51 AM 0
Share

Sounds logical to me, I will try it out later but it should work, thanks. And yes I will also add a Player attribute and I am not really a Unity pro, I know what a table is and all but how exactly would it work with my board game?

avatar image K4nickel K4nickel · Aug 01, 2019 at 01:02 AM 0
Share

Okay never$$anonymous$$d, I got how you meant it and I think I will actually do it. Thanks for you help :D

avatar image SirPaddow K4nickel · Aug 01, 2019 at 01:29 AM 0
Share

I didn't test it, but here is how I would imagine the code, assu$$anonymous$$g the bottom left tile (empty or not) of your grid is positionned at [0, 0] :

 private const float tilingDistance = 3;
 
     private Transform player;
     private Transform[,] tiles;
     private Button moveUpButton;
     private Button moveRightButton;
     private Button moveLeftButton;
     private Button moveDownButton;
 
     private Vector2Int playerCoordinates;
 
     public void Start()
     {
         BuildTileGrid();
         player = GameObject.Find("Player1").transform;
         playerCoordinates = new Vector2Int((int)(player.position.x / tilingDistance), (int)(player.position.y / tilingDistance));
         moveUpButton = GameObject.Find("$$anonymous$$oveUp").GetComponent<Button>();
         moveRightButton = GameObject.Find("$$anonymous$$oveRight").GetComponent<Button>();
         moveLeftButton = GameObject.Find("$$anonymous$$oveLeft").GetComponent<Button>();
         moveDownButton = GameObject.Find("$$anonymous$$oveDown").GetComponent<Button>();
     }
 
     private void BuildTileGrid()
     {
         GameObject[] tiles = GameObject.FindGameObjectsWithTag("tile");
         float maxTileX = 0;
         float maxTileY = 0;
         foreach (GameObject tile in tiles)
         {
             if (tile.transform.position.x > maxTileX) maxTileX = tile.transform.position.x;
             if (tile.transform.position.y > maxTileY) maxTileY = tile.transform.position.y;
         }
         this.tiles = new Transform[(int)(maxTileX / tilingDistance) + 1, (int)(maxTileY / tilingDistance) + 1];
         foreach (GameObject tile in tiles)
         {
             this.tiles[(int)(tile.transform.position.x / tilingDistance), (int)(tile.transform.position.y / tilingDistance)] = tile.transform;
         }
     }
 
     public void $$anonymous$$oveUp() { $$anonymous$$ove(0, 1); }
     public void $$anonymous$$oveDown() { $$anonymous$$ove(0, -1); }
     public void $$anonymous$$oveLeft() { $$anonymous$$ove(-1, 0); }
     public void $$anonymous$$oveRight() { $$anonymous$$ove(1, 0); }
     private void $$anonymous$$ove(int diffX, int diffY)
     {
         playerCoordinates += new Vector2Int(diffX, diffY);
         player.position = tiles[playerCoordinates.x, playerCoordinates.y].position;
         CheckTiles();
     }
 
     public void CheckTiles()
     {
         moveUpButton.interactable = playerCoordinates.y < tiles.GetLength(1) - 1 && tiles[playerCoordinates.x, playerCoordinates.y + 1] != null;
         moveDownButton.interactable = playerCoordinates.y > 0 && tiles[playerCoordinates.x, playerCoordinates.y - 1] != null;
         moveRightButton.interactable = playerCoordinates.x < tiles.GetLength(0) - 1 && tiles[playerCoordinates.x + 1, playerCoordinates.y] != null;
         moveLeftButton.interactable = playerCoordinates.y > 0 && tiles[playerCoordinates.x - 1, playerCoordinates.y] != null;
     }

The main difference is the BuildTileGrid function. In it, ins$$anonymous$$d of only keeping the list of tiles, I insert the tiles in a table. Where there is no tile, the table cell remains empty. Then, in the CheckTiles, all I need to do is to check around the position of the player, if the table cell is empty or not.

I hope it will help :)

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

111 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

Related Questions

Using Mathf.SmoothDamp() in a foreach loop 1 Answer

Not able to make a foreach loop 2 Answers

Access all variables of type within a C# script 2 Answers

foreach a array inside a generic list 1 Answer

Keeping one enemy object active at a time 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