Search Unity

Official 2D Roguelike: Q&A

Discussion in 'Community Learning & Teaching' started by Matthew-Schell, Feb 10, 2015.

Thread Status:
Not open for further replies.
  1. Deleted User

    Deleted User

    Guest

    Hi Atre, where you've got your void OnDisable, make sure that you're unsubscribing the event (rather than subscribing):

    Code (CSharp):
    1. void OnDisable()
    2. {
    3.         SceneManager.sceneLoaded -= OnLevelFinishedLoading;
    4. }
    5.  
    This may fix your issue. I 'think' it's trying to look for game objects that have already been destroyed once the script becomes disabled perhaps? Give it a shot anyway, I could be quite easily wrong. :p
     
  2. fregas

    fregas

    Joined:
    Dec 26, 2016
    Posts:
    3
    Question on Roguelike.

    I'm building a similar 2d game, and one thing I can't figure out: how does the Roguelike tutorial move only one tile at a time? I don't see anything that forces it to move exactly 32 pixels, the # in each tile. The linecast just stretches to the next collider as far as I can tell, so there shouldn't be anything stopping the player from moving several tiles or half a tile or whatever while its their turn.
     
  3. JRWidley

    JRWidley

    Joined:
    Nov 22, 2016
    Posts:
    18
    I may not be explaining this properly, as I'm just learning it too, but I think the move code moves it one "Unity" game unit, up, down, left, or right. When you imported your original spritesheet there was a setting that specified how many pixels (32) equal 1 unit. If you click on the spritesheet in your assets/sprites folder, then look at the properties editor you should see this.

    Again, I think this is what's happening but I could be wrong :)
     
    Matthew-Schell likes this.
  4. liam93

    liam93

    Joined:
    Feb 8, 2017
    Posts:
    3
    Hi. Hoping someone here can help me, because I'm pulling my hair here.

    I'm on part 11 of the tutorial, but at the end, where i'm supposed to test the game and see my character destroy walls and pick up food, he just walks straight over them. He's not even stopped by the outer walls. He can still move through the exit to the new level, though.

    I've checked everything I can think off - tags, layers, scripts. It's all identical to both the videos and the "completed" folder, save for the change in how the scene is loaded on restart. Does anyone know what might be wrong?

    A couple of pictures: broken.PNG player.PNG wall.PNG
     
  5. JRWidley

    JRWidley

    Joined:
    Nov 22, 2016
    Posts:
    18
    In MovingObject.cs what do you have in your AttemptMove <T> () method? Also what do you have in your Player.cs script for OnCantMove<T>() method? These are the methods that determine how to handle the component in the Wall prefabs. Here's mine:

    MovingObject.cs
    Code (CSharp):
    1. protected virtual void AttemptMove <T> (int xDir, int yDir)
    2.         where T : Component
    3.     {
    4.         RaycastHit2D hit;
    5.         bool canMove = Move(xDir, yDir, out hit);
    6.  
    7.         if (hit.transform == null)
    8.             return;
    9.  
    10.        T hitComponent = hit.transform.GetComponent<T>();
    11.  
    12.      
    13.         if (!canMove && hitComponent != null)
    14.             OnCantMove(hitComponent);
    15.     }
    Player.cs
    Code (CSharp):
    1. protected override void OnCantMove<T>(T component)
    2.     {
    3.         Wall hitWall = component as Wall;
    4.         hitWall.DamageWall(wallDamage);
    5.         animator.SetTrigger("playerChop");
    6.     }
    For the OuterWall prefabs, it should do nothing but prevent movement in that direction, but for Wall prefabs it will apply the hit logic and "playerChop" animation until the Wall has no damage left.
     
  6. liam93

    liam93

    Joined:
    Feb 8, 2017
    Posts:
    3
    Code (CSharp):
    1. protected virtual void AttemptMove<T>(int xDir, int yDir)
    2.         where T : Component {
    3.         RaycastHit2D hit;
    4.         bool CanMove = Move(xDir, yDir, out hit);
    5.         if (hit.transform == null)
    6.             return;
    7.         T hitComponent = hit.transform.GetComponent<T>();
    8.         if (!CanMove && hitComponent != null)
    9.             OnCantMove(hitComponent);
    10.     }
    Code (CSharp):
    1. protected override void OnCantMove<T>(T component) {
    2.         Wall hitWall = component as Wall;
    3.         hitWall.DamageWall(wallDamage);
    4.         animator.SetTrigger("playerChop");
    5.     }
    Those are mine. I can't spot the difference.
     
  7. JRWidley

    JRWidley

    Joined:
    Nov 22, 2016
    Posts:
    18
    do ALL your walls and food objects have the layer set to BlockingLayer?

    You said the exit works, but the player just walks over the food and soda and nothing happens? So whats different about the exit v.s. the food or soda? The three prefabs are handled in the same block of code so if they're setup the same they should each invoke a reaction. Is there anything different in the prefabs of the three that you can see?

    also, i'm sure there's a better way to do this - but i'm just learning as well, but in order to see if the game walks through a portion of code i add:
    debug.Log("test ....");
    and check the console output tab to see if it gets printed. Its a good way to see if the game makes runs through that block of code or if it's skipping it for some reason.


    Code (CSharp):
    1.  
    2. private void OnTriggerEnter2D(Collider2D other)
    3.     {
    4.         if (other.tag == "Exit")
    5.         {
    6.             Invoke("Restart", restartLevelDelay);
    7.             enabled = false;    
    8.         }
    9.         else if (other.tag == "Food")
    10.         {
    11.             food += pointsPerFood;
    12.             foodText.text = "+" + pointsPerFood + " Food: " + food;
    13.             SoundManager.instance.RandomizeSfx(eatSound1, eatSound2);
    14.             other.gameObject.SetActive(false);
    15.         }
    16.         else if (other.tag == "Soda")
    17.         {
    18.             food += pointsPerSoda;
    19.             foodText.text = "+" + pointsPerSoda + " Food: " + food;
    20.             SoundManager.instance.RandomizeSfx(drinkSound1, drinkSound2);
    21.             other.gameObject.SetActive(false);
    22.         }
    23.     }
    24.  
     
  8. liam93

    liam93

    Joined:
    Feb 8, 2017
    Posts:
    3
    No, Soda/Food is in the default layer along with Exit, just like the prefabs in the "Completed" folder.

    As for the debug logging, I'll try it in the morning. Thanks for now though!
     
  9. fregas

    fregas

    Joined:
    Dec 26, 2016
    Posts:
    3

    Thanks JR! I believe that is what I was missing!
     
    Matthew-Schell likes this.
  10. Mouradif

    Mouradif

    Joined:
    Mar 23, 2014
    Posts:
    1
    Hello there,

    I have been following the tutorial using Unity 5.5 (following the guidelines in the Upgrade guide PDF) with no problem until the step where I added the UI, then when I wanted to try, the game started at Day 2. I tried intializing the level to 0 instead of one, now the game starts at Day 1 but immediately after the first level I jump to Day 3 and foodCount gets set to 0 (thus after I try to move, I get the GameOver message "After 3 days, you starved."

    I added some `Debug.Log` in the function that calls `instance.level++`

    void OnLevelFinishedLoading(Scene scene, LoadSceneMode mode) {
    Debug.Log ("OnLevelFinishedLoading");
    //Add one to our level number.
    instance.level++;
    //Call InitGame to initialize our level.
    instance.InitGame();
    }​

    That's when I realized the function `OnLevelFinishedLoading` was called once when the game starts then twice after each level. How do I prevent that ?

    EDIT:

    After putting GameManager.instance.playerFood = food; in Player function "Restart" instead of OnDisable(), the food problem got away (now that I think of it, do we ever disable the player ?). So I could play further in the game, the only level that gets skipped is level 2. So I get "Day 1", "Day 3", "Day 4", "Day 5", ... I still have no idea why OnLevelFinishedLoading gets called twice after I finish level 1
     
    Last edited: Feb 24, 2017
  11. JRWidley

    JRWidley

    Joined:
    Nov 22, 2016
    Posts:
    18
    I had this problem as well, as did a few others in this thread.

    This is what i did to fix:
    Remove the InitGame(); line from the Awake() method of GameManager. It's getting called there, and also in OnLevelFinishedLoading() at the start of the game which is why it jumps to level 2.

    also, change this function to the following
    Code (CSharp):
    1.  void OnLevelFinishedLoading(Scene scene, LoadSceneMode mode)
    2.     {
    3.         level++;
    4.         InitGame();
    5.     }
    and at the top of GameManager initialize level=0;
     
    Palkei likes this.
  12. Solacefire

    Solacefire

    Joined:
    Dec 7, 2015
    Posts:
    2
    Hi, I'm close to finishing but getting some compilation errors:



    Enemy.cs:

    Code (CSharp):
    1.  
    2. using System;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using UnityEngine;
    6.  
    7. public class Enemy : MovingObject {
    8.  
    9.     public int playerDamage;
    10.  
    11.     private Animator animator;
    12.     private Transform target;
    13.     private bool skipMove;
    14.  
    15.     protected override void Start ()
    16.     {
    17.         GameManager.instance.AddEnemyToList(this);
    18.         animator = GetComponent<Animator>();
    19.         target = GameObject.FindGameObjectWithTag("Player").transform;
    20.         base.Start();
    21.     }
    22.  
    23.     protected override void AttemptMove <T> (int xDir, int yDir)
    24.     {
    25.         if (skipMove)
    26.         {
    27.             skipMove = false;
    28.             return;
    29.         }
    30.  
    31.         base.AttemptMove <T> (xDir, yDir);
    32.  
    33.         skipMove = true;
    34.     }
    35.  
    36.     public void MoveEnemy()
    37.     {
    38.         int xDir = 0;
    39.         int yDir = 0;
    40.  
    41.         if (Mathf.Abs(target.position.x - transform.position.x) < float.Epsilon)
    42.             yDir = target.position.y > transform.position.y ? 1 : -1;
    43.         else
    44.             xDir = target.position.x > transform.position.x ? 1 : -1;
    45.  
    46.         AttemptMove <Player> (xDir, yDir);
    47.     }
    48.  
    49.     protected override void OnCantMove <T> (T component)
    50.     {
    51.         Player hitPlayer = component as Player;
    52.  
    53.         hitPlayer.LoseFood (playerDamage);
    54.  
    55.         animator.SetTrigger ("enemyAttack");
    56.     }
    57.  
    58. }
    59.  
    I've tried replacing it with the completed version, same error. Any help would be appreciated on this.

    UPDATE: Solved using notes in '2D Roguelike Upgrade Guide 5x.pdf' in assets folder.
    UPDATE 2: This has not actually solved my issue, just mitigated a further one. Still getting the same two errors.
    UPDATE 3: Solved, Player prefab was not tagged 'Player'. Now only have a small problem where player picks up soda but not food...
    UPDATE 4: Also solved, ' else if (other.tag == "Food")' line in Player.cs did not have 'Food' capitalized. Success!
     
    Last edited: Mar 1, 2017
  13. TeamFortressDude

    TeamFortressDude

    Joined:
    Mar 4, 2017
    Posts:
    1
    Hey, I am a new to Unity and programming, so I can not figure out what is going on with my game. I have followed the tutorial as closely as I can, and everything is working fine so far, except the exit does not spawn in on the second day. Everything else seems to work fine.

    Here is the error I get:
    ArgumentException: The thing you want to instantiate is null.

    When I double click on the error, it leads me to this line of code:
    Instantiate (tileChoice, randomPosition, Quaternion.identity);

    Anybody know how to fix it? Thanks for any help.
     
  14. imthemonster

    imthemonster

    Joined:
    Mar 4, 2017
    Posts:
    7
    In my Game when the player dies doesn't restar the level. I opened the completed project and it doesn't open either. What should i do?

    GameManager
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. namespace Completed
    5. {
    6.     using System.Collections.Generic;        //Allows us to use Lists.
    7.     using UnityEngine.UI;                    //Allows us to use UI.
    8.    
    9.     public class GameManager : MonoBehaviour
    10.     {
    11.         public float levelStartDelay = 2f;                        //Time to wait before starting level, in seconds.
    12.         public float turnDelay = 0.1f;                            //Delay between each Player turn.
    13.         public int playerFoodPoints = 100;                        //Starting value for Player food points.
    14.         public static GameManager instance = null;                //Static instance of GameManager which allows it to be accessed by any other script.
    15.         [HideInInspector] public bool playersTurn = true;        //Boolean to check if it's players turn, hidden in inspector but public.
    16.        
    17.        
    18.         private Text levelText;                                    //Text to display current level number.
    19.         private GameObject levelImage;                            //Image to block out level as levels are being set up, background for levelText.
    20.         private BoardManager boardScript;                        //Store a reference to our BoardManager which will set up the level.
    21.         private int level = 1;                                    //Current level number, expressed in game as "Day 1".
    22.         private List<Enemy> enemies;                            //List of all Enemy units, used to issue them move commands.
    23.         private bool enemiesMoving;                                //Boolean to check if enemies are moving.
    24.         private bool doingSetup = true;                         //Boolean to check if we're setting up board, prevent Player from moving during setup.
    25.        
    26.  
    27.  
    28.  
    29.         //Awake is always called before any Start functions
    30.         void Awake()
    31.         {
    32.             //Check if instance already exists
    33.             if (instance == null)
    34.                
    35.                 //if not, set instance to this
    36.                 instance = this;
    37.            
    38.             //If instance already exists and it's not this:
    39.             else if (instance != this)
    40.                
    41.                 //Then destroy this. This enforces our singleton pattern, meaning there can only ever be one instance of a GameManager.
    42.                 Destroy(gameObject);  
    43.            
    44.             //Sets this to not be destroyed when reloading scene
    45.             DontDestroyOnLoad(gameObject);
    46.            
    47.             //Assign enemies to a new List of Enemy objects.
    48.             enemies = new List<Enemy>();
    49.            
    50.             //Get a component reference to the attached BoardManager script
    51.             boardScript = GetComponent<BoardManager>();
    52.            
    53.             //Call the InitGame function to initialize the first level
    54.             InitGame();
    55.         }
    56.        
    57.         //This is called each time a scene is loaded.
    58.         void OnLevelWasLoaded(int index)
    59.         {
    60.             //Add one to our level number.
    61.             level++;
    62.             //Call InitGame to initialize our level.
    63.             InitGame();
    64.         }
    65.        
    66.         //Initializes the game for each level.
    67.         void InitGame()
    68.         {
    69.             //While doingSetup is true the player can't move, prevent player from moving while title card is up.
    70.             doingSetup = true;
    71.            
    72.             //Get a reference to our image LevelImage by finding it by name.
    73.             levelImage = GameObject.Find("LevelImage");
    74.            
    75.             //Get a reference to our text LevelText's text component by finding it by name and calling GetComponent.
    76.             levelText = GameObject.Find("LevelText").GetComponent<Text>();
    77.            
    78.             //Set the text of levelText to the string "Day" and append the current level number.
    79.             levelText.text = "Day " + level;
    80.            
    81.             //Set levelImage to active blocking player's view of the game board during setup.
    82.             levelImage.SetActive(true);
    83.            
    84.             //Call the HideLevelImage function with a delay in seconds of levelStartDelay.
    85.             Invoke("HideLevelImage", levelStartDelay);
    86.            
    87.             //Clear any Enemy objects in our List to prepare for next level.
    88.             enemies.Clear();
    89.            
    90.             //Call the SetupScene function of the BoardManager script, pass it current level number.
    91.             boardScript.SetupScene(level);
    92.            
    93.         }
    94.        
    95.        
    96.         //Hides black image used between levels
    97.         void HideLevelImage()
    98.         {
    99.             //Disable the levelImage gameObject.
    100.             levelImage.SetActive(false);
    101.            
    102.             //Set doingSetup to false allowing player to move again.
    103.             doingSetup = false;
    104.         }
    105.        
    106.         //Update is called every frame.
    107.         void Update()
    108.         {
    109.             //Check that playersTurn or enemiesMoving or doingSetup are not currently true.
    110.             if(playersTurn || enemiesMoving || doingSetup)
    111.                
    112.                 //If any of these are true, return and do not start MoveEnemies.
    113.                 return;
    114.            
    115.             //Start moving enemies.
    116.             StartCoroutine (MoveEnemies ());
    117.         }
    118.        
    119.         //Call this to add the passed in Enemy to the List of Enemy objects.
    120.         public void AddEnemyToList(Enemy script)
    121.         {
    122.             //Add Enemy to List enemies.
    123.             enemies.Add(script);
    124.         }
    125.        
    126.        
    127.         //GameOver is called when the player reaches 0 food points
    128.         public void GameOver()
    129.         {
    130.             //Set levelText to display number of levels passed and game over message
    131.             levelText.text = "After " + level + " days, you starved.";
    132.            
    133.             //Enable black background image gameObject.
    134.             levelImage.SetActive(true);
    135.            
    136.             //Disable this GameManager.
    137.             enabled = false;
    138.  
    139.             Invoke("Restart", restartLevelDelay);
    140.         }
    141.        
    142.         //Coroutine to move enemies in sequence.
    143.         IEnumerator MoveEnemies()
    144.         {
    145.             //While enemiesMoving is true player is unable to move.
    146.             enemiesMoving = true;
    147.            
    148.             //Wait for turnDelay seconds, defaults to .1 (100 ms).
    149.             yield return new WaitForSeconds(turnDelay);
    150.            
    151.             //If there are no enemies spawned (IE in first level):
    152.             if (enemies.Count == 0)
    153.             {
    154.                 //Wait for turnDelay seconds between moves, replaces delay caused by enemies moving when there are none.
    155.                 yield return new WaitForSeconds(turnDelay);
    156.             }
    157.            
    158.             //Loop through List of Enemy objects.
    159.             for (int i = 0; i < enemies.Count; i++)
    160.             {
    161.                 //Call the MoveEnemy function of Enemy at index i in the enemies List.
    162.                 enemies[i].MoveEnemy ();
    163.                
    164.                 //Wait for Enemy's moveTime before moving next Enemy,
    165.                 yield return new WaitForSeconds(enemies[i].moveTime);
    166.             }
    167.             //Once Enemies are done moving, set playersTurn to true so player can move.
    168.             playersTurn = true;
    169.            
    170.             //Enemies are done moving, set enemiesMoving to false.
    171.             enemiesMoving = false;
    172.         }
    173.     }
    174. }
    175.  
    176.  
    Player
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.UI;    //Allows us to use UI.
    4.  
    5. namespace Completed
    6. {
    7.     //Player inherits from MovingObject, our base class for objects that can move, Enemy also inherits from this.
    8.     public class Player : MovingObject
    9.     {
    10.         public float restartLevelDelay = 1f;        //Delay time in seconds to restart level.
    11.         public int pointsPerFood = 10;                //Number of points to add to player food points when picking up a food object.
    12.         public int pointsPerSoda = 20;                //Number of points to add to player food points when picking up a soda object.
    13.         public int wallDamage = 1;                    //How much damage a player does to a wall when chopping it.
    14.         public Text foodText;                        //UI Text to display current player food total.
    15.         public AudioClip moveSound1;                //1 of 2 Audio clips to play when player moves.
    16.         public AudioClip moveSound2;                //2 of 2 Audio clips to play when player moves.
    17.         public AudioClip eatSound1;                    //1 of 2 Audio clips to play when player collects a food object.
    18.         public AudioClip eatSound2;                    //2 of 2 Audio clips to play when player collects a food object.
    19.         public AudioClip drinkSound1;                //1 of 2 Audio clips to play when player collects a soda object.
    20.         public AudioClip drinkSound2;                //2 of 2 Audio clips to play when player collects a soda object.
    21.         public AudioClip gameOverSound;                //Audio clip to play when player dies.
    22.        
    23.         private Animator animator;                    //Used to store a reference to the Player's animator component.
    24.         private int food;                            //Used to store player food points total during level.
    25.         private Vector2 touchOrigin = -Vector2.one;    //Used to store location of screen touch origin for mobile controls.
    26.        
    27.        
    28.         //Start overrides the Start function of MovingObject
    29.         protected override void Start ()
    30.         {
    31.             //Get a component reference to the Player's animator component
    32.             animator = GetComponent<Animator>();
    33.            
    34.             //Get the current food point total stored in GameManager.instance between levels.
    35.             food = GameManager.instance.playerFoodPoints;
    36.            
    37.             //Set the foodText to reflect the current player food total.
    38.             foodText.text = "Food: " + food;
    39.            
    40.             //Call the Start function of the MovingObject base class.
    41.             base.Start ();
    42.         }
    43.        
    44.        
    45.         //This function is called when the behaviour becomes disabled or inactive.
    46.         private void OnDisable ()
    47.         {
    48.             //When Player object is disabled, store the current local food total in the GameManager so it can be re-loaded in next level.
    49.             GameManager.instance.playerFoodPoints = food;
    50.         }
    51.        
    52.        
    53.         private void Update ()
    54.         {
    55.             //If it's not the player's turn, exit the function.
    56.             if(!GameManager.instance.playersTurn) return;
    57.            
    58.             int horizontal = 0;      //Used to store the horizontal move direction.
    59.             int vertical = 0;        //Used to store the vertical move direction.
    60.            
    61.             //Check if we are running either in the Unity editor or in a standalone build.
    62.             #if UNITY_STANDALONE || UNITY_WEBPLAYER
    63.            
    64.             //Get input from the input manager, round it to an integer and store in horizontal to set x axis move direction
    65.             horizontal = (int) (Input.GetAxisRaw ("Horizontal"));
    66.            
    67.             //Get input from the input manager, round it to an integer and store in vertical to set y axis move direction
    68.             vertical = (int) (Input.GetAxisRaw ("Vertical"));
    69.            
    70.             //Check if moving horizontally, if so set vertical to zero.
    71.             if(horizontal != 0)
    72.             {
    73.                 vertical = 0;
    74.             }
    75.             //Check if we are running on iOS, Android, Windows Phone 8 or Unity iPhone
    76.             #elif UNITY_IOS || UNITY_ANDROID || UNITY_WP8 || UNITY_IPHONE
    77.            
    78.             //Check if Input has registered more than zero touches
    79.             if (Input.touchCount > 0)
    80.             {
    81.                 //Store the first touch detected.
    82.                 Touch myTouch = Input.touches[0];
    83.                
    84.                 //Check if the phase of that touch equals Began
    85.                 if (myTouch.phase == TouchPhase.Began)
    86.                 {
    87.                     //If so, set touchOrigin to the position of that touch
    88.                     touchOrigin = myTouch.position;
    89.                 }
    90.                
    91.                 //If the touch phase is not Began, and instead is equal to Ended and the x of touchOrigin is greater or equal to zero:
    92.                 else if (myTouch.phase == TouchPhase.Ended && touchOrigin.x >= 0)
    93.                 {
    94.                     //Set touchEnd to equal the position of this touch
    95.                     Vector2 touchEnd = myTouch.position;
    96.                    
    97.                     //Calculate the difference between the beginning and end of the touch on the x axis.
    98.                     float x = touchEnd.x - touchOrigin.x;
    99.                    
    100.                     //Calculate the difference between the beginning and end of the touch on the y axis.
    101.                     float y = touchEnd.y - touchOrigin.y;
    102.                    
    103.                     //Set touchOrigin.x to -1 so that our else if statement will evaluate false and not repeat immediately.
    104.                     touchOrigin.x = -1;
    105.                    
    106.                     //Check if the difference along the x axis is greater than the difference along the y axis.
    107.                     if (Mathf.Abs(x) > Mathf.Abs(y))
    108.                         //If x is greater than zero, set horizontal to 1, otherwise set it to -1
    109.                         horizontal = x > 0 ? 1 : -1;
    110.                     else
    111.                         //If y is greater than zero, set horizontal to 1, otherwise set it to -1
    112.                         vertical = y > 0 ? 1 : -1;
    113.                 }
    114.             }
    115.            
    116.             #endif //End of mobile platform dependendent compilation section started above with #elif
    117.             //Check if we have a non-zero value for horizontal or vertical
    118.             if(horizontal != 0 || vertical != 0)
    119.             {
    120.                 //Call AttemptMove passing in the generic parameter Wall, since that is what Player may interact with if they encounter one (by attacking it)
    121.                 //Pass in horizontal and vertical as parameters to specify the direction to move Player in.
    122.                 AttemptMove<Wall> (horizontal, vertical);
    123.             }
    124.         }
    125.        
    126.         //AttemptMove overrides the AttemptMove function in the base class MovingObject
    127.         //AttemptMove takes a generic parameter T which for Player will be of the type Wall, it also takes integers for x and y direction to move in.
    128.         protected override void AttemptMove <T> (int xDir, int yDir)
    129.         {
    130.             //Every time player moves, subtract from food points total.
    131.             food--;
    132.            
    133.             //Update food text display to reflect current score.
    134.             foodText.text = "Food: " + food;
    135.            
    136.             //Call the AttemptMove method of the base class, passing in the component T (in this case Wall) and x and y direction to move.
    137.             base.AttemptMove <T> (xDir, yDir);
    138.            
    139.             //Hit allows us to reference the result of the Linecast done in Move.
    140.             RaycastHit2D hit;
    141.            
    142.             //If Move returns true, meaning Player was able to move into an empty space.
    143.             if (Move (xDir, yDir, out hit))
    144.             {
    145.                 //Call RandomizeSfx of SoundManager to play the move sound, passing in two audio clips to choose from.
    146.                 SoundManager.instance.RandomizeSfx (moveSound1, moveSound2);
    147.             }
    148.            
    149.             //Since the player has moved and lost food points, check if the game has ended.
    150.             CheckIfGameOver ();
    151.            
    152.             //Set the playersTurn boolean of GameManager to false now that players turn is over.
    153.             GameManager.instance.playersTurn = false;
    154.         }
    155.        
    156.        
    157.         //OnCantMove overrides the abstract function OnCantMove in MovingObject.
    158.         //It takes a generic parameter T which in the case of Player is a Wall which the player can attack and destroy.
    159.         protected override void OnCantMove <T> (T component)
    160.         {
    161.             //Set hitWall to equal the component passed in as a parameter.
    162.             Wall hitWall = component as Wall;
    163.            
    164.             //Call the DamageWall function of the Wall we are hitting.
    165.             hitWall.DamageWall (wallDamage);
    166.            
    167.             //Set the attack trigger of the player's animation controller in order to play the player's attack animation.
    168.             animator.SetTrigger ("playerChop");
    169.         }
    170.        
    171.        
    172.         //OnTriggerEnter2D is sent when another object enters a trigger collider attached to this object (2D physics only).
    173.         private void OnTriggerEnter2D (Collider2D other)
    174.         {
    175.             //Check if the tag of the trigger collided with is Exit.
    176.             if(other.tag == "Exit")
    177.             {
    178.                 //Invoke the Restart function to start the next level with a delay of restartLevelDelay (default 1 second).
    179.                 Invoke ("Restart", restartLevelDelay);
    180.                
    181.                 //Disable the player object since level is over.
    182.                 enabled = false;
    183.             }
    184.            
    185.             //Check if the tag of the trigger collided with is Food.
    186.             else if(other.tag == "Food")
    187.             {
    188.                 //Add pointsPerFood to the players current food total.
    189.                 food += pointsPerFood;
    190.                
    191.                 //Update foodText to represent current total and notify player that they gained points
    192.                 foodText.text = "+" + pointsPerFood + " Food: " + food;
    193.                
    194.                 //Call the RandomizeSfx function of SoundManager and pass in two eating sounds to choose between to play the eating sound effect.
    195.                 SoundManager.instance.RandomizeSfx (eatSound1, eatSound2);
    196.                
    197.                 //Disable the food object the player collided with.
    198.                 other.gameObject.SetActive (false);
    199.             }
    200.            
    201.             //Check if the tag of the trigger collided with is Soda.
    202.             else if(other.tag == "Soda")
    203.             {
    204.                 //Add pointsPerSoda to players food points total
    205.                 food += pointsPerSoda;
    206.                
    207.                 //Update foodText to represent current total and notify player that they gained points
    208.                 foodText.text = "+" + pointsPerSoda + " Food: " + food;
    209.                
    210.                 //Call the RandomizeSfx function of SoundManager and pass in two drinking sounds to choose between to play the drinking sound effect.
    211.                 SoundManager.instance.RandomizeSfx (drinkSound1, drinkSound2);
    212.                
    213.                 //Disable the soda object the player collided with.
    214.                 other.gameObject.SetActive (false);
    215.             }
    216.         }
    217.        
    218.        
    219.         //Restart reloads the scene when called.
    220.         private void Restart ()
    221.         {
    222.             //Load the last scene loaded, in this case Main, the only scene in the game.
    223.             Application.LoadLevel (Application.loadedLevel);
    224.         }
    225.        
    226.        
    227.         //LoseFood is called when an enemy attacks the player.
    228.         //It takes a parameter loss which specifies how many points to lose.
    229.         public void LoseFood (int loss)
    230.         {
    231.             //Set the trigger for the player animator to transition to the playerHit animation.
    232.             animator.SetTrigger ("playerHit");
    233.            
    234.             //Subtract lost food points from the players total.
    235.             food -= loss;
    236.            
    237.             //Update the food display with the new total.
    238.             foodText.text = "-"+ loss + " Food: " + food;
    239.            
    240.             //Check to see if game has ended.
    241.             CheckIfGameOver ();
    242.         }
    243.        
    244.        
    245.         //CheckIfGameOver checks if the player is out of food points and if so, ends the game.
    246.         private void CheckIfGameOver ()
    247.         {
    248.             //Check if food point total is less than or equal to zero.
    249.             if (food <= 0)
    250.             {
    251.                 //Call the PlaySingle function of SoundManager and pass it the gameOverSound as the audio clip to play.
    252.                 SoundManager.instance.PlaySingle (gameOverSound);
    253.                
    254.                 //Stop the background music.
    255.                 SoundManager.instance.musicSource.Stop();
    256.                
    257.                 //Call the GameOver function of GameManager.
    258.                 GameManager.instance.GameOver ();
    259.             }
    260.         }
    261.     }
    262. }
    263.  
    264.  
     
  15. Farlokko

    Farlokko

    Joined:
    Mar 9, 2017
    Posts:
    3
    Hello! I'm having a strange problem: when i restart the scene because of the "exit" the 'playerFoodPoints' of my GameManager istance go to zero. All the remaining values of the instance don't change. I suppose it's something related to the "dontDestroyOnLoad". Any idea? ^^

    I can easily solve the problem with a static int variable skipping the instance but i'd like to understand the behaviour described above.

    Thanks!
     
  16. Deleted User

    Deleted User

    Guest

  17. Farlokko

    Farlokko

    Joined:
    Mar 9, 2017
    Posts:
    3
    This solved the problem, thanks a lot ! :)

    So if I understand correctly, I was calling the OnLevelFinishedLoading from the start. However I don't understand anyway what caused the bug, do you?
     
    xjoel likes this.
  18. Wiesiek1303

    Wiesiek1303

    Joined:
    Feb 23, 2017
    Posts:
    2
    Hi Matt,
    Thank you very much for this tutorial, I am very new to Unity, so forgive me if I ask obvious question.
    I follow the tutorial in Unity v 5.5.2. I feel I learned very much from your work.
    However, I have found the problem which I cannot manage. In order to describe it you need to watch the video I have attached. In this video You see that when Player takes Food, or Soda, or interacts with walls, there is changing the Outer Walls in position of the Column 0.
    Do you have any Ideas what could be the cause of this bug and how to fix it.


    Thank you for your help in adwance
    Wiesiek1303
     
  19. Airmand1

    Airmand1

    Joined:
    Jul 18, 2014
    Posts:
    2
    Im not sure where to begin on sharing my scripts. I just finished up episode 11 and the issue Im having is that my player is not picking up any items or able to interact with the exit. I get no errors. I also put debug.log statements in the OnTriggerEnter2D function in the "Player" script. I get no console output whenever I walk over these items. Is trigger is checked on items, Player character has a rigid body and is kinematic. Tags are correct, "Food", "Soda", "Exit". The are set to default layer with the "Items" sorting layer. Hopefully someone will be able to assist me on this one.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.SceneManagement;
    5.  
    6. public class Player : MovingObject {
    7.  
    8.     public int wallDamage = 1;
    9.     public int pointsPerFood = 10;
    10.     public int pointsPerSoda = 20;
    11.     public float restartLevelDelay = 1f;
    12.  
    13.     private Animator animator;
    14.     private int food;
    15.  
    16.     // Use this for initialization
    17.     protected override void Start ()
    18.     {
    19.         animator = GetComponent<Animator> ();
    20.         food = GameManager.instance.playerFoodPoints;
    21.  
    22.         base.Start ();
    23.     }
    24.  
    25.     private void OnDisable()
    26.     {
    27.         GameManager.instance.playerFoodPoints = food;
    28.     }
    29.    
    30.     // Update is called once per frame
    31.     void Update ()
    32.     {
    33.         if (!GameManager.instance.playerTurn)
    34.             return;
    35.  
    36.         int horizontal = 0;
    37.         int vertical = 0;
    38.  
    39.         horizontal = (int)Input.GetAxisRaw ("Horizontal");
    40.         vertical = (int)Input.GetAxisRaw ("Vertical");
    41.  
    42.         if (horizontal != 0)
    43.             vertical = 0;
    44.  
    45.         if (horizontal != 0 || vertical != 0)
    46.             AttemptMove<Wall> (horizontal, vertical);
    47.     }
    48.  
    49.     protected override void AttemptMove <T> (int xDir, int yDir)
    50.     {
    51.         food--;
    52.  
    53.         base.AttemptMove <T> (xDir, yDir);
    54.  
    55.         RaycastHit2D hit;
    56.  
    57.         CheckIfGameOver ();
    58.  
    59.         GameManager.instance.playerTurn = false;
    60.     }
    61.  
    62.     private void OnTriggerEnter2d (Collider2D other)
    63.     {
    64.         if (other.tag == "Exit")
    65.         {
    66.             Debug.Log ("Collision");
    67.             Invoke ("Restart", restartLevelDelay);
    68.             enabled = false;
    69.         }
    70.         else if (other.tag == "Food")
    71.         {
    72.             Debug.Log ("Collision");
    73.             food += pointsPerFood;
    74.             other.gameObject.SetActive (false);
    75.         }
    76.  
    77.         else if (other.tag == "Soda")
    78.         {
    79.             Debug.Log ("Collision");
    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.     }
    93.  
    94.     private void Restart()
    95.     {
    96.         SceneManager.LoadScene (SceneManager.GetActiveScene ().buildIndex);
    97.     }
    98.  
    99.     public void LoseFood (int loss)
    100.     {
    101.         animator.SetTrigger ("playerHit");
    102.         food -= loss;
    103.         CheckIfGameOver ();
    104.     }
    105.  
    106.     private void CheckIfGameOver()
    107.     {
    108.         if (food <= 0)
    109.             GameManager.instance.GameOver ();
    110.     }
    111. }
    112.  
     
    Last edited: Mar 20, 2017
  20. Airmand1

    Airmand1

    Joined:
    Jul 18, 2014
    Posts:
    2
    ****EDIT****
    Nevermind I figure out the issue. I had "private void OnTriggerEnter2d" rather than 2D
     
  21. crystalwizard321

    crystalwizard321

    Joined:
    Mar 12, 2017
    Posts:
    23
    is that in the actual compiled game or is that when playing the game inside the Unity editor?
     
  22. crystalwizard321

    crystalwizard321

    Joined:
    Mar 12, 2017
    Posts:
    23
    Next stupid questions.

    1:
    Instead of every wall having 3 hit points, I want them to have a random range of hp, and I'm thinking that the code should be
    public int hp = Random.Range(1,5)
    but I wanted to check with you guys and see if this was correct.

    2:
    When the player hits the wall, again I want a random ammount of damage to be done, and I'm thinking that it should be:

    public int wallDamage = Random.Range(1,3)
    and again, I wanted to check this.

    And 3:
    I would like to display the amount of damage done to the wall with each hit, but I just get errors when trying to use the same code that's used for displaying the food points when food is picked up, so was looking for some help. The code doesn't need to be public, so I tried using a private variable - but got no where. C# and I are not getting along well, unfortunately. I'm experienced with C but C# is kicking me to the curb and Unity is helping.
     
  23. Wiesiek1303

    Wiesiek1303

    Joined:
    Feb 23, 2017
    Posts:
    2
    Thank you for your answer,
    this happens in both situation, i.e. in Unity Editor and after compilation, in the compiled program the number of that places is bigger and concerns all walls around the game board.
    Regards Wiesiek1303
     
  24. crystalwizard321

    crystalwizard321

    Joined:
    Mar 12, 2017
    Posts:
    23
    I would redo all your animations and tiles. It sounds like you've gotten something mixed up. And make sure that you didn't accidentally name 2 things the same somehow.
     
  25. zetaroid

    zetaroid

    Joined:
    Apr 3, 2017
    Posts:
    1
    Hey so everything is working perfectly except for one minor detail. If I hold down an arrow key between scenes loading (or levels loading whatever you prefer to call it), the player is able to move exactly one block in the next scene, but no more than that. Any idea what might be causing this?
     
  26. QuinnPurdy

    QuinnPurdy

    Joined:
    Apr 3, 2017
    Posts:
    1
    I am on section 5 of the tutorial. It tells me to drag my prefabs into my BoardManager script after I add it to my GameManager gameitem. I have copied the tutorial word for word, but there is no place for me to drag my prefabs into. I cannot run anything as it gives me a compile error.
     
  27. umenneske

    umenneske

    Joined:
    Apr 6, 2017
    Posts:
    1
    I am following the tutorial and am at the section described as assigning variables to the Board Manager script. I've assigned the prefabs to the Board Manager script and tested, but only Outer Wall 1-3, Floor 1-8 and Exit are showing. Enemy 1 and 2, Wall 1-8, Food and Soda don't show up. I wondered whether I had the wrong sorting layer for these, but have checked it and they seem to be right. Any advice would be appreciated, thanks.
     
  28. crystalwizard321

    crystalwizard321

    Joined:
    Mar 12, 2017
    Posts:
    23
    If you've put enemies, food, and soda in your prefabs, and deleted them from the project, they won't show up in the game until the script loads them. Enemies don't show up on the first level, ever. Your food or soda objects will show up on level 1, but not necessarily both of them. It's random. And they're only going to show up when the game is running.

    But your inner walls should be showing up.

    Do this:

    Run the game, then look at the console tab. Are there any errors?
     
  29. crystalwizard321

    crystalwizard321

    Joined:
    Mar 12, 2017
    Posts:
    23
    you're still building the game. Don't hold the arrow key down. Wait till the game is completely built then see if its still happening.
     
  30. crystalwizard321

    crystalwizard321

    Joined:
    Mar 12, 2017
    Posts:
    23
    1. you need to go through the earlier tutorials for space shooter and roll the ball.

    2. You need to create a prefabs folder under the assets folder on the project tab, and put your prefabs in that folder.
     
  31. RedEyedDeveloper

    RedEyedDeveloper

    Joined:
    Apr 14, 2017
    Posts:
    8
    Hello, I am having only two issues in the tutorial for the 2DRougelike game from Unity (I have just finished part 11 the Enemy Animator Video).

    1. My When my player moves onto the food and/or the Soda tiles, the food and/or Soda does not get "picked up".
    2. In my scripts (even tough I followed the tutorial to the letter), states the variable 'hit' is declared but never used, Is this a issue?

    Any help will be greatly appreciated. Thank You.

    P.S. I have found this tutorial to be wonderful and informative I am really enjoying it (I am using Windows 10 if that makes any difference).
     
  32. crystalwizard321

    crystalwizard321

    Joined:
    Mar 12, 2017
    Posts:
    23
    Did you forget to set your food and soda items as triggers?
     
  33. RedEyedDeveloper

    RedEyedDeveloper

    Joined:
    Apr 14, 2017
    Posts:
    8
    Hello CrystalWixard321,

    I have fixed the issue it was just a bug in the scripting. However, I am having three different issues now.

    1. The black screen that is suppose to appear at the start, end and between levels does not cover the games screen fully.
    2. After my player dies the game does not automatically restart.
    3. The only way I can close the game is from closing it from right clicking it in the system tray of my computer and clicking close.

    Any help will be greatly appreciated. Thank You.
     
  34. Mascasc

    Mascasc

    Joined:
    Apr 17, 2017
    Posts:
    3
    I have been following the tutorial, and it has been going quite well up to the point where I added the ui elements.

    I can display Day 1 correctly, and the food counter displays correctly.

    Unfortunately the ui image does not disappear. So the screen remains black.

    The food counter is fine, and I can move around the screen, pick up soda, get hurt by enemies, even move to the next level. The Day 2 text displays.

    I am just doing this all in total darkness. Looking in the inspector the image element is greyed out after the Day text disappears, leading me to believe the SetActive method is being called and inactivating the image. But it doesn't go away.

    The layer is set to UI.

    Any suggestions for how to fix this? Had a lot of fun so far.
     
  35. crystalwizard321

    crystalwizard321

    Joined:
    Mar 12, 2017
    Posts:
    23
    Hi RedEye:

    >1. The black screen that is suppose to appear at the start, end and between levels does not cover the games screen fully.

    Go back through the UI training video. You've missed several steps.

    >2. After my player dies the game does not automatically restart.

    No, and it won't. But you can go through the roll the ball tutorial and there are instructions in it to add a restart button in that the player can click.

    >3. The only way I can close the game is from closing it from right clicking it in the system tray of my computer and clicking close.

    when in Unity or when playing in a build from windows? If it's the windows build, no, you can't close it. You can alt-tab to get to a different window, or you can add in a restart/quit menu. That's not something that's included (unfortunately) in the tutorial.
     
  36. crystalwizard321

    crystalwizard321

    Joined:
    Mar 12, 2017
    Posts:
    23
    I suggest you re-watch the UI tutorial video and double-check everything.
     
  37. Mascasc

    Mascasc

    Joined:
    Apr 17, 2017
    Posts:
    3
    I rewatched the video again, paying special attention to anything that might cause a wrong result but not be caught by the compiler (I come from a C/C++ background so I'm used to stumbling over my own silliness in this way).

    The only thing that I could see that might cause a problem is that since I am using version 5.3 the OnSceneLoaded function could be potentially deprecated and not work.

    I followed then the UpgradeGuide and got an error that "sceneLoaded" was not defined in the package.

    Sometimes an error is progress for me, but I"m not sure if this is one of those cases.
     
  38. crystalwizard321

    crystalwizard321

    Joined:
    Mar 12, 2017
    Posts:
    23
    Don't feel bad. I hate C#. I much prefer C. My own background is programming MUDs.

    >I followed then the UpgradeGuide and got an error that "sceneLoaded" was not defined in the package.

    You need to add using UnityEngine.SceneManagement; to your includes in the player script

    You didn't state what tutorial video you're on, but under section 4 he starts talking about adding in the UI elements, how to position text such as food points, what layer to put the various elements (including the black image that displays between level) and so on. What step are you on?
     
  39. GrisWoldDiablo

    GrisWoldDiablo

    Joined:
    Apr 5, 2017
    Posts:
    8
    OMG I looked everywhere. Stupid thing I didn't notice. Thanks Steerpike.
     
  40. GrisWoldDiablo

    GrisWoldDiablo

    Joined:
    Apr 5, 2017
    Posts:
    8
    Well maybe some people wondered how have the screen properly size for portrait and landscape on mobile.
    Here my code for the Loader script. Modified it so now the camera size change to fit any screen.
    And also update if you rotate the screen.
    Also make sure the Canvas->Canvas Scaler->UI Scale Mode: is set to 'Scale With Screen Size' so the Texts scales properly
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class Loader : MonoBehaviour {
    4.  
    5.     public GameObject gameManager;
    6.  
    7. #if UNITY_IOS || UNITY_ANDROID || UNITY_WP8 || UNITY_IPHONE
    8.     private float sW;
    9.     private float sH;
    10. #endif
    11.  
    12.     void Awake()
    13.     {
    14.         if (GameManager.instance == null)
    15.         {
    16.             Instantiate(gameManager);
    17.         }
    18.     }
    19.  
    20. #if UNITY_IOS || UNITY_ANDROID || UNITY_WP8 || UNITY_IPHONE
    21.     public void Update()
    22.     {
    23.         sW = Screen.width;
    24.         sH = Screen.height;
    25.      
    26.         if (Screen.width < Screen.height)
    27.         {
    28.             Camera.main.orthographicSize = (5f / (sW / sH));
    29.         }
    30.         else if (Screen.width > Screen.height)
    31.         {
    32.             Camera.main.orthographicSize = 5;
    33.         }
    34.     }
    35. #endif
    36. }
    37.  
     
  41. ritchgee68

    ritchgee68

    Joined:
    Mar 25, 2017
    Posts:
    4
    I am new to scripting and I am having this error when I finish the level and step into the exit sign. I followed the supplement pdf for the GameManager script.

    NullReferenceException: Object reference not set to an instance of an object
    Completed.GameManager.OnSceneLoaded (Scene arg0, LoadSceneMode arg1) (at Assets/_Complete-Game/Scripts/GameManager.cs:69)
    UnityEngine.SceneManagement.SceneManager.Internal_SceneLoaded (Scene scene, LoadSceneMode mode) (at C:/buildslave/unity/build/artifacts/generated/common/runtime/SceneManagerBindings.gen.cs:245) I did not mistakenly use any of the completed scripts so I don't know why it is referring to (at Assets/_Complete-Game/Scripts/GameManager.cs:69)
     
  42. ritchgee68

    ritchgee68

    Joined:
    Mar 25, 2017
    Posts:
    4

    Everything works fine until ( except starts on Day 2), food walls, enemies, hit points when enemies attack... I even spent the day starting from scratch.... I step into the exit..... then I get exception... I know that Unity just got upgraded and the supplement has something to do with it...
     
  43. ritchgee68

    ritchgee68

    Joined:
    Mar 25, 2017
    Posts:
    4
    I put // in front of InitGame in Awake() and now she works ! Thanks...I don't know why you start at level 2 though..I have private int level = 2... and my game starts at 1..?
     
  44. Include

    Include

    Joined:
    Nov 20, 2014
    Posts:
    1
    Hi,

    I'm having trouble after "2D Roguelike 11 of 14 : Enemy Animator Controller" tutorial. I launch the game and the first level is fine. When I go to the exit the next level starts, but I can only move once, and even in to the blocking walls.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.UI;
    4. using System.Collections.Generic;
    5. using UnityEngine.SceneManagement;
    6.  
    7. public class GameManager : MonoBehaviour
    8. {
    9.     public float levelStartDelay = 2f;                  
    10.     public float turnDelay = 0.1f;                  
    11.     public int playerFoodPoints = 100;                
    12.     public static GameManager instance = null;        
    13.     [HideInInspector] public bool playersTurn = true;    
    14.  
    15.  
    16.     private BoardManager boardScript;                  
    17.     private int level = 0;                        
    18.     private List<Enemy> enemies;                      
    19.     private bool enemiesMoving;
    20.     private bool firstRun=true;
    21.  
    22.     void Awake()
    23.     {
    24.         if (instance == null)
    25.             instance = this;
    26.         else if (instance != this)
    27.             Destroy(gameObject);
    28.  
    29.         DontDestroyOnLoad(gameObject);
    30.  
    31.         enemies = new List<Enemy>();
    32.  
    33.         boardScript = GetComponent<BoardManager>();
    34.  
    35.         InitGame();
    36.     }
    37.  
    38.     void OnEnable()
    39.     {
    40.         SceneManager.sceneLoaded += OnLevelFinishedLoading;
    41.     }
    42.  
    43.     void OnDisable()
    44.     {
    45.         SceneManager.sceneLoaded -= OnLevelFinishedLoading;
    46.     }
    47.  
    48.  
    49.     void OnLevelFinishedLoading(Scene scene, LoadSceneMode mode)
    50.     {
    51.         if (firstRun)
    52.         {
    53.             firstRun = false;
    54.             return;
    55.         }
    56.  
    57.         instance.level++;
    58.         instance.InitGame();
    59.     }
    60.  
    61.     void InitGame()
    62.     {
    63.         enemies.Clear();
    64.  
    65.         boardScript.SetupScene(level);
    66.     }
    67.  
    68.     void Update()
    69.     {
    70.         if(playersTurn || enemiesMoving)
    71.             return;
    72.  
    73.         StartCoroutine (MoveEnemies ());
    74.     }
    75.  
    76.     public void AddEnemyToList(Enemy script)
    77.     {
    78.         enemies.Add(script);
    79.     }
    80.  
    81.     public void GameOver()
    82.     {
    83.         enabled = false;
    84.     }
    85.      
    86.     IEnumerator MoveEnemies()
    87.     {
    88.         enemiesMoving = true;
    89.  
    90.         yield return new WaitForSeconds(turnDelay);
    91.  
    92.         if (enemies.Count == 0)
    93.         {
    94.             yield return new WaitForSeconds(turnDelay);
    95.         }
    96.          
    97.         for (int i = 0; i < enemies.Count; i++)
    98.         {
    99.             enemies[i].MoveEnemy ();
    100.  
    101.             yield return new WaitForSeconds(enemies[i].moveTime);
    102.         }
    103.  
    104.         playersTurn = true;
    105.         enemiesMoving = false;
    106.     }
    107. }
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public abstract class MovingObject : MonoBehaviour {
    6.  
    7.     public float moveTime = 0.1f;
    8.     public LayerMask blockingLayer;
    9.  
    10.     private BoxCollider2D boxCollider;
    11.     private Rigidbody2D rb2D;
    12.     private float inverseMoveTime;
    13.  
    14.     // Use this for initialization
    15.     protected virtual void Start ()
    16.     {
    17.         boxCollider = GetComponent<BoxCollider2D> ();
    18.         rb2D = GetComponent<Rigidbody2D> ();
    19.         inverseMoveTime = 1f / moveTime;
    20.     }
    21.  
    22.     protected bool Move (int xDir, int yDir, out RaycastHit2D hit)
    23.     {
    24.         Vector2 start = transform.position;
    25.         Vector2 end = start + new Vector2 (xDir, yDir);
    26.  
    27.         boxCollider.enabled =false;
    28.         hit = Physics2D.Linecast (start, end, blockingLayer);
    29.         boxCollider.enabled = true;
    30.  
    31.         if (hit.transform == null)
    32.         {
    33.             StartCoroutine (SmoothMovement (end));
    34.             return true;
    35.         }
    36.         return false;
    37.     }
    38.      
    39.     protected IEnumerator SmoothMovement (Vector3 end)
    40.     {
    41.         float sqrRemainingDistance = (transform.position - end).sqrMagnitude;
    42.  
    43.         while (sqrRemainingDistance > float.Epsilon)
    44.         {
    45.             Vector3 newPosition = Vector3.MoveTowards (rb2D.position, end, inverseMoveTime * Time.deltaTime);
    46.             rb2D.MovePosition (newPosition);
    47.             sqrRemainingDistance = (transform.position - end).sqrMagnitude;
    48.             yield return null;
    49.         }
    50.     }
    51.  
    52.     protected virtual void AttemptMove <T> (int xDir, int yDir)
    53.         where T : Component
    54.     {
    55.         RaycastHit2D hit;
    56.         bool canMove = Move (xDir, yDir, out hit);
    57.  
    58.         if (hit.transform == null)
    59.             return;
    60.  
    61.         T hitComponent = hit.transform.GetComponent<T> ();
    62.  
    63.         if (!canMove && hitComponent != null)
    64.             OnCantMove (hitComponent);
    65.  
    66.     }
    67.  
    68.     protected abstract void OnCantMove <T> (T component)
    69.         where T : Component;
    70.  
    71. }
    72.  
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.SceneManagement;  
    4.  
    5.  
    6. public class Player : MovingObject
    7. {
    8.     public float restartLevelDelay = 1f;    
    9.     public int pointsPerFood = 10;        
    10.     public int pointsPerSoda = 20;        
    11.     public int wallDamage = 1;          
    12.  
    13.     private Animator animator;          
    14.     private int food;
    15.  
    16.     protected override void Start ()
    17.     {
    18.         animator = GetComponent<Animator>();
    19.  
    20.         food = GameManager.instance.playerFoodPoints;
    21.  
    22.         base.Start ();
    23.     }
    24.  
    25.  
    26.     private void OnDisable ()
    27.     {
    28.         GameManager.instance.playerFoodPoints = food;
    29.     }
    30.  
    31.  
    32.     private void Update ()
    33.     {
    34.         if(!GameManager.instance.playersTurn) return;
    35.  
    36.         int horizontal = 0;
    37.         int vertical = 0;
    38.  
    39.  
    40.         horizontal = (int) (Input.GetAxisRaw ("Horizontal"));
    41.         vertical = (int) (Input.GetAxisRaw ("Vertical"));
    42.  
    43.         if(horizontal != 0)
    44.         {
    45.             vertical = 0;
    46.         }
    47.  
    48.         if(horizontal != 0 || vertical != 0)
    49.         {
    50.             AttemptMove<Wall> (horizontal, vertical);
    51.         }
    52.     }
    53.      
    54.     protected override void AttemptMove <T> (int xDir, int yDir)
    55.     {
    56.         food--;
    57.         base.AttemptMove <T> (xDir, yDir);
    58.         RaycastHit2D hit;
    59.  
    60.         if (Move (xDir, yDir, out hit))
    61.         {
    62.          
    63.         }
    64.         CheckIfGameOver ();
    65.         GameManager.instance.playersTurn = false;
    66.     }
    67.      
    68.     protected override void OnCantMove <T> (T component)
    69.     {
    70.         Wall hitWall = component as Wall;
    71.         hitWall.DamageWall (wallDamage);
    72.         animator.SetTrigger ("playerChop");
    73.     }
    74.  
    75.     private void OnTriggerEnter2D (Collider2D other)
    76.     {
    77.         if (other.tag == "Exit") {
    78.             Invoke ("Restart", restartLevelDelay);
    79.             enabled = false;
    80.         }
    81.         else if(other.tag == "Food")
    82.         {
    83.             food += pointsPerFood;
    84.             other.gameObject.SetActive (false);
    85.         }
    86.         else if(other.tag == "Soda")
    87.         {
    88.             food += pointsPerSoda;
    89.             other.gameObject.SetActive (false);
    90.         }
    91.     }
    92.      
    93.     private void Restart ()
    94.     {
    95.         SceneManager.LoadScene (0);
    96.     }
    97.  
    98.     public void LoseFood (int loss)
    99.     {
    100.         animator.SetTrigger ("playerHit");
    101.  
    102.         food -= loss;
    103.  
    104.         CheckIfGameOver ();
    105.     }
    106.     private void CheckIfGameOver ()
    107.     {
    108.         if (food <= 0)
    109.         {
    110.             GameManager.instance.GameOver ();
    111.         }
    112.     }
    113. }
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Enemy : MovingObject
    5. {
    6.     public int playerDamage;                      
    7.  
    8.     private Animator animator;                      
    9.     private Transform target;                
    10.     private bool skipMove;                
    11.  
    12.     protected override void Start ()
    13.     {
    14.         GameManager.instance.AddEnemyToList (this);
    15.  
    16.         animator = GetComponent<Animator> ();
    17.  
    18.         target = GameObject.FindGameObjectWithTag ("Player").transform;
    19.  
    20.         base.Start ();
    21.     }
    22.      
    23.     protected override void AttemptMove <T> (int xDir, int yDir)
    24.     {
    25.         if(skipMove)
    26.         {
    27.             skipMove = false;
    28.             return;
    29.  
    30.         }
    31.          
    32.         base.AttemptMove <T> (xDir, yDir);
    33.  
    34.         skipMove = true;
    35.     }
    36.      
    37.     public void MoveEnemy ()
    38.     {
    39.         int xDir = 0;
    40.         int yDir = 0;
    41.  
    42.         if(Mathf.Abs (target.position.x - transform.position.x) < float.Epsilon)
    43.             yDir = target.position.y > transform.position.y ? 1 : -1;
    44.         else
    45.             xDir = target.position.x > transform.position.x ? 1 : -1;
    46.  
    47.         AttemptMove <Player> (xDir, yDir);
    48.     }
    49.      
    50.     protected override void OnCantMove <T> (T component)
    51.     {
    52.         Player hitPlayer = component as Player;
    53.  
    54.         hitPlayer.LoseFood (playerDamage);
    55.  
    56.         animator.SetTrigger ("enemyAttack");
    57.     }
    58. }
     
  45. xjoel

    xjoel

    Joined:
    Jan 15, 2017
    Posts:
    1
    Thanks, you pointed me to the solution :)
     
  46. DGH1988

    DGH1988

    Joined:
    Apr 27, 2017
    Posts:
    4
    Hi all,
    I see this thread is still active, awesome!
    Let's say I want to replace floor tiles and player sprites with some of my own work. Is there anyway around the fact that it is all 32x32 pixels? If I add my own artwork it keeps its real size (downsizing is not an option because I am not into pixel art) but positions it on the grid as if it is the 32x32.

    So my solution would be to have the boardmanager.cs lay things out in a way that there is enough room for bigger sprites but still have all the player movements etc. work properly. The problem is, I don't know how.

    In case that isn't clear enough, what would be needed to replace the 32x32 floor sprites with let's say, 150x150 floor sprites without messing everything up since simple drag and drop to the Sprite Renderer will do this.

    Any advice, pointers or general info would be much appreciated and thanks in advance already!

    PS. I followed the tutorial without trouble but am a beginner with Unity and new to C#. I read up on it a bit and have some light/moderate experience in JS, TCL and HTML.
     
  47. ngmingchiat

    ngmingchiat

    Joined:
    Apr 27, 2017
    Posts:
    6
    HI i like to ask about the video 4 on the
    1)c# script mine is totally different when i open it, how i gonna change so that it is correct
    https://drive.google.com/open?id=0BwWz8Rjue85ocmxBOWlQWksyMGM
    2)can i change the sequence ??
    exp. = using UnityEngine;
    L using System.Collections;
    to
    = using System.Collections;
    L using UnityEngine;

    exp2 = using UnityEngine;
    L using System;
    L using System.Collections.Generic;
    L using Random = UnityEngine.Random;
    to

    = using UnityEngine;
    L using System;
    L using Random = UnityEngine.Random;
    L using System.Collections.Generic;
     
  48. MadMax1992

    MadMax1992

    Joined:
    Apr 17, 2017
    Posts:
    1
    Hi guys
    I have a question about the Script BoardManager.cs (in the Complete-Game Version).

    why should i use a Vector3 in line 41 ?

    this line:

    Code (CSharp):
    1. private List <Vector3> gridPositions = new List <Vector3> ();    //A list of possible locations to place tiles.
    Could i use a Vector2 as well ?


    And in line 114
    Code (CSharp):
    1. int objectCount = Random.Range (minimum, maximum+1);
    Why should i coose maximum "+1"?

    Can anybody please explain me why we should add 1 to maximum ?



    Great Videos
    Thanks
     
    Last edited: Apr 30, 2017
  49. Sil3ntxNinja

    Sil3ntxNinja

    Joined:
    May 2, 2017
    Posts:
    1
    Could you please help with this could I can't figure out how to use the Delegates for the GameManager.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using UnityEngine.SceneManagement;
    6.  
    7.  
    8. public class GameManager : MonoBehaviour
    9. {
    10.     public float levelStartDelay = 2f;
    11.     public float turnDelay = .1f;
    12.     public static GameManager instance = null;
    13.     public BoardManager boardScript;
    14.     public int playerFoodPoints = 100;
    15.     [HideInInspector] public bool playersTurn = true;
    16.  
    17.  
    18.     private Text levelText;
    19.     private GameObject levelImage;
    20.     private int level = 1;
    21.     private List<Enemy> enemies;
    22.     private bool enemiesMoving;
    23.     private bool doingSetup;
    24.  
    25.     void Awake()
    26.     {
    27.         if (instance == null)
    28.             instance = this;
    29.         else if (instance != this)
    30.             Destroy(gameObject);
    31.  
    32.         DontDestroyOnLoad(gameObject);
    33.         enemies = new List<Enemy>();
    34.         boardScript = GetComponent<BoardManager>();
    35.         InitGame();
    36.     }
    37.  
    38.     private void SceneManager.sceneLoaded()
    39.     {
    40.    
    41.     }
    42.  
    43.     void OnLevelFinishedLoading(Scene scene, LoadSceneMode mode)
    44.     {
    45.         level++;
    46.         InitGame();
    47.     }
    48.  
    49.     void OnEnable()
    50.     {
    51.         SceneManager.sceneLoaded += OnLevelFinishedLoading;
    52.     }
    53.  
    54.     void OnDisable()
    55.     {
    56.         SceneManager.sceneLoaded -= OnLevelFinishedLoading;
    57.     }
    58.  
    59.     void InitGame()
    60.     {
    61.         doingSetup = true;
    62.  
    63.         levelImage = GameObject.Find("LevelImage");
    64.         levelText = GameObject.Find("LevelText").GetComponent<Text>();
    65.         levelText.text = "Day " + level;
    66.         levelImage.SetActive(true);
    67.         Invoke("HideLevelImage", levelStartDelay);
    68.  
    69.         enemies.Clear();
    70.         boardScript.SetupScene(level);
    71.     }
    72.  
    73.     private void HideLevelImage()
    74.     {
    75.         levelImage.SetActive(false);
    76.         doingSetup = false;
    77.     }
    78.  
    79.     public void GameOver()
    80.     {
    81.         levelText.text = "After " + level + " days, you starved";
    82.         levelImage.SetActive(true);
    83.         enabled = false;
    84.     }
    85.  
    86.     void Update()
    87.     {
    88.         if (playersTurn || enemiesMoving || doingSetup)
    89.             return;
    90.  
    91.         StartCoroutine(MoveEnemies());
    92.     }
    93.  
    94.     public void AddEnemyToList(Enemy script)
    95.     {
    96.         enemies.Add(script);
    97.     }
    98.  
    99.     IEnumerator MoveEnemies()
    100.     {
    101.         enemiesMoving = true;
    102.         if (enemies.Count == 0)
    103.         {
    104.             yield return new WaitForSeconds(turnDelay);
    105.         }
    106.  
    107.         for (int i = 0; i < enemies.Count; i++)
    108.         {
    109.             enemies[i].MoveEnemy();
    110.             yield return new WaitForSeconds(enemies[i].moveTime);
    111.         }
    112.  
    113.         playersTurn = true;
    114.         enemiesMoving = false;
    115.     }
    116.  
    117.  
    118. }
     
  50. gwnguy

    gwnguy

    Joined:
    Apr 25, 2017
    Posts:
    144
    I too had the level skipping by 2 counts and starting at level 2 (then 4,6,8,...)
    Reading the comments saw the solution so excellently described JRWidley by this post (#912).
    +30 food=Rare Prime Rib points to you!
     
    JRWidley likes this.
Thread Status:
Not open for further replies.