Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question Pawn not moving on a board game

Discussion in 'Scripting' started by Bakaando, Oct 2, 2022.

  1. Bakaando

    Bakaando

    Joined:
    Sep 17, 2022
    Posts:
    6
    I have a board game project in unity, where six players roll a dice, and go forward using a waypoint system on a really basic board game (2d). I found some code on YouTube, and adapted it to my project. everything goes pretty well, except for the fact that the pawns don't move forward. They set correctly to the first waypoint, they are selected to move, but don't. I suspect that my transform.position don't work, but I can't understand why. I'm really new to c# and unity, so I can't find the problem. Here is my pawn movement code :

    Code (CSharp):
    1. using System.Collections;
    2.  
    3. using System.Collections.Generic; using UnityEngine;
    4.  
    5. public class FollowThePath : MonoBehaviour {
    6.  
    7. public Transform[] waypoints;
    8.  
    9. [SerializeField]
    10. private float moveSpeed = 1f;
    11.  
    12. [HideInInspector]
    13. public int waypointIndex = 0;
    14.  
    15. public bool moveAllowed = false;
    16.  
    17. // Start is called before the first frame update
    18. private void Start()
    19. {
    20.    transform.position = waypoints[waypointIndex].transform.position;
    21. }
    22.  
    23. // Update is called once per frame
    24. private void Update()
    25. {
    26.    if (moveAllowed)
    27.        Move();
    28. }
    29.  
    30.  
    31. private void Move(){
    32.    if (waypointIndex <= waypoints.Length -1)
    33.    {
    34.        transform.position = Vector2.MoveTowards(transform.position,
    35.        waypoints[waypointIndex].transform.position,
    36.        moveSpeed * Time.deltaTime);
    37.        Debug.Log(transform.position);
    38.  
    39.        if (transform.position == waypoints[waypointIndex].transform.position)
    40.        {
    41.            waypointIndex += 1;
    42.        }
    43.    }
    44. }
    45.  
    46. }
    47.  
    I Think the problem is at the end of this script.
    I also have a dice script :

    Code (CSharp):
    1. using System.Collections;
    2.  
    3. using UnityEngine;
    4.  
    5. public class Dice : MonoBehaviour {
    6.  
    7. // Array of dice sides sprites to load from Resources folder
    8. private Sprite[] diceSides;
    9.  
    10. // Reference to sprite renderer to change sprites
    11. private SpriteRenderer rend;
    12.  
    13. // Select the player's turn
    14. private int whosturn = 1;
    15.  
    16. //Check if we can roll the dice
    17. private bool coroutineallowed = true;
    18.  
    19. // Use this for initialization
    20. private void Start () {
    21.  
    22.    // Assign Renderer component
    23.    rend = GetComponent<SpriteRenderer>();
    24.  
    25.    // Load dice sides sprites to array from DiceSides subfolder of Resources folder
    26.    diceSides = Resources.LoadAll<Sprite>("DiceSides/");
    27. }
    28.  
    29. // If you left click over the dice then RollTheDice coroutine is started
    30. private void OnMouseDown()
    31. {
    32.    if (!GameControl.gameOver && coroutineallowed)
    33.    StartCoroutine("RollTheDice");
    34. }
    35.  
    36. // Coroutine that rolls the dice
    37. private IEnumerator RollTheDice()
    38. {
    39.    // Turn coroutineallowed off
    40.  
    41.    coroutineallowed = false;
    42.    // Variable to contain random dice side number.
    43.    // It needs to be assigned. Let it be 0 initially
    44.    int randomDiceSide = 0;
    45.  
    46.    // Loop to switch dice sides ramdomly
    47.    // before final side appears. 10 itterations here.
    48.    for (int i = 0; i <= 10; i++)
    49.    {
    50.        // Pick up random value from 0 to 5 (All inclusive)
    51.        randomDiceSide = Random.Range(0, 6);
    52.  
    53.        // Set sprite to upper face of dice from array according to random value
    54.        rend.sprite = diceSides[randomDiceSide];
    55.  
    56.        // Pause before next itteration
    57.        yield return new WaitForSeconds(0.05f);
    58.    }
    59.  
    60.    GameControl.diceSideThrown = randomDiceSide + 1;
    61.    if (whosturn == 1){
    62.        GameControl.MovePlayer(1);
    63.    }
    64.  
    65.    if (whosturn == 2){
    66.        GameControl.MovePlayer(2);
    67.    }
    68.  
    69.    if (whosturn == 3){
    70.        GameControl.MovePlayer(3);
    71.    }
    72.  
    73.    if (whosturn == 4){
    74.        GameControl.MovePlayer(4);
    75.    }
    76.  
    77.    if (whosturn == 5){
    78.        GameControl.MovePlayer(5);
    79.    }
    80.  
    81.    if (whosturn == 6){
    82.        GameControl.MovePlayer(6);
    83.        whosturn -= 6;
    84.    }
    85.  
    86.    if (whosturn <= 5){
    87.        whosturn += 1;
    88.    }
    89.    coroutineallowed = true;
    90. }
    91.  
    92. }
    93.  
    and a Game control script :

    Code (CSharp):
    1. using System.Collections; using UnityEngine;
    2.  
    3. public class Dice : MonoBehaviour {
    4.  
    5. // Array of dice sides sprites to load from Resources folder
    6. private Sprite[] diceSides;
    7.  
    8. // Reference to sprite renderer to change sprites
    9. private SpriteRenderer rend;
    10.  
    11. // Select the player's turn
    12. private int whosturn = 1;
    13.  
    14. //Check if we can roll the dice
    15. private bool coroutineallowed = true;
    16.  
    17. // Use this for initialization
    18. private void Start () {
    19.  
    20.    // Assign Renderer component
    21.    rend = GetComponent<SpriteRenderer>();
    22.  
    23.    // Load dice sides sprites to array from DiceSides subfolder of Resources folder
    24.    diceSides = Resources.LoadAll<Sprite>("DiceSides/");
    25. }
    26.  
    27. // If you left click over the dice then RollTheDice coroutine is started
    28. private void OnMouseDown()
    29. {
    30.    if (!GameControl.gameOver && coroutineallowed)
    31.    StartCoroutine("RollTheDice");
    32. }
    33.  
    34. // Coroutine that rolls the dice
    35. private IEnumerator RollTheDice()
    36. {
    37.    // Turn coroutineallowed off
    38.  
    39.    coroutineallowed = false;
    40.    // Variable to contain random dice side number.
    41.    // It needs to be assigned. Let it be 0 initially
    42.    int randomDiceSide = 0;
    43.  
    44.    // Loop to switch dice sides ramdomly
    45.    // before final side appears. 10 itterations here.
    46.    for (int i = 0; i <= 10; i++)
    47.    {
    48.        // Pick up random value from 0 to 5 (All inclusive)
    49.        randomDiceSide = Random.Range(0, 6);
    50.  
    51.        // Set sprite to upper face of dice from array according to random value
    52.        rend.sprite = diceSides[randomDiceSide];
    53.  
    54.        // Pause before next itteration
    55.        yield return new WaitForSeconds(0.05f);
    56.    }
    57.  
    58.    GameControl.diceSideThrown = randomDiceSide + 1;
    59.    if (whosturn == 1){
    60.        GameControl.MovePlayer(1);
    61.    }
    62.  
    63.    if (whosturn == 2){
    64.        GameControl.MovePlayer(2);
    65.    }
    66.  
    67.    if (whosturn == 3){
    68.        GameControl.MovePlayer(3);
    69.    }
    70.  
    71.    if (whosturn == 4){
    72.        GameControl.MovePlayer(4);
    73.    }
    74.  
    75.    if (whosturn == 5){
    76.        GameControl.MovePlayer(5);
    77.    }
    78.  
    79.    if (whosturn == 6){
    80.        GameControl.MovePlayer(6);
    81.        whosturn -= 6;
    82.    }
    83.  
    84.    if (whosturn <= 5){
    85.        whosturn += 1;
    86.    }
    87.    coroutineallowed = true;
    88. }
    89. }
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,949
    Super common problem when developing.

    Welcome to the forums, and welcome to debugging!

    Here is how you can get started on figuring out what is happening.

    What is often happening in these cases is one of the following:

    - the code you think is executing is not actually executing at all
    - the code is executing far EARLIER or LATER than you think
    - the code is executing far LESS OFTEN than you think
    - the code is executing far MORE OFTEN than you think
    - the code is executing on another GameObject than you think it is
    - you're getting an error or warning and you haven't noticed it in the console window

    You must find a way to get the information you need in order to reason about what the problem is.

    To help gain more insight into your problem, I recommend liberally sprinkling
    Debug.Log()
    statements through your code to display information in realtime.

    Doing this should help you answer these types of questions:

    - is this code even running? which parts are running? how often does it run? what order does it run in?
    - what are the values of the variables involved? Are they initialized? Are the values reasonable?
    - are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)

    Knowing this information will help you reason about the behavior you are seeing.

    You can also supply a second argument to Debug.Log() and when you click the message, it will highlight the object in scene, such as
    Debug.Log("Problem!",this);


    If your problem would benefit from in-scene or in-game visualization, Debug.DrawRay() or Debug.DrawLine() can help you visualize things like rays (used in raycasting) or distances.

    You can also call Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene manually, looking for all the parts, where they are, what scripts are on them, etc.

    You can also call GameObject.CreatePrimitive() to emplace debug-marker-ish objects in the scene at runtime.

    You could also just display various important quantities in UI Text elements to watch them change as you play the game.

    If you are running a mobile device you can also view the console output. Google for how on your particular mobile target, such as this answer or iOS: https://forum.unity.com/threads/how-to-capturing-device-logs-on-ios.529920/ or this answer for Android: https://forum.unity.com/threads/how-to-capturing-device-logs-on-android.528680/

    Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.

    Here's an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

    https://forum.unity.com/threads/coroutine-missing-hint-and-error.1103197/#post-7100494

    When in doubt, print it out!(tm)

    Note: the
    print()
    function is an alias for Debug.Log() provided by the MonoBehaviour class.
     
    Bakaando likes this.
  3. exiguous

    exiguous

    Joined:
    Nov 21, 2010
    Posts:
    1,749
    Code (csharp):
    1. if (transform.position == waypoints[waypointIndex].transform.position)
    positions consist of float values and those should NEVER be compared with equality operator. For floats use Mathf.Approximately, for Vectors calculate the distance and compare this against a small value (fe 0.001). This is "close enough". For details look into "floating point imprecision". This thing is inherent to how computers work, not specific to Unity.
    If that is the cause of your problem I can't tell. But you can verfiy wether that if ever fires (with a Debug.Log for example).
     
    Bakaando and Kurt-Dekker like this.
  4. Bakaando

    Bakaando

    Joined:
    Sep 17, 2022
    Posts:
    6
    I think you pinpointed my problem, thank you very much !
    I now have this:
    Code (CSharp):
    1. if (Mathf.Approximately(transform.position, waypoints[waypointIndex].transform.position))
    The only problem I face now, is that Unity tells me I can't use Mathf.Approximately with vectors, and the internet tells me that vectors are stored as floats.
    I also didn't really undersand the "calculate the distance" part, and I guess they are linked.
    Thank you again vor the help !
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,949
    Let me lay it out:

    If you have two Vector3s named A and B...

    Do NOT do this:

    Code (csharp):
    1. if (A == B)
    2. {
    3.   /// reached goal
    4. }
    Instead, do this:

    Code (csharp):
    1. if (Vector3.Distance (A, B) < 0.1f)
    2. {
    3.   /// reached goal
    4. }
     
    exiguous and Bakaando like this.
  6. Bakaando

    Bakaando

    Joined:
    Sep 17, 2022
    Posts:
    6
    Thank you so much, it now works !
     
    Kurt-Dekker likes this.
  7. exiguous

    exiguous

    Joined:
    Nov 21, 2010
    Posts:
    1,749
    That's why I said (or tried to do so) when you compare floats use Mathf.Approximately. Vectors are not "stored as floats". A Vector consists of 3 float values. That's not the same.
    Kurt showed you how to use the distance of 2 vectors.
    What you should take away from this is, that floating point values (this includes double) suffer from said precision problems and should not be compared for equality.
     
  8. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,620
    I think to be fair though, you can use Vector2 and Vector3 equality using the "==" operator as it's approximate however using "Vector2/3.Equals()" isn't, it's exact and prone to numeric errors. Personally, I hate this implementation decision.

    This can be a source of errors though so the absolute distance method above is foolproof for sure!
     
  9. Bakaando

    Bakaando

    Joined:
    Sep 17, 2022
    Posts:
    6
    Oh okay, I understand now, thank you !
     
  10. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,381
    By the way, instead of typing all this:
    Code (csharp):
    1.  
    2. if (whosturn == 1){
    3.        GameControl.MovePlayer(1);
    4.    }
    5.  
    6.    if (whosturn == 2){
    7.        GameControl.MovePlayer(2);
    8.    }
    9.  
    10.    if (whosturn == 3){
    11.        GameControl.MovePlayer(3);
    12.    }
    13.  
    14.    if (whosturn == 4){
    15.        GameControl.MovePlayer(4);
    16.    }
    17.  
    18.    if (whosturn == 5){
    19.        GameControl.MovePlayer(5);
    20.    }
    21.  
    22.    if (whosturn == 6){
    23.        GameControl.MovePlayer(6);
    24.        whosturn -= 6;
    25.    }
    26.  
    You could shorten it to this, and it will do the same thing:
    Code (csharp):
    1.  
    2. GameControl.MovePlayer(whosturn);
    3. if (whosturn==6)
    4. {
    5.   whosturn=0;
    6. }
    7.  
     
  11. Bakaando

    Bakaando

    Joined:
    Sep 17, 2022
    Posts:
    6
    Oh yeah, it makes sense, thank you !