the glozzom
the glozzom

Reputation: 21

I'm not sure why but my add force isn't working i have a rigidbody2d, and the code looks correct but it still won't work?

I'm not sure why but my .addforce on my rigidbody isn't working.

I have tried following the official unity addforce tutorial.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ArrowController : MonoBehaviour
{
    public Rigidbody2D rb;
    public float speed = 5.0f;
    public Vector2 pos;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
    }
    // Update is called once per frame
    void Update()
    {
        faceMouse();
        testForClick();
    }

    void faceMouse()
    {
        Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        Vector3 differance = GameObject.Find("gunArm").transform.position - mousePos;
        float gunAngle = Mathf.Atan2(differance.y, differance.x) * Mathf.Rad2Deg;
        GameObject.Find("gunArm").transform.rotation = Quaternion.Euler(0, 0, gunAngle);
    }

    void testForClick()
    {
        if (Input.GetMouseButtonDown(0))
        {
            print("click");
            rb.AddForce(transform.forward);
        }
    }
}

I expect arrow to have force added to it in the forwards direction but it just prints out "click" (The message I added to ensure the mouse-click was working).

Upvotes: 0

Views: 2416

Answers (3)

the glozzom
the glozzom

Reputation: 21

I'm not sure why but I created a test script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{
    public Rigidbody2D rb;
    public float speed = 20.0f;

    // Start is called before the first frame update
    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            print("click");

            rb.AddForce(transform.right * speed, ForceMode2D.Impulse);
        }

        rotate();
    }

    private void rotate()
    {

    }
}

I also edited my old script to this:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ArrowController : MonoBehaviour
{
    public Rigidbody2D rb;
    public float speed = 50.0f;
    public Vector2 pos;

    private void Start()
    {
        rb = GetComponent<Rigidbody2D>();
    }

    private void Update()
    {
        faceMouse();
        testForClick();
    }

    void FixedUpdate()
    {
        if (doForce == true)
        {
            doForce = false;
            rb.AddForce(transform.forward * speed, ForceMode2D.Impulse);
        }
    }

    private bool doForce;

    private GameObject gunArm;
    private Camera cam;

    private void faceMouse()
    {
        // try to reuse the reference
        if (!cam) cam = Camera.main;

        var mousePos = cam.ScreenToWorldPoint(Input.mousePosition);

        // try to re-use the reference
        if (!gunArm) gunArm = GameObject.Find("gunArm");

        var difference = rb.transform.position - mousePos;
        var gunAngle = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg;
        rb.transform.rotation = Quaternion.Euler(0, 0, gunAngle);
    }

    void testForClick()
    {
        if (Input.GetMouseButtonDown(0))
        {
            print("click");

            // only set the flag
            doForce = true;
        }
    }

    void place()
    {

    }
}

and the test worked by itself with no rotation and on the main script only the rotation worked so i tried having both scripts active at the same time and it started working, thanks for all the help on this issue.

Upvotes: 1

Erik Overflow
Erik Overflow

Reputation: 2306

The reason your code doesn't do anything is not because it doesn't work, but instead because transform.forward is a vector with magnitude 1. Adding a force of magnitude 1 will not do much to most objects, and friction will likely slow down the object again.

Try adding a force with a higher strength and ForceMode.Impulse instead:

float strength = 50f;
rb.AddForce(transform.forward * strength, ForceMode.Impulse);

Update:

It looks like you want the gun to face your mouse position and that's where your problem might be: Let's try using Quaternion.LookRotation to get that working instead of doing to math manually.

Maybe:

GameObject gunArm;

void Awake()
{
    gunArm = GameObject.Find("gunArm");
}

void faceMouse()
{
    Vector3 difference = mousePos - gunArm.transform.position;
    difference.z = 0;
    gunArm.transform.rotation = Quaternion.LookRotation(difference);
}

Upvotes: 0

derHugo
derHugo

Reputation: 90580

Despite the fact that isn't working is a quite weak description:

First of all you should do it in FixedUpdate but get the input in Update.

Second reduce the Find calls in Update .. very inefficient. It would be better to reference them via the Inspector if possible. Otherwise maybe in Start .. the way I show here is the last resort with lazy initialization assuming your script might be spawned later on runtime

Additionally (thanks to EricOverflow) you might want to rather pass ForceMode.Impulse to AddForce since you add the force only once and not continuesly.

public class ArrowController : MonoBehaviour
{
    public Rigidbody2D rb;
    public float speed = 5.0f;
    public Vector2 pos;

    // store and re-use references!
    // would be better to already reference them via drag&drop
    // in the Inspector
    [SerializeField] private GameObject gunArm;
    [SerializeField] private Camera cam;

    private void Start()
    {
        rb = GetComponent<Rigidbody2D>();
    }

    private void Update()
    {
        testForClick();
    }

    private void FixedUpdate()
    {
        // also do this here
        faceMouse();

        if (doForce)
        {
            doForce = false;
            rb.AddForce(transform.forward, ForceMode.Impulse);
        }
    }

    private bool doForce;



    private void faceMouse()
    {
        // try to reuse the reference
        if(!cam) cam = Camera.main;

        var mousePos = cam.ScreenToWorldPoint(Input.mousePosition);

        // try to re-use the reference
        if (!gunArm) gunArm = GameObject.Find("gunArm");

        var difference = gunArm.transform.position - mousePos;
        var gunAngle = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg;

        gunArm.rotation = Quaternion.Euler(0, 0, gunAngle);
    }

    private void testForClick()
    {
        if (Input.GetMouseButtonDown(0))
        {
            print("click");

            // only set the flag
            doForce = true;
        }
    }
}

Upvotes: 0

Related Questions