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. Dismiss Notice

[SOLVED] 2D Rouglike Tutorial - Character Can Only Move Twice

Discussion in 'Scripting' started by lazy-fox, May 17, 2019.

  1. lazy-fox

    lazy-fox

    Joined:
    Feb 2, 2019
    Posts:
    14
    I am currently doing the 2D Roguelike Tutorial from the official tutorial section
    https://unity3d.com/learn/tutorials/s/2d-roguelike-tutorial

    I have completed all the videos in sections 1-3.

    Issue

    The game should be functional at this point. It loads but it does not play correctly.

    The issue is that I can only tell my character to move twice. After that, he refuses to move in any direction.

    Steps to solving the problem

    I placed a debug line in the Player script. This line is supposed to output the state of the horizontal and vertical input access state.

    I am expecting the console to output the state of the axis once per frame since it is in the update() function

    The console only updates when I tell the player to move with the arrow keys. Yet even then it can only do so the first two times.

    I have absolutely no clue how this happens.

    A screenshot is attached to this threat as an attachment



    My Code

    Code (CSharp):
    1. //GameManager.cs
    2.  
    3. using UnityEngine;
    4. using System.Collections;
    5. using System.Collections.Generic;
    6.  
    7.  
    8. public class GameManager : MonoBehaviour
    9. {
    10.     public float turnDelay = 0.1f;
    11.     public static GameManager instance = null;
    12.     public int playerFoodPoints = 100;
    13.     [HideInInspector] public bool playersTurn = true;
    14.  
    15.     private BoardManager boardScript;
    16.     private int level = 3;
    17.     private List<Enemy> enemies;
    18.     private bool enemiesMoving;
    19.  
    20.     // Start is called before the first frame update
    21.     void Awake()
    22.     {
    23.         if(instance == null)
    24.             instance = this;
    25.         else if(instance != this)
    26.             Destroy(gameObject);
    27.      
    28.         DontDestroyOnLoad(gameObject);
    29.         enemies = new List<Enemy>();
    30.         boardScript = GetComponent<BoardManager>();
    31.         InitGame();
    32.     }
    33.  
    34.     void InitGame()
    35.     {
    36.         enemies.Clear();
    37.         boardScript.SetupScene(level);
    38.     }
    39.  
    40.     public void GameOver()
    41.     {
    42.             enabled = false;
    43.     }
    44.  
    45.     // Update is called once per frame
    46.     void Update()
    47.     {
    48.  
    49.         if (playersTurn || enemiesMoving)
    50.             return;
    51.         StartCoroutine(MoveEnemies());
    52.      
    53.     }
    54.  
    55.     public void AddEnemyToList(Enemy script)
    56.     {
    57.         enemies.Add(script);
    58.     }
    59.  
    60.     IEnumerator MoveEnemies()
    61.     {
    62.      
    63.         enemiesMoving = true;
    64.         yield return new WaitForSeconds(turnDelay);
    65.         if(enemies.Count == 0)
    66.             {
    67.                 yield return new WaitForSeconds(turnDelay);
    68.             }
    69.          
    70.             for(int i = 0; i < enemies.Count; i++)
    71.             {
    72.                 enemies[i].MoveEnemy();
    73.                 yield return new WaitForSeconds(enemies[i].moveTime);
    74.             }
    75.          
    76.             playersTurn = true;
    77.     }
    78. }
    79.  
    80.  
    Code (CSharp):
    1. //MovingObject.cs
    2.  
    3. using System.Collections;
    4. using UnityEngine;
    5. using UnityEngine.SceneManagement;
    6.  
    7. public class Player : MovingObject
    8. {
    9.     public int wallDamage = 1;
    10.     public int pointsPerFood = 10;
    11.     public int pointsPerSoda = 20;
    12.     public float restartLevelDelay = 1f;
    13.  
    14.     private Animator animator;
    15.     private int food;
    16.  
    17.     // Start is called before the first frame update
    18.     protected override void Start()
    19.     {
    20.             animator = GetComponent<Animator>();
    21.          
    22.             food = GameManager.instance.playerFoodPoints;
    23.          
    24.             base.Start();
    25.     }
    26.  
    27.     private void OnDisable()
    28.     {
    29.         GameManager.instance.playerFoodPoints = food;
    30.     }
    31.  
    32.     // Update is called once per frame
    33.     void Update()
    34.     {
    35.         Debug.Log("Food Points = " + food);
    36.         if(!GameManager.instance.playersTurn) return;
    37.      
    38.         int horizontal = 0;
    39.         int vertical = 0;
    40.      
    41.         horizontal = (int) Input.GetAxisRaw("Horizontal");
    42.         vertical = (int) Input.GetAxisRaw("Vertical");
    43.      
    44.         Debug.Log("Horizonal = " + horizontal);
    45.         Debug.Log("Vertical = " + vertical);
    46.      
    47.         if(horizontal != 0)
    48.             vertical = 0;
    49.         if(horizontal != 0 || vertical != 0)
    50.             AttemptMove<Wall> (horizontal, vertical);
    51.     }
    52.  
    53.     protected override void AttemptMove <T> (int xDir, int yDir)
    54.     {
    55.         food--;
    56.      
    57.         base.AttemptMove <T> (xDir, yDir);
    58.      
    59.         RaycastHit2D hit;
    60.      
    61.         if (Move (xDir, yDir, out hit))
    62.         {
    63.          
    64.         }
    65.      
    66.         CheckIfGameOver();
    67.      
    68.         GameManager.instance.playersTurn = false;
    69.     }
    70.  
    71.     private void OnTriggerEnter2D(Collider2D other)
    72.     {
    73.             if(other.tag == "Exit")
    74.             {
    75.                 Invoke("Restart", restartLevelDelay);
    76.                 enabled = false;
    77.             }
    78.             else if(other.tag == "Food")
    79.             {
    80.                 food += pointsPerSoda;
    81.                 other.gameObject.SetActive(false);
    82.             }
    83.     }
    84.  
    85.     protected override void OnCantMove <T> (T component)
    86.     {
    87.         Wall hitWall = component as Wall;
    88.         hitWall.DamageWall(wallDamage);
    89.         animator.SetTrigger("playerChop");
    90.     }
    91.  
    92.     private void Restart()
    93.     {
    94.         //Application.LoadLevel(Application.loadedLevel);
    95.         SceneManager.LoadScene(0);
    96.     }
    97.  
    98.     public void LoseFood (int loss)
    99.     {
    100.         animator.SetTrigger("playerHit");
    101.         food -= loss;
    102.         CheckIfGameOver();
    103.     }
    104.  
    105.     private void CheckIfGameOver()
    106.     {
    107.         if(food <= 0)
    108.             GameManager.instance.GameOver();
    109.     }
    110. }
    Code (CSharp):
    1. //Wall.cs
    2.  
    3. using UnityEngine;
    4. using System.Collections;
    5.  
    6. public class Wall : MonoBehaviour
    7. {
    8.  
    9.     public Sprite dmgSprite;
    10.     public int hp = 4;
    11.  
    12.     private SpriteRenderer spriteRenderer;
    13.  
    14.     // Start is called before the first frame update
    15.     void Awake()
    16.     {
    17.         spriteRenderer = GetComponent<SpriteRenderer>();
    18.     }
    19.  
    20.     public void DamageWall (int loss)
    21.     {
    22.         spriteRenderer.sprite = dmgSprite;
    23.         hp -= loss;
    24.         if(hp <= 0)
    25.             gameObject.SetActive(false);
    26.     }
    27. }
    28.  
    29.  
    Code (CSharp):
    1. //Enemy.cs
    2.  
    3. using UnityEngine;
    4. using System.Collections;
    5.  
    6. public class Enemy : MovingObject
    7. {
    8.     public int playerDamage;
    9.     private Animator animator;
    10.     private Transform target;
    11.     private bool skipMove;
    12.  
    13.     // Start is called before the first frame update
    14.     protected override void Start()
    15.     {
    16.         GameManager.instance.AddEnemyToList(this);
    17.         animator = GetComponent<Animator>();
    18.         target = GameObject.FindGameObjectWithTag("Player").transform;
    19.         base.Start();
    20.     }
    21.  
    22.     protected override void AttemptMove <T> (int xDir, int yDir)
    23.     {
    24.         if(skipMove)
    25.         {
    26.             skipMove = false;
    27.             return;
    28.         }
    29.     base.AttemptMove <T> (xDir,yDir);
    30.     skipMove = true;
    31.     }
    32.  
    33.     public void MoveEnemy()
    34.     {
    35.         int xDir = 0;
    36.         int yDir = 0;
    37.      
    38.         if (Mathf.Abs(target.position.x - transform.position.x) < float.Epsilon)
    39.             yDir = target.position.y > transform.position.y ? 1 : -1;
    40.         else
    41.             xDir = target.position.x > transform.position.x ? 1 : -1;
    42.      
    43.         AttemptMove <Player> (xDir, yDir);
    44.     }
    45.  
    46.     protected override void OnCantMove <T> (T component)
    47.     {
    48.         Player hitPlayer = component as Player;
    49.         animator.SetTrigger("enemyAttack");
    50.         hitPlayer.LoseFood(playerDamage);
    51.     }
    52. }
    53.  
    Code (CSharp):
    1. //Loader.cs
    2.  
    3. using UnityEngine;
    4. using System.Collections;
    5.  
    6.  
    7.     public class Loader : MonoBehaviour
    8.     {
    9.         public GameObject gameManager;          //GameManager prefab to instantiate.
    10.         //public GameObject soundManager;         //SoundManager prefab to instantiate.
    11.      
    12.      
    13.         void Awake ()
    14.         {
    15.             //Check if a GameManager has already been assigned to static variable GameManager.instance or if it's still null
    16.             if (GameManager.instance == null)
    17.              
    18.                 //Instantiate gameManager prefab
    19.                 Instantiate(gameManager);
    20.          
    21.             //Check if a SoundManager has already been assigned to static variable GameManager.instance or if it's still null
    22.             //if (SoundManager.instance == null)
    23.              
    24.                 //Instantiate SoundManager prefab
    25.                // Instantiate(soundManager);
    26.         }
    27.     }
    Code (CSharp):
    1. //BoardManager.cs
    2.  
    3. using System.Collections;
    4. using UnityEngine;
    5. using System;
    6. using System.Collections.Generic;
    7. using Random = UnityEngine.Random;
    8.  
    9. public class BoardManager : MonoBehaviour
    10. {
    11.     [Serializable]
    12.     public class Count
    13.     {
    14.         public int minimum;
    15.         public int maximum;
    16.         public Count (int min, int max)
    17.         {
    18.             minimum = min;
    19.             maximum = max;
    20.         }
    21.     }
    22.  
    23.     public int columns = 8;
    24.     public int rows = 8;
    25.     public Count wallCount = new Count (5,9);
    26.     public Count foodCount = new Count (5,9);
    27.     public GameObject exit;
    28.     public GameObject[] floorTiles;
    29.     public GameObject[] wallTiles;
    30.     public GameObject[] foodTiles;
    31.     public GameObject[] enemyTiles;
    32.     public GameObject[] outerWallTiles;
    33.  
    34.     private Transform boardHolder;
    35.     private List <Vector3> gridPositions = new List<Vector3>();
    36.  
    37.     void InitialiseList()
    38.     {
    39.         gridPositions.Clear();
    40.         for (int x = 1; x < columns - 1; x++)
    41.         {
    42.             for (int y = 1; y < rows - 1; y++)
    43.             {
    44.                 gridPositions.Add(new Vector3(x,y,0f));
    45.             }
    46.         }
    47.     }
    48.  
    49.  
    50. void BoardSetup ()
    51.         {
    52.             boardHolder = new GameObject ("Board").transform;
    53.             for(int x = -1; x < columns + 1; x++)
    54.             {
    55.                 for(int y = -1; y < rows + 1; y++)
    56.                 {
    57.                     GameObject toInstantiate = floorTiles[Random.Range (0,floorTiles.Length)];
    58.                  
    59.                     if(x == -1 || x == columns || y == -1 || y == rows)
    60.  
    61.                     toInstantiate = outerWallTiles[Random.Range (0, outerWallTiles.Length)];
    62.                  
    63.                     GameObject instance = Instantiate(toInstantiate, new Vector3 (x, y, 0f), Quaternion.identity) as GameObject;
    64.                      
    65.                     instance.transform.SetParent(boardHolder);
    66.  
    67.                 }
    68.             }
    69.         }
    70.  
    71.     Vector3 RandomPosition()
    72.     {
    73.         int randomIndex = Random.Range (0, gridPositions.Count);
    74.         Vector3 randomPosition = gridPositions[randomIndex];
    75.         gridPositions.RemoveAt(randomIndex);
    76.         return randomPosition;
    77.     }
    78.  
    79.     void LayoutObjectAtRandom(GameObject[] tileArray, int minimum, int maximum)
    80.     {
    81.         int objectCount = Random.Range (minimum, maximum + 1);
    82.      
    83.         for(int i = 0; i < objectCount; i++)
    84.         {
    85.             Vector3 randomPosition = RandomPosition();
    86.             GameObject tileChoice = tileArray[Random.Range (0, tileArray.Length)];
    87.             Instantiate (tileChoice, randomPosition, Quaternion.identity);  
    88.         }
    89.     }
    90.  
    91.     public void SetupScene (int level)
    92.     {
    93.         BoardSetup();
    94.         InitialiseList();
    95.         LayoutObjectAtRandom(wallTiles, wallCount.minimum, wallCount.maximum);
    96.         LayoutObjectAtRandom(foodTiles, foodCount.minimum, foodCount.maximum);
    97.         int enemyCount = (int)Mathf.Log(level,2f);
    98.         LayoutObjectAtRandom(enemyTiles, enemyCount, enemyCount);
    99.         Instantiate(exit, new Vector3(columns - 1, rows - 1, 0f), Quaternion.identity);
    100.     }  
    101. }
    102.  
     
  2. lazy-fox

    lazy-fox

    Joined:
    Feb 2, 2019
    Posts:
    14
    Update

    I went into the Player script and attempted to change a line of code in the AttemptMove() function


    Code (CSharp):
    1. //Old Code
    2. GameManager.instance.playersTurn = false;
    3.  
    4. //New Code
    5. GameManager.instance.playersTurn = true;
    I have noticed that the longer I hold down my arrow key, the move food the player loses. For example...

    The first time I tapped the right arrow key, the player lost 2 food.

    The second time I held it down the arrow key. The player lost 16 food.

    From this, I can conclude (with my level of experience), that the axis is registering a key hold rather than a key press or key release. I'm not sure how I am supposed to correct this.
     
  3. lazy-fox

    lazy-fox

    Joined:
    Feb 2, 2019
    Posts:
    14
    Solved

    I had to add a line of code at the end of my MoveEnemies() coroutine

    Code (CSharp):
    1. enemiesMoving = false;