Search Unity

AddForce is giving me a hard time

Discussion in '2D' started by ProjektSpark, Oct 23, 2018.

  1. ProjektSpark

    ProjektSpark

    Joined:
    Jun 6, 2018
    Posts:
    11
    Hi,

    Before anything else, sorry if this thread is in the wrong place, I will gladly move it if it is the case.
    So, I'm currently developing a 2D platformer (my first one, hurra) and I'm having a bit of trouble with the last part of my programming.
    The character is supposed to be able to shoot in the direction of the cursor (which follows the movements of the mouse), and then be moved in the other direction (as a standard recoil). So i did this:

    Code (CSharp):
    1. Vector2 PointDeTirPosition = new Vector2(PointDeTir.position.x, PointDeTir.position.y);
    2. Vector2 target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    3. Vector2 direction = target - PointDeTirPosition;
    4. Vector2 Recoil = new Vector2(PointDeTir.position.x - Curseur.position.x, PointDeTir.position.y - Curseur.position.y);
    5. Vector3 difference = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;
    6. difference.Normalize();
    7. direction.Normalize();
    8. Recoil.Normalize();
    9. float RotZ = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg;
    10. GameObject clone = (GameObject)Instantiate(Projectile1, PointDeTirPosition, Quaternion.Euler(0f, 0f, RotZ));
    11. clone.GetComponent<Rigidbody2D>().velocity = direction * ProjectileSpeed1;
    12. GetComponent<Rigidbody2D>().AddForce(Recoil * RecoilStrength1, ForceMode2D.Impulse);
    It works pretty well, except for the X axis: there, the movement is instaneous and almost non-existent, whereas the Y axis works perfectly.
    Any idea where it comes from ? Thank you a lot to those who will give it a try :)
     
  2. Green11001

    Green11001

    Joined:
    Apr 14, 2018
    Posts:
    397
    Ok your code looks a bit complicated but I have 2 questions. Are you using transform.right and why are you normalizing everything.
     
    vakabaka likes this.
  3. ProjektSpark

    ProjektSpark

    Joined:
    Jun 6, 2018
    Posts:
    11
    Hi, thank you for your time !Yes the code is quite messed up, I had problems all along the way so I stitched up some parts...
    I am not using transform.right, though I have tried Addforce, Rigidbody velocity and transform.translate. I like Addforce the most, because it's the smoothest and delivers a short burst of movement (such as one would expect from a shooting weapon), but as far as I went, X axis doesn't receive more than one tenth of the force applied to Y axis.
    I normalized vector because I want the force applied to be normalized: before I did, the force applied to projectiles and to player afetr a shot was proportionnal to the distance between the player and the cursor (which was definitely not what i wanted), so this shouldn't be the problem.
     
  4. vakabaka

    vakabaka

    Joined:
    Jul 21, 2014
    Posts:
    1,153
    transform.right is the direction and can be used instead of rotation over mathf.atan.

    as example:
    Vector3 difference = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;
    clone.transform.right = difference;
    (you can use transform.right, transform.up, - transform.right, -transform.up)

    what is PointDeTir ? Can it be that rigidbody from the projectile is locked on x ?

    I think your code should work, I have tested (with PointDeTir as gameobject.transform) and the projectile are flying in all directions.
    Code (CSharp):
    1. public Transform PointDeTir;
    2.     public GameObject Projectile1;
    3.     public float ProjectileSpeed1;
    4.  
    5.  
    6.     void Update()
    7.     {
    8.         if (Input.GetMouseButtonDown(0))
    9.         {
    10.             Vector2 PointDeTirPosition = new Vector2(PointDeTir.position.x, PointDeTir.position.y);
    11.             Vector2 target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    12.             Vector2 direction = target - PointDeTirPosition;
    13.             Vector3 difference = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;
    14.             direction.Normalize();
    15.             float RotZ = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg;
    16.             GameObject clone = (GameObject)Instantiate(Projectile1, PointDeTirPosition, Quaternion.Euler(0f, 0f, RotZ));
    17.             clone.GetComponent<Rigidbody2D>().velocity = direction * ProjectileSpeed1;
    18.         }
    19.     }
    20. }
     
    Last edited: Oct 24, 2018
  5. ProjektSpark

    ProjektSpark

    Joined:
    Jun 6, 2018
    Posts:
    11
    So I just tried this, and this only made the character rotate in the most hilarious way, I fail to understand how this could be the way
    And PointDeTir is french, it represents the position of an empty object where my particles and projectiles come from (tip of the weapon)
     
  6. vakabaka

    vakabaka

    Joined:
    Jul 21, 2014
    Posts:
    1,153
    with transform.right in my example it whould be like:
    Code (CSharp):
    1. void Update()
    2.     {
    3.         if (Input.GetMouseButtonDown(0))
    4.         {
    5.             Vector2 PointDeTirPosition = new Vector2(PointDeTir.position.x, PointDeTir.position.y);
    6.             Vector2 target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    7.             Vector2 direction = target - PointDeTirPosition;
    8.             direction.Normalize();
    9.             GameObject clone = (GameObject)Instantiate(Projectile1, PointDeTirPosition, Quaternion.identity);
    10.             clone.transform.right = direction;
    11.             clone.GetComponent<Rigidbody2D>().velocity = direction * ProjectileSpeed1;
    12.         }
    13.     }
    you can use it as local vector: clone.GetComponent<Rigidbody2D>().velocity = clone.transform.right * ProjectileSpeed1;
     
  7. ProjektSpark

    ProjektSpark

    Joined:
    Jun 6, 2018
    Posts:
    11
    I must have explained my problem poorly: the projectiles are all OK, the issue is in the recoil movement: the addforce I'm using on the character after a shot doesn't impact the X axis, and therefore makes the player skyrocket to the moon, while not moving more than 5 inches on the sides
     
  8. vakabaka

    vakabaka

    Joined:
    Jul 21, 2014
    Posts:
    1,153
    ah, sorry :) What is curseur ? Is it the same as mouse position ?
     
  9. ProjektSpark

    ProjektSpark

    Joined:
    Jun 6, 2018
    Posts:
    11
    It's ok, thanks to help me anyways ! Curseur is the gamebject following the mouse psoition, towards which the character is shooting
     
  10. vakabaka

    vakabaka

    Joined:
    Jul 21, 2014
    Posts:
    1,153
    maybe you can just use opposite to shooting direction ?
    GetComponent<Rigidbody2D>().AddForce(- direction * RecoilStrength1, ForceMode2D.Impulse);
     
  11. ProjektSpark

    ProjektSpark

    Joined:
    Jun 6, 2018
    Posts:
    11
    Well it's actually the same thing, given that Curseur is technically the target ! (I know, my code is stitched up like crap :^) )
    I have tried it anyways, and the result is precisely the same, so I'm beggining to suspect that this a problem with Addforce and the X axis that i'm not seeing... I have searched on the net and haven't found a way yet: my rigidbody is dynamic, simulated, without constraints, mass gravity and drag are standard, animator doesn't have root motion applied...
     
  12. vakabaka

    vakabaka

    Joined:
    Jul 21, 2014
    Posts:
    1,153
    just for test, will this move the object on x ?
    GetComponent<Rigidbody2D>().velocity = - direction * RecoilStrength1;

    I think your moving script can overwright the x-force
     
    Last edited: Oct 24, 2018
  13. ProjektSpark

    ProjektSpark

    Joined:
    Jun 6, 2018
    Posts:
    11
    Absolutely doesn't, neither does the Recoil vector... That's a problem right ?
     
  14. vakabaka

    vakabaka

    Joined:
    Jul 21, 2014
    Posts:
    1,153
    then do you move the player with velocity too ? I think you should disable moving at the shooting time (or use force for moving). Velocity change the moving vector directly, it is good for precise moving but ignoring the forces.
     
  15. ProjektSpark

    ProjektSpark

    Joined:
    Jun 6, 2018
    Posts:
    11
    I do move him with velocity. I tried deleting
    Code (CSharp):
    1.  
    2.         moveY = Input.GetAxis("Vertical");
    3.         moveX = Input.GetAxis("Horizontal");
    from my total code, but that didn't work
     
  16. vakabaka

    vakabaka

    Joined:
    Jul 21, 2014
    Posts:
    1,153
    yes, because your velocity can be now zero, delete line with velocity
     
  17. ProjektSpark

    ProjektSpark

    Joined:
    Jun 6, 2018
    Posts:
    11
    Oh yeah, totally works then ! So all I have to do is deactivate movement's velocity when the character is about to shoot, right ?
     
  18. vakabaka

    vakabaka

    Joined:
    Jul 21, 2014
    Posts:
    1,153
    as example, I am sure it will not work good
    Code (CSharp):
    1.  
    2. public Transform PointDeTir;
    3.     public GameObject Projectile1;
    4.     public float ProjectileSpeed1, RecoilStrength1, delay, speed;
    5.     bool isShooting, canBePushed;
    6.     Vector2 direction;
    7.     Rigidbody2D rb;
    8.     float x, y;
    9.  
    10.     void Start ()
    11.     {
    12.         rb = GetComponent<Rigidbody2D>();
    13.     }
    14.  
    15.  
    16.     void Update()
    17.     {
    18.         x = Input.GetAxis("Horizontal");
    19.         y = Input.GetAxis("Vertical");
    20.  
    21.         if (Input.GetMouseButtonDown(0))
    22.         {
    23.             Vector2 PointDeTirPosition = new Vector2(PointDeTir.position.x, PointDeTir.position.y);
    24.             Vector2 target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    25.             direction = target - PointDeTirPosition;
    26.             direction.Normalize();
    27.             GameObject clone = (GameObject)Instantiate(Projectile1, PointDeTirPosition, Quaternion.identity);
    28.             clone.transform.right = direction;
    29.             clone.GetComponent<Rigidbody2D>().velocity = direction * ProjectileSpeed1;
    30.             isShooting = true;
    31.             canBePushed = true;
    32.             StartCoroutine("MovingDelay");
    33.         }
    34.     }
    35.  
    36.     void FixedUpdate ()
    37.     {
    38.         if (!isShooting)
    39.         {
    40.             rb.velocity = new Vector2(x, y) * speed;
    41.         }
    42.         else if (canBePushed)
    43.         {
    44.             canBePushed = false;
    45.             rb.velocity = Vector2.zero;
    46.             rb.AddForce(-direction * RecoilStrength1, ForceMode2D.Impulse);
    47.         }
    48.     }
    49.  
    50.     IEnumerator MovingDelay ()
    51.     {
    52.         yield return new WaitForSeconds(delay);
    53.         isShooting = false;
    54.     }
    55. }
    56.  
    or as said, you can just move the player with force instead of velocity
     
    Last edited: Oct 24, 2018
  19. ProjektSpark

    ProjektSpark

    Joined:
    Jun 6, 2018
    Posts:
    11
    Welp, this works top notch, thank you so much pal. here is the part of the code that I changed :

    Code (CSharp):
    1.        
    2.         Vector2 Recul = new Vector3(transform.position.x - Curseur.position.x, transform.position.y - Curseur.position.y);
    3.         Recul.Normalize();
    4.         float elapsedTime = 0f;
    5.         IsPushed = true;
    6.         while (elapsedTime < duration)
    7.         {
    8.             gameObject.GetComponent<Rigidbody2D>().AddForce(Recul * RecoilStrength1);
    9.             elapsedTime += Time.deltaTime;
    10.             yield return null;
    11.         }
    12.         yield return new WaitForSeconds(1 / 10);
    13.         CurrentEnergy = CurrentEnergy - EnergyCost1;
    14.         UpdateHealthBar();
    15.         IsPushed = false;
    16.  
    The only problem is that the movement ends up brutally by going down, and without any "floating" in the air (if you have any clue on how I could improve that :^) ), but I can definitely works with that !
    Thank you a lot mate !
     
  20. ProjektSpark

    ProjektSpark

    Joined:
    Jun 6, 2018
    Posts:
    11
    OK so I changed a few things so that the IsPushed boolean runs when the movement is being done, and this is rock solid ! Thank you a lot, and have a good day !
     
  21. vakabaka

    vakabaka

    Joined:
    Jul 21, 2014
    Posts:
    1,153
    you too :rolleyes: