- Home /
Drag to add power, release to throw at opposite angle (RigidBody2D), strange beahviour.
I'm a total beginner and I'm making a simple 2D game, you have ball which you throw to collect pickups. I managed, following tutorials and searching on the web, to script the controls as I wanted them, when the mouse is clicked the force to apply is calculated by the movement on axis X and Y and on mouse button release the force is applied and the gravity turned on:
if (Input.GetMouseButton(0)) mouseDown = true;
if (!Input.GetMouseButton(0)) mouseDown = false;
if (Input.GetAxis("Mouse X") != 0 && mouseDown)
{
xForce -= Input.GetAxis("Mouse X") * 50;
}
if (Input.GetAxis("Mouse Y") != 0 && mouseDown)
{
yForce -= Input.GetAxis("Mouse Y") * 50;
}
if (Input.GetMouseButtonUp(0))
{
GetComponent<Rigidbody2D>().gravityScale = 1;
GetComponent<Rigidbody2D>().AddForce(new Vector2(xForce, yForce));
yForce = 0;
xForce = 0;
}
But while working perfectly while testing it on unity using the mouse, it behave strangely on my 2 android phones. Sometimes the ball seems to get the force only for the X axis, and even if dragging only vertically the ball has an X force applied... What could be the problem?
EDIT: I added Debug.Log(xForce) and Debug.Log(yForce) and looking at the log with adb logcat I noticed that, also when simply tapping on the screen, without dragging on neither axis, the value of those variables increase, I have really no idea on how to solve this...
Answer by Firedan1176 · May 16, 2016 at 04:00 PM
Those values for Input.GetAxis are delta values, so it is the difference in movement of the mouse since the last update frame. It may not always be accurate. What I would recommend you doing, however, is get the start position of the mouse when they first click, and the end position when they release. I would get the difference between that and simply use that as the x and y force values. So something like this:
Vector2 start, end, force;
void Update() {
if(Input.GetMouseButtonDown(0)) start = Input.mousePosition;
else if(Input.GetMouseButtonUp(0)) {
end = Input.mousePosition;
force = end - start;
}
}
If you want to try that out, let me know how that works. It is just a start, so I do not know how it will work in your project.
Thanks a lot @Firedan1176 you pointed me to the right direction (after days of web searching), and after some experimenting I ended up with what I wanted, here's my code, I get the mouse position when button is clicked (or screen touched):
if (Input.Get$$anonymous$$ouseButtonDown(0))
{
startPosX = Input.mousePosition.x;
startPosY = Input.mousePosition.y;
}
then when the mouse button is released I store the position of it and store in 2 variables xForce and yForce the difference between start and end position, and make a Vector2 with those variables to add a force to the rigidbody, then reset everything to be ready for the second shot:
if (Input.Get$$anonymous$$ouseButtonUp(0))
{
endPosX = Input.mousePosition.x;
endPosY = Input.mousePosition.y;
xForce = startPosX - endPosX;
yForce = startPosY - endPosY;
GetComponent<Rigidbody2D>().gravityScale = 1;
GetComponent<Rigidbody2D>().AddForce(new Vector2(xForce, yForce));
yForce = 0;
xForce = 0;
startPosX = 0;
startPosY = 0;
}
It works with both mouse and touch controls, I'm pretty happy with it :) Should I mark your question as "accepted" or should I post another answer with my full code?
@Ring$$anonymous$$, I'm glad it was helpful. In your comment, you are getting endPositionY and endPositionX as separate variables, which are probably floats in your script? However, it will save you time if you simply keep it as a Vector2 like in my example. Remember, a Vector2 is only 2 floats stored in 1 variable. That way, you save your time. Also, Input.mousePosition returns a Vector2, so you are really making extra work for yourself. Good luck, and keep on coding!
@Firedan1176 Thanks! I broke it down to separate values because I was getting problems "normalizing" negative values, I should revert them to a Vector2 :)
Answer by RingK · Sep 01, 2017 at 08:24 AM
private float yForce;
private float xForce;
private float maxForceY = 900;
private float maxForceXp = 800;
private float maxForceXm = -800;
private float startPosX;
private float startPosY;
private float endPosX;
private float endPosY;
private float originX;
private float originY;
void Update () {
originX = GetComponent<Rigidbody2D>().position.x;
originY = GetComponent<Rigidbody2D>().position.y;
if (Input.GetMouseButtonDown(0))
{
startPosX = Input.mousePosition.x;
startPosY = Input.mousePosition.y;
}
if (Input.GetMouseButtonUp(0))
{
endPosX = Input.mousePosition.x;
endPosY = Input.mousePosition.y;
xForce = (startPosX - endPosX) * 3;
yForce = (startPosY - endPosY) * 2;
if (yForce < 0) yForce = 0;
if (yForce > maxForceY) yForce = maxForceY;
if (xForce > 0 && xForce > maxForceXp) xForce = maxForceXp;
if (xForce < 0 && xForce < maxForceXm) xForce = maxForceXm;
GetComponent<Rigidbody2D>().gravityScale = 1;
GetComponent<Rigidbody2D>().AddForce(new Vector2(xForce, yForce));
yForce = 0;
xForce = 0;
startPosX = 0;
startPosY = 0;
endPosX = 0;
endPosY = 0;
}
}
This is what I ended up with, hope it helps. Surely, it can be improved ;)