Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

Unity C# - Rigidbody2D.velocity problems (Mobile)

Discussion in 'Scripting' started by NukoTheNeko, Mar 14, 2018.

  1. NukoTheNeko

    NukoTheNeko

    Joined:
    Feb 26, 2015
    Posts:
    3
    Hello, I'm currently developing a mobile game where the player moves by clicking on a point on screen, and dragging towards the pretended direction of movement.

    The following is my current movement script:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3.  
    4. public class MovementScript : MonoBehaviour
    5. {
    6.     private GameObject _player;
    7.     private Rigidbody2D _playerRigidbody2D;
    8.     [SerializeField]
    9.     private float _jumpForce = 300f;
    10.     [SerializeField]
    11.     private float _playerSpeed=3f;
    12.  
    13.     private Vector2 _touchPosition;
    14.  
    15.     [SerializeField]
    16.     private LayerMask _groundMask;
    17.     [SerializeField]
    18.     private Transform _groundCheckPosition;
    19.     [SerializeField]
    20.     private float _groundCheckRadius = 0.4f;
    21.     private bool _isGrounded = true;
    22.  
    23.     [SerializeField]
    24.     private Text _text;
    25.  
    26.     private void Awake()
    27.     {
    28.         _player = GameObject.Find("Player");
    29.         _playerRigidbody2D = _player.GetComponent<Rigidbody2D>();
    30.     }
    31.  
    32.     private void FixedUpdate()
    33.     {
    34.         _isGrounded = false;
    35.         Collider2D[] hits = new Collider2D[4];
    36.  
    37.         if (Physics2D.OverlapCircleNonAlloc(_groundCheckPosition.position, _groundCheckRadius, hits, _groundMask) > 0)
    38.         {
    39.             _isGrounded = true;
    40.         }
    41.  
    42.         if (Input.touchCount > 0)
    43.         {
    44.             for (int i = 0; i < Input.touchCount; i++)
    45.             {
    46.                 if (Input.GetTouch(i).position.x > Screen.width / 2)
    47.                 {
    48.                     if (Input.GetTouch(i).phase == TouchPhase.Began)
    49.                     {
    50.                         _touchPosition = Input.GetTouch(i).position;
    51.                     }
    52.  
    53.                     Vector2 direction = (Input.GetTouch(i).position - _touchPosition).normalized;
    54.  
    55.                     if (direction.y > 0.5f)
    56.                     {
    57.                         if (_isGrounded)
    58.                         {
    59.                             _playerRigidbody2D.AddForce(new Vector2(0, _jumpForce));
    60.                         }
    61.                     }
    62.  
    63.                     //Velocity
    64.                     _playerRigidbody2D.velocity = new Vector2(_playerSpeed * 50 * (direction.x), _playerRigidbody2D.velocity.y);
    65.                     _text.text = ("speed " + _playerSpeed + " + " + "direction " +
    66.                                   new Vector2(_playerSpeed * (direction.x), _playerRigidbody2D.velocity.y));
    67.                     /*
    68.                     //AddForce
    69.                     _playerRigidbody2D.AddForce(new Vector2(_playerSpeed * 50 * (direction.x),0));
    70.                     */
    71.                     if (direction.x > 0 && !_player.GetComponent<PlayerScript>().ReturnPlayerFacingRight())
    72.                     {
    73.                         _player.GetComponent<PlayerScript>().Flip();
    74.                     }
    75.                     else if (direction.x < 0 && _player.GetComponent<PlayerScript>().ReturnPlayerFacingRight())
    76.                     {
    77.                         _player.GetComponent<PlayerScript>().Flip();
    78.                     }
    79.                     return;
    80.                 }
    81.             }
    82.         }
    83.     }
    84. }
    85.  
    What's happening is that the player doesn't seem to move with the velocity command, but the text box is getting updated with the correct value. It should also be noted that the AddForce command is working correctly, and when i used the velocity command with the keyboard input it worked properly.

    Am i missing anything obvious? Also if you notice any flaws in my code regarding any other point feel free to point them out.
     
  2. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Your non-alloc should re-use your array .. declare the array outside of the FixedUpdate method loop. :)
    Otherwise, you're kinda making your own version of the 'alloc' method. heh

    I think you only allow movement if your touch position is on the right hand half of the screen (intentional?).

    I don't usually use touch, but it may be that you shouldn't use the 'began phase' in Fixed Update, similarly to how one shouldn't use GetKeyDown. So, you could store that in Update, instead.
    However, touch has a deltaPosition, which maybe be useful, instead?

    Here is an extremely simplified example that I tested, kinda similar to yours, but obviously without touch..
    Code (csharp):
    1. public class Test9 : MonoBehaviour
    2. {
    3.     Rigidbody2D rb;
    4.     Vector3 lastpos;
    5.     void Awake()
    6.     {
    7.         rb = GetComponent<Rigidbody2D>();
    8.     }
    9.     void Update()
    10.     {
    11.         if (Input.GetMouseButtonDown(0))
    12.         {
    13.             lastpos = Input.mousePosition;
    14.         }
    15.         if (Input.GetMouseButtonUp(0))
    16.         {
    17.             rb.velocity = Vector2.zero;
    18.         }
    19.     }
    20.     void FixedUpdate()
    21.     {
    22.         if (Input.GetMouseButton(0))
    23.         {
    24.             Vector3 dir = (Input.mousePosition - lastpos).normalized;
    25.             if (dir != Vector3.zero)
    26.             {
    27.                 lastpos = Input.mousePosition;
    28.                 rb.velocity = new Vector2(dir.x * 5, rb.velocity.y);
    29.             }        
    30.         }  
    31.     }
    32. }
    Edit: Oops, just noticed that my example is imperfect in the sense that if you have y movement, and not 'x' the velocity can be set to zero for the horizontal. This could be fixed, I think, if you create a new vector to compare that zeroes out the y portion.
     
    Last edited: Mar 14, 2018
    NukoTheNeko likes this.
  3. NukoTheNeko

    NukoTheNeko

    Joined:
    Feb 26, 2015
    Posts:
    3
    Thank you very much for your response, I have already applied some of the optimizations you recommended, however, it seems like i didn't explain properly what i was trying to achieve.

    First, yes it is supposed to only work on half of the screen, the other half is reserved for other action(which are working properly), secondly, the way you did it seems like if the player stops moving the cursor the character also stops, my goal here, however, is to create something of like an analog stick, that doesn't have a position defined and can be started anywhere, movement will then be created based on the starting position and wherever the player drags his finger(movement will only stop upon lifting the finger).

    All of this is working however, the problem still maintains itself as it seems like even though i am correctly creating the vector for movement (the text component is getting updated properly), the velocity component of the Rigidbody2D isn't getting changed. When i tried this with the ApplyForce however it worked (although not with the desired results, hence why i need the velocity component).

    Either way thank you very much for your answer, and for the tips.
     
  4. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Ah okay, well I actually wrote that in a note at the bottom (maybe, unless I misunderstood you).. If I dragged my mouse, and it was still held down - and even if not moving - the character would continue to go in the previous direction of the drag. My note included a suggestion to fix the calculation, because it would stop if you dragged up but not to the side.

    Thanks for clearing up the half of the screen - just had to check that. :)

    I think my edited code looked like this:
    Code (csharp):
    1. Vector3 xdir = dir;
    2. xdir.y = 0;
    3. if(xdir != Vector2.zero) {
    4.    lastpos = Input.mousePosition;
    5.    rb.velocity = new Vector2(xdir.x * 5, rb.velocity.y);
    6.   }
    I think it was like that. This way, all 'zero' horizontal is not affecting the velocity, until the touch ended (or mouse up, in my example) is done..
     
    NukoTheNeko likes this.
  5. NukoTheNeko

    NukoTheNeko

    Joined:
    Feb 26, 2015
    Posts:
    3
    Well the situation just fixed itself without me really doing any work, so I am still in the blue as to why it didn't work...
    Either way thank you very much for helping me, especially with the code optimization tips. :)