Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 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 KHodow · Jan 21 at 04:18 PM · coroutinetransform.position

My code works but only with a waitforseconds() in a coroutine

Hi all, I'm currently makin a 2d chess game and I am trying to eliminate illegal moves from the highlighted tiles. The problem occurs when I want to make it so that pinned pieces (pieces where if they move the king will be under attack) moving is illegal.

To make these types of illegal moves I wrote code so that it will temporarily set the piece transform.position to each of the possible moves and test if the king is under attack. (The code is below) For pieces with only a few tiles to check it does this somewhat accurately, but with pieces with a lot of tiles to check like the queen, the "check if king is in danger" method seems to not work entirely.

The "check if king is in danger" method does work 100% since I checked after each turn and it consistently answered correctly if the king were in danger.

I then suspected that it can't handle checking each move with the "king in danger function" and thus labels each move as possible so I added everything to a coroutine and added a waitforseconds() of 0.1f seconds per move and now the code works.

However before highlighting available moves the piece visually moves around to each of the positions before showing possible moves, which doesn't exactly look appealing... I was wondering if there is anything I could do to make it efficient enough to check for illegal moves without the wait function?

 private void OnMouseDown()
     {
 
         if (selected)
         {
             selected = false;
             gm.selectedUnit = null;
             gm.ResetTiles();
 
             transform.localScale = new Vector3(flip * 1f, 1f);
         }
         else
         {
             transform.localScale = new Vector3(flip * 1.25f, 1.25f);
             if (playerNumber == gm.playerTurn)
             {
                 if (gm.selectedUnit != null)
                 {
                     gm.selectedUnit.selected = false;
                 }
                 selected = true;
                 gm.selectedUnit = this;
                 gm.ResetTiles();
                 eliminateIllegalMoves(playerNumber, GetWalkableTiles());
             }
         }
         tileUnder = GetTileBelow();
         tileUnder.OnMouseDown();
     }
 
 public void allPossibleMoves(int side)
     {
         foreach (Unit unit in FindObjectsOfType<Unit>())
         {
             if (unit.playerNumber == side)
             {
                 foreach (Tile tile in unit.GetWalkableTiles())
                 {
                     tile.isAttacked = true;
                 }
             }
         }
     }
 
 public bool isKingInDanger(int whichPlayer)
     {
         foreach(Tile tile in FindObjectsOfType<Tile>())
         {
             tile.isAttacked = false;
         }
         int enemyNumber;
         if (whichPlayer == 1)
         {
             enemyNumber = 2;
         }
         else
         {
             enemyNumber = 1;
         }
         allPossibleMoves(enemyNumber);
         foreach (Unit possibleKing in FindObjectsOfType<Unit>())
         {
             if (possibleKing.pieceType == 1 && possibleKing.playerNumber == whichPlayer)
             {
                 if (possibleKing.GetTileBelow().isAttacked)
                 {
                     return true;
                 }
                 else
                 {
                     return false;
                 }
             }
         }
         return false;
     }
 
 public List<Tile> eliminateIllegalMoves(int whichPlayer, List<Tile> allMoves)
     {
         legalMoves = new List<Tile>();
         StartCoroutine(eraseMoves(whichPlayer, allMoves));
         return legalMoves;
     }
 
 IEnumerator eraseMoves(int whichPlayer, List<Tile> allMoves)
     {
         Vector3 temp = transform.position;
         foreach (Tile tile in allMoves)
         {
             tile.isLegal = true;
             transform.position = tile.transform.position;
             //yield return new WaitForSeconds(0.1f);
             if (isKingInDanger(whichPlayer))
             {
                 tile.isLegal = false;
             }
             if (tile.isLegal)
             {
                 legalMoves.Add(tile);
             }
         }
         transform.position = temp;
         HighlightWalkableTiles(legalMoves);
         yield return null;
     }

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
1

Answer by Captain_Pineapple · Jan 21 at 05:56 PM

Hey there,

i cannot really see a direct way how to solve this issue but can offer a long term solution anyway:

this is a point in your development where you should take 5 steps back and rework some stuff.

Why? Because you should not be dependant on actually moving parts to check if a piece is checked or not. You should be able to just "simulate" this. Basically the best way would be to have the chess logic that only exists in non-monobehaviours and unitys only part is to take input, trigger functions in your chess logic and at the end of all calculations to display the visuals.


Why is that so important? Multiple reasons. Your current system is horrible on performance. You have a loop in line 87 that calls a function where each iteration calls 2 instances of FindObjectsOfType (which should be avoided in general, but is ok in Start functions) where each time the same objects are beeing searched.

your current system with your coroutine gives 1 frame of possibility in which an impossible move might be executed when someone clicks reaaaaally fast.


In general i'd strongly suggest you rebuild some systems to simply eleminate your problem by a rework. When you do this you should also read into enum as you can create something like this:

  enum Pieces { King, Queen, Pawn .....} 

so that in your code you don't have to have int piecetype = 1 where noone knows what it actually is but you can say Pieces piecetype = Pieces.King; and check for a type with if(piecetype == Pieces.Pawn) for example.

On top of that your logic should be (as already pointed out) based on functions which take objects with 2D Vectors as positions that are not monobehaviours so your don't have to actually set transform positions.

Comment
Add comment · Show 4 · 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 KHodow · Jan 21 at 06:52 PM 0
Share

Thanks so much for your reply! I'm still new to this so your feedback is really helpful! So what I'm should do is create a separate script that simulates the chessboard and checks for moves and all that and only use the unity gameobjects as actors for that simulated chessboard once a user makes a move?

avatar image Captain_Pineapple KHodow · Jan 21 at 09:11 PM 1
Share

I think you understood what i tried to describe in my post yes. In the end your current logic already does something similar. You have some objects with a variable position which you take and then calculate some things based on the position of all objects.


So by taking Unity out of this you can speed things up, make them testable and more slim in general.

I like how your put it with "unity gameobjects as actors". That is just perfect.


As an addition for my answer: An enum can also be used perfectly to encapsulate the player you are currently talking about. (e.g enum PlayerColor {White, Black} - you get the idea)

avatar image Captain_Pineapple KHodow · Jan 21 at 09:23 PM 1
Share

As a nifty little thing that might intrest you is this:

if for example you create an enum for the playercolors black and white:

  enum PlayerColor {White, Black};

you can add an extension method for the PlayerColor enum like this to get the other player color in one line wherever you want:

 public static class PlayerColorExtensions
 {
     public static PlayerColor OtherPlayer(this PlayerColor thisPlayer)
     {
         if(thisPlayer == PlayerColor.White)
             return PlayerColor.Black;
         return PlayerColor.White;
     }
 }

so when you have a variable that is defined like this:

  PlayerColor playerColorOfThisPiece;

then you can get the other color by:

  var otherColor = playerColorOfThisPiece.OtherPlayer();

Not tested but should work. You may scold me for talking s**t if it doesn't :)

avatar image KHodow Captain_Pineapple · Jan 23 at 06:25 PM 0
Share

Thanks! I'll give it a try!

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

143 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 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

Transform Object over Players head before destroying 0 Answers

object's children not moving with it when using a Lerp-ing coroutine 0 Answers

coroutine in update method 1 Answer

Coroutine - transform for every frame for duration? 0 Answers

How does Invoke cope with mapping on frames 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