Search Unity

Apply force to RigidBody using Float?

Discussion in '2D' started by DoomPriestK, Dec 2, 2019.

  1. DoomPriestK

    DoomPriestK

    Joined:
    Nov 23, 2019
    Posts:
    20
    When this object is spawned I need it to look in the direction of the mouse pointer then apply an initial burst of speed (after which gravity sets in), I especially need to be able to set an initial burst of speed on an item using a Float, I can probably get this to work without the float input but it's quite important the player is able to set the force applied using the inspector:

    Anyone have any ideas on how to accomplish this with a float?

    Code (csharp):
    1.  
    2.  
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using UnityEngine;
    6.  
    7. public class PlayerThrowingNut : MonoBehaviour
    8. {
    9.     public float nutSpeed;
    10.     public GameObject nutHitEffect;
    11.     private int myLayer = 8;
    12.  
    13.     private Rigidbody2D theRB;
    14.  
    15.     // Start is called before the first frame update
    16.     void Start()
    17.     {
    18.         theRB = GetComponent<Rigidbody2D>();
    19.         gameObject.layer = myLayer;
    20.         Physics2D.IgnoreLayerCollision(myLayer, myLayer, true);
    21.  
    22.         // GETS WHERE THE CURSOR IS ON THE SCREEN
    23.         Vector3 worldMousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    24.  
    25.         // LOOK TOWARDS THE CURSOR
    26.         transform.LookAt(Vector3.zero); // IF DOES NOT WORK TRY worldMousePos
    27.  
    28.         // THEN ADD INITIAL VELOCITY
    29.         theRB = AddForceAtPosition(nutSpeed);
    30.  
    31.     }
    32.  
    33.     // Update is called once per frame
    34.     void Update()
    35.     {
    36.  
    37.  
    38.  
    39.  
    40.     }
    41.  
    42.     // WHEN IT COLLIDES WITH SOMETHING....
    43.     void OnTriggerEnter2D(Collider2D other)
    44.     {
    45.         // IF THE OTHER OBJECT IS SET TO THE "Killable" LAYER
    46.         if (other.gameObject.layer == LayerMask.NameToLayer("Killable"))
    47.         {
    48.             // SPAWN A HIT GRAPHIC THEN DESTROY THE PROJECTILE
    49.             Instantiate(nutHitEffect, transform.position, transform.rotation);
    50.             Destroy(gameObject, 1.0f);
    51.         }
    52.     }
    53. }
    54.  
    55.  
     
  2. jeffreyschoch

    jeffreyschoch

    Joined:
    Jan 21, 2015
    Posts:
    2,647
    Code (CSharp):
    1. transform.LookAt(Vector3.zero);
    This code makes the transform point the Z axis towards (0,0,0), which is the world origin.

    In 2D, the Z axis usually points forwards and doesn't change. For this reason, LookAt is mainly useful for 3D uses.

    Commonly in 2D, the X axis will be "forward" for a 2D object. So you need to set the X axis direction.

    You can set "transform.right" to a new vector. That will automatically rotate the transform so that the X axis points in the direction you give it.

    The direction you want you can get like this:
    transform.right = worldMousePos - transform.position;


    This should work for most use cases.
     
  3. DoomPriestK

    DoomPriestK

    Joined:
    Nov 23, 2019
    Posts:
    20
    Yeah i'm making a 2d platformer in 3D space so it's tricky

    I replaced transform.LookAt(Vector3.zero); with
    transform.right = worldMousePos - transform.position;

    And apparently it's now saying theRB = AddForceAtPosition(nutSpeed); does not exist in the current context...

    Damn code...im only new to this
     
  4. jeffreyschoch

    jeffreyschoch

    Joined:
    Jan 21, 2015
    Posts:
    2,647
    theRB = AddForceAtPosition(nutSpeed);

    This is assigning the variable "theRB" which is not what you want.

    I think it should be
    theRB.AddForce(nutSpeed * transform.right);

    so that you're calling a function in "theRB" and passing a force vector in the direction that the object is now facing.
     
    Last edited: Dec 3, 2019
  5. DoomPriestK

    DoomPriestK

    Joined:
    Nov 23, 2019
    Posts:
    20
    Thanks for the help, it's easy to miss that type of syntax for a newbie :(

    i'm almost there!

    I think the problem im having is that instead of setting the direction with the player i'm trying to set it up per-item.

    Basically I just wanted a "throw on click" so once the item spawns it gets lobbed in the direction of your click (the closest comparable game is Worms, where the items act with gravity and bounce around) but I want to make prefab items where you can set the velocity in the inspecter on each item (to make the building process a bit easier and more modular as I create content).

    The script runs now, although the projectiles just go straight upwards and dont follow the trajectory of the mouse click, i'll have to try and see why that's happening, the full script now looks like:

    Code (csharp):
    1.  
    2.  
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using UnityEngine;
    6.  
    7. public class PlayerThrowingNut : MonoBehaviour
    8. {
    9.     public float nutSpeed;
    10.     public GameObject nutHitEffect;
    11.     private int myLayer = 8;
    12.  
    13.     private Rigidbody2D theRB;
    14.  
    15.  
    16.    
    17.     // Start is called before the first frame update
    18.     void Start()
    19.     {
    20.         theRB = GetComponent<Rigidbody2D>();
    21.         gameObject.layer = myLayer;
    22.         Physics2D.IgnoreLayerCollision(myLayer, myLayer, true);
    23.  
    24.         // GETS WHERE THE CURSOR IS ON THE SCREEN
    25.         Vector3 worldMousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    26.  
    27.         // LOOK TOWARDS THE CURSOR
    28.         transform.right = worldMousePos - transform.position;
    29.  
    30.         // THEN ADD INITIAL VELOCITY
    31.         theRB.AddForce(nutSpeed * transform.right);
    32.     }
    33.  
    34.     // Update is called once per frame
    35.     void Update()
    36.     {
    37.  
    38.  
    39.  
    40.  
    41.     }
    42.  
    43.     // WHEN IT COLLIDES WITH SOMETHING....
    44.     void OnTriggerEnter2D(Collider2D other)
    45.     {
    46.         // IF THE OTHER OBJECT IS SET TO THE "Killable" LAYER
    47.         if (other.gameObject.layer == LayerMask.NameToLayer("Killable"))
    48.         {
    49.             // SPAWN A HIT GRAPHIC THEN DESTROY THE PROJECTILE
    50.             Instantiate(nutHitEffect, transform.position, transform.rotation);
    51.             Destroy(gameObject, 1.0f);
    52.         }
    53.     }
    54. }
    55.  
    56.