Search Unity

2D mobile game, finding the player after death

Discussion in 'Scripting' started by Browdaddy96, Aug 27, 2015.

  1. Browdaddy96

    Browdaddy96

    Joined:
    Aug 27, 2015
    Posts:
    82
    I have all of my player's movements controllers in a "Button" script. The button scripts stops working after the player dies(which destroys the game object and then after a few seconds it "respawns him"). My find player method doesn't work for some reason though. Please help me.

    Button Script is the attached file.
     

    Attached Files:

  2. BenZed

    BenZed

    Joined:
    May 29, 2014
    Posts:
    524
    I see a couple problems here, I've made annotations. Make double sure that the Player gameObject you're instantiating has the "Player" tag.

    Annotations:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Button : MonoBehaviour {
    5.     public enum buttonController { MoveLeft, MoveRight, Jump};
    6.     public buttonController buttonType; // see @1
    7.     TouchManager touchManager; // never assigned or read
    8.  
    9.     public float jumpHeight = 5.0f; // see @1
    10.     public float moveSpeed = 5.0f;// see @1
    11.     public GameObject player;// see @1
    12.  
    13.     public Color defaultColor;// see @1
    14.     public Color selectedColor;// see @1
    15.  
    16.     // I'm imagining that this is only here for debugging purposes, so that you can see in the inspector
    17.     // weather the button is being touched or not. Is that true? Otherwise, if other scripts need it,
    18.     // it should be a property. Only this code should be able to set weather the button is being touched
    19.     // or not.
    20.     public bool touchingButton = false; //<
    21.  
    22.     //This is never assigned, either. I feel like you should just be using playerController.grounded
    23.     public bool grounded;// <
    24.  
    25.     // @1: Do these need to be public, or just serialized so you can see them in the inspector?
    26.     // Start using the [SerializeField] attribute.
    27.  
    28.     private float jumpTimer = .2f;
    29.     private float jumpCD = .2f;
    30.  
    31.  
    32.     private PlayerController playerController;
    33.     private Animator anim;
    34.     private Material mat;
    35.  
    36.     void Start()
    37.     {
    38.         // Without seeing your scene it's hard to be sure, but I feel like even if you
    39.         // weren't having trouble finding your player, it wouldn't have access to any
    40.         // of these components once the player gameObject has been deleted and remade.
    41.         playerController = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerController>();
    42.         anim = player.GetComponent<Animator>();
    43.  
    44.         mat = GetComponent<Renderer>().material;
    45.         mat.color = defaultColor;
    46.  
    47.         //This is a fine place to start a coroutine.
    48.         //I don't think a coroutein is necessary for your SearchForPlayer function,
    49.         //but this is correct, otherwise.
    50.         StartCoroutine(SearchForPlayer(player));
    51.     }
    52.  
    53.     void Update()
    54.     {
    55.         if (jumpTimer > 0)
    56.         {
    57.             jumpTimer -= Time.deltaTime; //I'd use a timestamp rather than constantly decrementing by deltaTime
    58.         }
    59.         if (jumpTimer < 0)
    60.         {
    61.             jumpTimer = 0;
    62.         }
    63.         if (player == null)
    64.         {
    65.             //@2: This is not correct. You're starting a coroutine every frame,
    66.             //without checking if it's running or not.
    67.             //do (player == null && !isSearchingForPlayer), or something
    68.             StartCoroutine(SearchForPlayer(player));
    69.         }
    70.     }
    71.  
    72.     void OnTouchDown()
    73.     {
    74.         mat.color = selectedColor;
    75.         touchingButton = true;
    76.  
    77.         //I'm assuming since buttonType is never set, that you set it in the inspector
    78.         //and have three of these buttons, each with this script assigned to it.
    79.         switch (buttonType)
    80.         {
    81.             case buttonController.Jump:
    82.                 //@3: Rather than make the comparison in each switch case, you should
    83.                 // do it before hand.
    84.                 if (player == null)
    85.                 {
    86.                     StartCoroutine(SearchForPlayer(player));
    87.                 }
    88.                 if (playerController.grounded == true)
    89.                 {
    90.                     //Cache the rigidbody component instead of Getting it every time you jump
    91.                     player.GetComponent<Rigidbody2D>().AddForce(Vector2.up * jumpHeight, ForceMode2D.Impulse);
    92.                     //@4: look into using hash codes to find animation parameters, it's much quicker than
    93.                     //using a string. Additionally, if you're doing this frequently, I'd put it in a property.
    94.                     anim.SetBool("Grounded", grounded);
    95.                 }
    96.                 break;
    97.             case buttonController.MoveLeft:
    98.                    //see @3
    99.                 if (player == null)
    100.                 {
    101.                     StartCoroutine(SearchForPlayer(player));
    102.                 }
    103.                 player.transform.Translate(-Vector2.right * moveSpeed * Time.deltaTime);
    104.                 player.transform.localScale = new Vector3(-1, 1, 1);
    105.                 anim.SetFloat("Speed", 5f); // see @4
    106.                 break;
    107.             case buttonController.MoveRight:
    108.                 //see @3
    109.                 if (player == null)
    110.                 {
    111.                     StartCoroutine(SearchForPlayer(player));
    112.                 }
    113.                 player.transform.Translate(Vector2.right * moveSpeed * Time.deltaTime);
    114.                 player.transform.localScale = new Vector3(1, 1, 1);
    115.                 anim.SetFloat("Speed", 5f); // see @4
    116.                 break;
    117.         }
    118.     }
    119.  
    120.     void OnTouchUp()
    121.     {
    122.         mat.color = defaultColor;
    123.         anim.SetFloat("Speed", 0f); // see @4
    124.         touchingButton = false;
    125.     }
    126.  
    127.     //it looks to me like OnTouchDown differs very litle from OnTouchStay. Don't write the same block of code
    128.     //twice. Use functions.
    129.     void OnTouchStay()
    130.     {
    131.         mat.color = selectedColor;
    132.         touchingButton = true;
    133.         switch (buttonType)
    134.         {
    135.            case buttonController.Jump:
    136.                 // see @2
    137.                 if (player == null)
    138.                 {
    139.                     StartCoroutine(SearchForPlayer(player));
    140.                 }
    141.                 if (playerController.grounded == true)
    142.                 {
    143.  
    144.                     //jumpTimer is a flot, so you should never be making exact comparisons to zero.
    145.                     //use Mathf.Approximatly(jumpTimer, 0f) or jumpTimer <= 0f instead. I realize
    146.                     //you set jumpTimer to 0 if it's less than 0, but that is sloppy.
    147.                     if (jumpTimer == 0)
    148.                     {
    149.                         //Cache the rigidbody component instead of Getting it every time you jump.
    150.                         player.GetComponent<Rigidbody2D>().AddForce(Vector2.up * jumpHeight, ForceMode2D.Impulse);
    151.                         anim.SetBool("Grounded", grounded); // see @4
    152.                         jumpTimer = jumpCD;
    153.                     }
    154.                 }
    155.                 else
    156.                     return;
    157.                 break;
    158.                
    159.             case buttonController.MoveLeft:
    160.                 //see @2
    161.                 if (player == null)
    162.                 {
    163.                     StartCoroutine(SearchForPlayer(player));
    164.                 }
    165.                 player.transform.Translate(-Vector2.right * moveSpeed * Time.deltaTime); //I'm not sure onTouchS
    166.                 player.transform.localScale = new Vector3(-1, 1, 1);
    167.                 anim.SetFloat("Speed", 5f); // see @4
    168.                 break;
    169.             case buttonController.MoveRight:
    170.                 //see @2
    171.                 if (player == null)
    172.                 {
    173.                     StartCoroutine(SearchForPlayer(player));
    174.                 }
    175.                 player.transform.Translate(Vector2.right * moveSpeed * Time.deltaTime);
    176.                 player.transform.localScale = new Vector3(1, 1, 1);
    177.                 anim.SetFloat("Speed", 5f); // see @4
    178.                 break;
    179.         }
    180.     }
    181.  
    182.     void OnTouchExit()
    183.     {
    184.         anim.SetFloat("Speed", 0f); // see @4
    185.         mat.color = defaultColor;
    186.         touchingButton = false;
    187.     }
    188.  
    189.     //It doesn't seem to me that this needs to be a coroutine at all, especailly
    190.     //with all the problems above with you calling it every frame.
    191.     //You also don't need to pass the _player gameObejct into it, since you have access
    192.     //to the player variable in the class.
    193.     IEnumerator SearchForPlayer(GameObject _player)
    194.     {
    195.         // {
    196.         _player = GameObject.FindGameObjectWithTag("Player");
    197.         if (_player != null)
    198.         {
    199.             player = _player.gameObject;
    200.         }
    201.         else
    202.         {
    203.             yield return new WaitForSeconds(0.5f);
    204.         }
    205.         // } < yikes
    206.     }
    207. }
    208.  
    Example Refactor:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Button : MonoBehaviour {
    5.    
    6.     #region Nested
    7.    
    8.     public enum ControllerType
    9.     {
    10.         MoveLeft,
    11.         MoveRight,
    12.         Jump  
    13.     }
    14.    
    15.     #endregion
    16.    
    17.     #region Settings
    18.  
    19.     [SerializeField] ControllerType type;
    20.    
    21.     [SerializeField] float jumpHeight;
    22.     [SerializeField] float moveSpeed;
    23.    
    24.     [SerializeField] Color defaultColor;
    25.     [SerializeField] Color selectedColor;
    26.    
    27.     [SerializeField] float jumpInterval;
    28.     float jumpTimeStamp = 0f;
    29.    
    30.     #endregion
    31.    
    32.     #region References
    33.    
    34.     GameObject player;
    35.     PlayerController controller;
    36.     Animator anim;
    37.     Rigidbody2D body;
    38.     Material mat;
    39.    
    40.     #endregion
    41.    
    42.     #region Anim Properties
    43.    
    44.     bool animGrounded {
    45.         set {
    46.             anim.SetBool("Grounded", value);
    47.         }  
    48.     }
    49.    
    50.     float animSpeed {
    51.         set {
    52.             anim.SetFloat("Speed", value);
    53.         }
    54.     }
    55.    
    56.     #endregion
    57.    
    58.     #region Unity Callers
    59.    
    60.     void Start()
    61.     {
    62.         FindPlayer();
    63.         mat = GetComponent<Renderer>().material;
    64.     }
    65.  
    66.     void OnTouchDown()
    67.     {
    68.         DoButtonAction();
    69.     }
    70.    
    71.     void OnTouchStay()
    72.     {
    73.         DoButtonAction();
    74.     }
    75.  
    76.     void OnTouchExit()
    77.     {
    78.         if (anim)
    79.             animSpeed = 0f;
    80.        
    81.         mat.color = defaultColor;
    82.     }
    83.  
    84.     #endregion
    85.  
    86.     #region Helper
    87.     //Returns true if the player was found, false otherwise
    88.     bool FindPlayer()
    89.     {
    90.         player = GameObject.FindGameObjectWithTag("Player");
    91.         if (!player)
    92.             return false;
    93.        
    94.         controller = player.GetComponent<PlayerController>();
    95.         anim = player.GetComponent<Animator>();
    96.         body = player.GetComponent<Rigidbody2D>();
    97.  
    98.         return true;
    99.     }  
    100.  
    101.     void DoButtonAction()
    102.     {
    103.         mat.color = selectedColor;
    104.        
    105.         if (!player && !FindPlayer())
    106.             return;
    107.        
    108.         if (type == ControllerType.Jump)
    109.             TryJump();
    110.         else
    111.             TryMove(type);
    112.     }
    113.  
    114.     void TryJump()
    115.     {
    116.         animGrounded = controller.isGrounded;
    117.  
    118.         bool canJump = controller.isGrounded && Time.time > jumpTimeStamp + jumpInterval;
    119.         if (!canJump)
    120.             return;
    121.  
    122.         jumpTimeStamp = Time.time;
    123.         body.AddForce(Vector2.up * jumpHeight, ForceMode2D.Impulse);
    124.     }
    125.  
    126.     void TryMove(ControllerType moveType)
    127.     {
    128.  
    129.         bool left = moveType == ControllerType.MoveLeft;
    130.  
    131.         float flipX = left ? -1f : 1f;
    132.         Vector2 moveDir = left ? -Vector2.right : Vector2.right;
    133.  
    134.         player.transform.Translate(moveDir * moveSpeed * Time.deltaTime);
    135.         player.transform.localScale = new Vector3(flipX, 1f, 1f);
    136.         animSpeed = 5f;
    137.     }
    138.  
    139.     #endregion
    140. }
     
  3. Browdaddy96

    Browdaddy96

    Joined:
    Aug 27, 2015
    Posts:
    82
    Thank you very much for both, the commented script on what was wrong and the correct script. The commented script taught me a lot. Thank you.
     
    BenZed likes this.