Reputation: 21
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
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
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);
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
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