Search Unity

TouchPhase question. [SOLVED]

Discussion in 'Scripting' started by topherbwell, Jan 27, 2016.

  1. topherbwell

    topherbwell

    Joined:
    Jun 8, 2015
    Posts:
    180
    Hello,
    I have a 2d side scrolling game that uses a mario- style jump mechanic, as well as a double- jump mechanic.

    Previously, I was using getmousebuttondown, getmousebutton, and getmousebuttonup, but have recently begun the work of integrating proper mobile control instead.

    The mechanic should work as follows: the player touches the screen and the player character jumps. If the player keeps his finger on the screen the player will continue to jump higher, and if the player takes his finger off of the screen then the player will stop jumping. I have all the usual bools and ground checks and such to determine whether I am grounded, whether I can double jump, how long I have been jumping, etc.

    Now that I am using touch control, it seems there is a lag between TouchPhase.Began and TouchPhase.Stationary. Previously in my code these were the Input.GetMouseButtonDown and Input.GetMouseButton. The behavior now is that when you touch the screen, the player jumps, then kind of slows down as if he is not applying force for a moment, then continues to jump upward as he should.

    My code is looking like:

    Code (CSharp):
    1. public class PlayerController : MonoBehaviour
    2. {
    3.     public float moveSpeed;
    4.  
    5.     //jump
    6.     public float jumpForce;
    7.     public float jumpTime;
    8.     public float jumpTimeCounter;
    9.  
    10.     //variables for ground detection
    11.     public bool grounded;
    12.     public LayerMask whatIsGround;
    13.     public bool stoppedJumping;
    14.     public bool canDoubleJump;
    15.     public Transform groundCheck;
    16.     public float groundCheckRadius;
    17.  
    18.     private Rigidbody2D rb;
    19.  
    20.     void Start ()
    21.     {
    22.         rb = GetComponent<Rigidbody2D>();
    23.  
    24.         jumpTimeCounter = jumpTime;
    25.         stoppedJumping = true;
    26.         canDoubleJump = true;
    27.     }
    28.  
    29.     void Update ()
    30.     {
    31.         //defines the number of touches
    32.         int theTouches = Input.touchCount;
    33.         if(theTouches > 0)
    34.         {
    35.             print(theTouches + " touch(es) detected");
    36.  
    37.             for (int i = 0; i < theTouches; i++)
    38.             {
    39.                 Touch touch = Input.GetTouch(i);
    40.  
    41.                 print("Touch index " + touch.fingerId + " detected at position " + touch.position);
    42.             }
    43.         }
    44.         //detect whether the player is touching the ground
    45.         grounded = Physics2D.OverlapCircle (groundCheck.position, groundCheckRadius, whatIsGround);
    46.  
    47.         if(grounded)
    48.         {
    49.             jumpTimeCounter = jumpTime;
    50.             canDoubleJump = true;
    51.         }
    52.     }
    53.  
    54.     void FixedUpdate()
    55.     {
    56.         rb.velocity = new Vector2 (moveSpeed , rb.velocity.y);
    57.  
    58.         foreach (Touch touch in Input.touches)
    59.         {
    60.             int pointerID = touch.fingerId;
    61.             if (EventSystem.current.IsPointerOverGameObject(pointerID))
    62.             {
    63.                 // at least one touch is over a canvas UI
    64.                 return;
    65.             }
    66.  
    67.             if (touch.phase == TouchPhase.Ended)
    68.             {
    69.                 // here we don't know if the touch was over an canvas UI
    70.                 return;
    71.             }
    72.  
    73.  
    74.             if(Input.GetTouch(0).phase == TouchPhase.Began)
    75.             {
    76.                 if(grounded)
    77.                 {
    78.                     rb.velocity = new Vector2 (rb.velocity.x, jumpForce);
    79.                     stoppedJumping = false;
    80.                     jumpSound.Play();
    81.                 }
    82.  
    83.                 if(!grounded && canDoubleJump)
    84.                 {
    85.                     rb.velocity = new Vector2 (rb.velocity.x, jumpForce);
    86.                     jumpTimeCounter = jumpTime;
    87.                     stoppedJumping = false;
    88.                     canDoubleJump = false;
    89.                     anim.SetBool("isRocketing", false);
    90.                     anim.SetBool ("doubleJump", true);
    91.  
    92.                     jumpSound.Play();
    93.                 }
    94.             }
    95.  
    96.             if((Input.GetTouch(0).phase == TouchPhase.Stationary) && !stoppedJumping)
    97.             {
    98.                 if(jumpTimeCounter > 0)
    99.                 {
    100.                     rb.velocity = new Vector2 (rb.velocity.x, jumpForce);
    101.                     jumpTimeCounter -= Time.deltaTime;
    102.                 }
    103.             }
    104.  
    105.             if(Input.GetTouch(0).phase == TouchPhase.Ended)
    106.             {
    107.                 jumpTimeCounter = 0;
    108.                 stoppedJumping = true;
    109.             }
    110.         }
    111.     }
     
    Last edited: Jan 27, 2016
  2. topherbwell

    topherbwell

    Joined:
    Jun 8, 2015
    Posts:
    180
    It seems as if there is some time between when the touch began and when it is counted as stationary; with mouse it seems to go directly from getMouseDown to GetMouse, without any time in between.

    Is there a way to adjust the amount of time between phases so that I can make this jump mechanic feel more natural and behave the way I intended? Thanks in advance!
     
  3. topherbwell

    topherbwell

    Joined:
    Jun 8, 2015
    Posts:
    180
    Bump. Anyone have experience with this?
     
  4. topherbwell

    topherbwell

    Joined:
    Jun 8, 2015
    Posts:
    180
    Bueller?
     
  5. topherbwell

    topherbwell

    Joined:
    Jun 8, 2015
    Posts:
    180
    Third day and no responses?
     
  6. ADNCG

    ADNCG

    Joined:
    Jun 9, 2014
    Posts:
    994
    GetMouseButton returns when the respective mouse button is held, regardless of wether or not it is stationary.

    TouchPhase.Stationary returns if the touch position hasn't move since the last frame. If it moved, TouchPhase.Moved is returned instead.

    It is likely that you are missing a few frames because the finger has slightly moved since the last frame. To avoid that, you should also listen to TouchPhase.Moved
     
  7. topherbwell

    topherbwell

    Joined:
    Jun 8, 2015
    Posts:
    180
    Hey thanks I will try this and that totally makes sense if that it the case!
     
    ADNCG likes this.
  8. topherbwell

    topherbwell

    Joined:
    Jun 8, 2015
    Posts:
    180
    I've been pretty busy the last few days with another project but got back around this morning to this; this solution worked perfectly. The jump behaviour works as intended now and Fujik hit the nail on the head; it looks like maybe a few touchphase.Moved frames were being detected just after touchphase.Began.

    Thanks Fujik!

    I changed the following line to include listening for TouchPhase.Moved:
    Code (CSharp):
    1. if((Input.GetTouch(0).phase == TouchPhase.Stationary) && !stoppedJumping || (Input.GetTouch(0).phase == TouchPhase.Moved) && !stoppedJumping)