Search Unity

how to move player one step on touch?

Discussion in 'Scripting' started by javaBroker, Sep 22, 2017.

  1. javaBroker

    javaBroker

    Joined:
    Jun 14, 2017
    Posts:
    11
    Hello, Currently my player keep moving forward and keep to move right or left if I keep touching the screen. What I want the player to do is to move a fixed amount of distance to the right or left when tap on the screen. Even if I keep touch it.

    The code I have right now is mimic the GetAxis of the keyboard with the right sensitivity, if you like to see how it done in touch, here is the thread.

    I can't figure out what changes I need to make in my code to make it work that way. I have tried TouchPhase.Began but no luck. Here is the code I'm using now to control the player:

    Code (CSharp):
    1. void Update() {
    2.          if (Input.touchCount > 0) {
    3.              touchPosition = Input.GetTouch (0).position;
    4.              if (touchPosition.x > screenCenter) {
    5.                  target = 1;
    6.              }
    7.              if (touchPosition.x < screenCenter) {
    8.                  target = -1;
    9.              }
    10.              moveHorizontal = Mathf.MoveTowards (moveHorizontal, target, sensitivity * Time.deltaTime);
    11.          } else {
    12.              moveHorizontal = Mathf.MoveTowards (moveHorizontal, 0, sensitivity * Time.deltaTime);
    13.          }
    14.              movement = new Vector3 (moveHorizontal, 0.0f, 0.0f);
    15.      }
    16.  
    17. void FixedUpdate () {
    18.          rb.velocity = movement * speedHorizontal;
    19.              //restrict movement to boundaries
    20.              if (transform.position.x <= xMin) {
    21.                  transform.position = new Vector3 (xMin, transform.position.y, transform.position.z);
    22.              }
    23.              if (transform.position.x >= xMax) {
    24.                  transform.position = new Vector3 (xMax, transform.position.y, transform.position.z);
    25.              }
    26.              //tilt the player when move horizontal
    27.              rb.rotation = Quaternion.Euler (0.0f, 0.0f, rb.velocity.x * -tilt);
    28.              //keep move forward while playing
    29.              rb.velocity += Vector3.forward * speedForward;
    30.      }
    Here is what I have tried, got to move the player one step each touch, however the transform is fast and no tilt

    Code (CSharp):
    1. Vector3 temp = rb.position;
    2.  
    3. void Update() {
    4.  
    5.        if (Input.touchCount > 0) {
    6.  
    7.            if (Input.GetTouch(0).phase == TouchPhase.Began) {
    8.  
    9.            touchPosition = Input.GetTouch (0).position;
    10.  
    11.            if (touchPosition.x > screenCenter) {
    12.                    end_pos = 2f;
    13.                    if (temp.x < 4) {
    14.                    temp.x += end_pos;
    15.                    }
    16.            }
    17.            if (touchPosition.x < screenCenter) {
    18.                    end_pos = 2f;
    19.                    if (temp.x > -4) {
    20.                    temp.x -= end_pos;
    21.                    }
    22.            }
    23.  
    24.            }
    25.  
    26.        } else {
    27.            temp = rb.position;
    28.        }
    29.    }
    30.  
    31.    void FixedUpdate () {
    32.  
    33.        rb.position = temp;
    34. }
    Can you help me plese and tell me what should I try?
    thank you for your time.
     
  2. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    Mix the two. Use the first code, but add the target changing between 1 and -1 only inside TouchPhase.Begin like in the second. Then use Mathf.MoveTowards() outside of the touch phase to move to the last selected target spot.
     
  3. javaBroker

    javaBroker

    Joined:
    Jun 14, 2017
    Posts:
    11
    thank you for your replay. I tried what you suggested and it's working except one problem: player is moving now only when tap on the screen which is what I wanted. but he is not moving in a fixed amount of distance. for example I want him to move 2 units on the X but he move in a different float value each time such as 1.869 units and if i try to move him back to 0 then he always come back to 0 at different values such as 0.126, 0.420 etc

    do you have any idea what can I modify in the code to move him the fixed amount of distance?
    maybe it's something to do with the sensitivity of the touch or the update function?

    I did Debuging to check how the player move in real time and to my surprise he is moving the amount needed all the way till the end of the distance but only in CODE. because in the EDITOR in the transform values I can see the X position is a Float...

    here is the code as is now:

    Code (CSharp):
    1.  
    2. void Update() {
    3.  
    4.        if (Input.touchCount > 0) {
    5.  
    6.            if (Input.GetTouch(0).phase == TouchPhase.Began) {
    7.          
    8.            touchPosition = Input.GetTouch (0).position;
    9.          
    10.            if (touchPosition.x > screenCenter) {
    11.                target = 2f;
    12.            }
    13.            if (touchPosition.x < screenCenter) {
    14.                target = -2f;
    15.            }
    16.                isTap = true;
    17.                //moveHorizontal = Mathf.MoveTowards (moveHorizontal, target, sensitivity * Time.deltaTime);
    18.            }
    19.        }
    20.  
    21.        if (isTap == true) {
    22.            moveHorizontal = Mathf.MoveTowards (moveHorizontal, target, sensitivity * Time.deltaTime);
    23.            if (moveHorizontal == 2f || moveHorizontal == -2f) {
    24.                isTap = false;
    25.            }
    26.        }
    27.  
    28.        if (isTap == false) {
    29.            moveHorizontal = Mathf.MoveTowards (moveHorizontal, 0, sensitivity * Time.deltaTime);
    30.        }
    31.  
    32.        movement = new Vector3 (moveHorizontal, 0.0f, 0.0f);
    33.    }

    Code (CSharp):
    1. void FixedUpdate () {
    2.  
    3.        rb.velocity = movement * speedHorizontal;
    4.  
    5.            //restrict movement to boundaries
    6.            if (transform.position.x <= xMin) {
    7.                transform.position = new Vector3 (xMin, transform.position.y, transform.position.z);
    8.            }
    9.            if (transform.position.x >= xMax) {
    10.                transform.position = new Vector3 (xMax, transform.position.y, transform.position.z);
    11.            }
    12.  
    13.            //tilt the player when move horizontal
    14.        rb.rotation = Quaternion.Euler (0.0f, 0.0f, rb.velocity.x * -tilt);
    15.  
    16.            //keep move forward while playing
    17.          rb.velocity += Vector3.forward * speedForward;
    18.    }
     
    Last edited: Sep 30, 2017
  4. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Can I ask if what you want is to be able to move +/- 2 based on where you tap the screen?

    If that's the case, I think you can move all of your code to be within Update() and ignore fixed update (this part is semi unrelated, just an observation).

    Adjust your 'target' by +/- 2 .. set your velocity, and then clamp your position (so it doesn't go off screen, as you're already doing). And an additional clamp for the target position - I think that would work.

    This assumes you want to use the physics system for collisions somehow/somewhere else, otherwise you could just as easily move the transform instead.
     
  5. javaBroker

    javaBroker

    Joined:
    Jun 14, 2017
    Posts:
    11
    yes, that is what i want to achive. if you tap on left half of the screen, player move -2, if tap on the right half player move +2. the idea of clamp the target is sounds good. but i even cant think of how to actually implement that on real time in update.. I have tried another way of code which make the player move exactly as I want but there is no tilt working. more than that, i'm able to rotate only to the right side and the rotation if full 360' instead of 7' i wish to each side. so if to solve the tilt issue, my player will be able to do what i tried..

    Code (CSharp):
    1.  
    2.  
    3.  float end_pos = 2;
    4.  
    5. void Update() {
    6.        
    7.         if (Input.touchCount > 0) {
    8.  
    9.             if (Input.GetTouch(0).phase == TouchPhase.Began) {
    10.                
    11.                 touchPosition = Input.GetTouch (0).position;
    12.  
    13.                 if (touchPosition.x > screenCenter && isTap == false) {
    14.  
    15.                     if (tempX < 4) {
    16.                         tempX += end_pos;
    17.                         target = -1;
    18.                         isTap = true;
    19.                     }
    20.                 }
    21.  
    22.                 if (touchPosition.x < screenCenter && isTap == false) {
    23.                     if (tempX > -4) {
    24.                         tempX -= end_pos;
    25.                         target = 1;
    26.                         isTap = true;
    27.                     }
    28.                 }
    29.             }
    30.         }
    31.        
    32.         if (isTap == true) {
    33.             currentLerpTime += Time.deltaTime;
    34.             if (currentLerpTime >= lerpTime) {
    35.                 currentLerpTime = lerpTime;
    36.                 isTap = false;
    37.             }
    38.             perc = currentLerpTime/lerpTime;
    39.             Vector3 rbV = rb.position;
    40.             Vector3 rbVnew = new Vector3(tempX,rb.position.y,rb.position.z);
    41.             rb.position = Vector3.Lerp(rb.position,rbVnew,perc);
    42.            
    43.             float z = target * 7f;
    44.             euler = rb.transform.localEulerAngles;
    45.             euler.z = Mathf.Lerp(euler.z, z, 3f * Time.deltaTime);
    46.            rb.transform.localEulerAngles = euler;
    47.         }
    48.         if (isTap == false) {
    49.             currentLerpTime = 0;
    50.             euler = rb.transform.localEulerAngles;
    51.             euler.z = Mathf.Lerp(euler.z, 0, 2f * Time.deltaTime);
    52.            rb.transform.localEulerAngles = euler;
    53.         }
    54.        
    55.     }
     
  6. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Was the tilt working in your earlier example? If so, just keep it like that and try the suggestion that I made?

    Also, quick question.. can you only be in 1 of 3 positions? -2 , 0 , and +2? It seems that's all you calculate, so just curious if you could be at -4 or -10 or -12 or 24 or anything else lol

    As for clamping to the position, if you adjust the target with each tap, you could "clamp" .. maybe for example:
    if target = -4 then if position.x <= target , then position.x = target;
    if target is positive, then you'd check if position.x >= target
    Maybe I shouldn't have used the word clamp, to avoid confusion. :)
    If you're always moving with velocity, and you were using such a setup, it might look like:
    Code (csharp):
    1.  
    2. target = 4;
    3. rb.velocity = (whatever speed);
    4. if(transform.position.x >= target) {
    5.    transform.position = new Vector3(target, transform.posiition.y, transform.position.z);
    6.    rb.velocity = Vector3.zero;   // stop the movement if you're at the target.. until a new touch/tap is made.
    7.    }
    8.  
    Those are just some ideas. If you move in other directions, as well, you'd have to alter the rb.velocity where I set it to zero -- you may want to merely zero out the 'x' portion, instead.

    That kinda make sense?
     
    javaBroker likes this.
  7. javaBroker

    javaBroker

    Joined:
    Jun 14, 2017
    Posts:
    11
    sorry for confuse you.. what i want to do is, move the player one step only on tap only and keep the tilt look the same. if I want to do this, for my grid, each step must be 2 units and up to 4 for each side (-4, 4) because of the 5 ways there..

    one code i tried saved the tilt mechanics but didn't move a fixed amount,
    the other code i try is moving a fixed amount but no tilt LOL
     
    Last edited: Sep 30, 2017
  8. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    So, ya.. I see what you're talking about.. I think the answer I gave would work in this situation.
     
  9. javaBroker

    javaBroker

    Joined:
    Jun 14, 2017
    Posts:
    11
    ok so I have tried to clamp the transform and it is moving in a fixed distance and the rotation is working, but unfortunately the transform just jump from place to place and you can't see any smooth movement. maybe because the clamp code cancel in realtime the Mathf.MoveTowards

    in the Update when touch began i catch the last position.x of the rigidbody and then clamp it in the fixed update under the boundary restrict:

    Code (CSharp):
    1.             //restrict movement to boundaries
    2.             if (transform.position.x <= xMin) {
    3.                 transform.position = new Vector3 (xMin, transform.position.y, transform.position.z);
    4.             }
    5.             if (transform.position.x >= xMax) {
    6.                 transform.position = new Vector3 (xMax, transform.position.y, transform.position.z);
    7.             }
    8.  
    9.         if (transform.position.x <= cathLastPosition + target) {
    10.             transform.position = new Vector3 (cathLastPosition + target, transform.position.y, transform.position.z);
    11.             }
    12.         if (transform.position.x >= cathLastPosition + target) {
    13.             transform.position = new Vector3 (cathLastPosition + target, transform.position.y, transform.position.z);
    14.             }
    Update method:

    Code (CSharp):
    1.     void Update() {
    2.  
    3.         if (Input.touchCount > 0) {
    4.  
    5.             if (Input.GetTouch(0).phase == TouchPhase.Began) {
    6.            
    7.             touchPosition = Input.GetTouch (0).position;
    8.             cathLastPosition = rb.transform.position.x; //<<<<--new line
    9.  
    10.             if (touchPosition.x > screenCenter) {
    11.                 target = 2f;
    12.             }
    13.             if (touchPosition.x < screenCenter) {
    14.                 target = -2f;
    15.             }
    16.             isTap = true;
    17.                 //moveHorizontal = Mathf.MoveTowards (moveHorizontal, target, sensitivity * Time.deltaTime);
    18.             }
    19.         }
    20.         if (isTap == true) {
    21.             moveHorizontal = Mathf.MoveTowards (moveHorizontal, target, sensitivity * Time.deltaTime);
    22.  
    23.             if (moveHorizontal == 2f || moveHorizontal == -2f) {
    24.                 isTap = false;
    25.             }
    26.         }
    27.  
    28.         if (isTap == false) {
    29.             moveHorizontal = Mathf.MoveTowards (moveHorizontal, 0, sensitivity * Time.deltaTime);
    30.         }
    31.  
    32.         movement = new Vector3 (moveHorizontal, 0.0f, 0.0f);
    33.     }
     
  10. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    The only "gotcha" is that trying to stop on an exact spot using velocity alone is basically impossible, so it's much easier to just use Rigidbody.MovePosition() instead.

    Anyways, here's the code I've come up with:
    Code (csharp):
    1.  
    2.        // new variables (set them at the top with your others)
    3.        private Vector3 targetPosition;
    4.        private Quaternion targetRotation;
    5.  
    6.        private int lane = 0;
    7.  
    8.        private void Awake()
    9.        {
    10.            // set these in your Awake():
    11.            targetPosition = transform.position;
    12.            targetRotation = Quaternion.identity;
    13.        }
    14.  
    15.        private void Update()
    16.        {
    17.            if (Input.touchCount > 0)
    18.            {
    19.                if (Input.GetTouch(0).phase == TouchPhase.Began)
    20.                {
    21.                    touchPosition = Input.GetTouch(0).position;
    22.  
    23.                    if (touchPosition.x > screenCentre)
    24.                        lane += 1;
    25.                    if (touchPosition.x < screenCentre)
    26.                        lane -= 1;
    27.  
    28.                    lane = Mathf.Clamp(lane, -2, 2); // change to how many lanes you have
    29.                }
    30.            }
    31.  
    32.            float laneWidth = 2f; // change from 2 if you need to
    33.            float laneTarget = lane * laneWidth;
    34.  
    35.            targetPosition.x = Mathf.MoveTowards(targetPosition.x, laneTarget, speedHorizontal * Time.deltaTime);
    36.            targetPosition.z += speedForward * Time.deltaTime;
    37.  
    38.            float tilt = laneTarget - targetPosition.x;
    39.  
    40.            targetRotation = Quaternion.RotateTowards(targetRotation, Quaternion.Euler(0f, 0f, -tilt * 25f), 90f * Time.deltaTime);
    41.        }
    42.  
    43.        private void FixedUpdate()
    44.        {
    45.            rigidbody.MovePosition(targetPosition);
    46.            rigidbody.MoveRotation(targetRotation);
    47.        }
    48.  
    And it should work like this:


    Let me know if that's not what you're looking for.
     
    Last edited: Oct 1, 2017
    Sanhueza and javaBroker like this.
  11. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Move position is a valid option, too. However, I think it's a stretch to say I moved him wildly astray.

    When you're checking if you >= target or <= target you have to account for direction you're going. I mentioned that. With fresh eyes, after some sleep, I could have also suggested that there are 5 values you store and you can cycle between with to set a moveTowards target.

    In any event, hopefully with your help and/or mine, he is close to his solution working :)
     
  12. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    Sorry methos5k, I didn't mean that in an accusatory or defaming way. My apologies if that's how it came across. I just meant that the OP was close to a solution and then you blew his mind with a different approach. I've edited my original post as clearly my tone was lost in text.
     
  13. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    No worries, I appreciate you saying so. All is well, I was just hoping to get him to a working solution. Perhaps I didn't take a prior solution well enough into account when posting.

    I'll wait and see what he writes back with to see what's working :)
     
  14. javaBroker

    javaBroker

    Joined:
    Jun 14, 2017
    Posts:
    11
    the code is working! thank you, i just moved
    Code (CSharp):
    1.  targetPosition.z += speedForward * Time.deltaTime;
    to my Fixed update in my case. I wish I had skills in Unity code as you can see my problem have been as a result of lack of knowledge..

    thank you both guys for your time helping me, i appreciate it so much!