Getting the player jump correctly in Unity3D - c#

I'm still learning the basics so please be a bit gentle. I'm working on the movement script of a roll-a-ball game. I've got the rolling around working perfectly fine, but now I'm trying to add the ability to jump.
In my case the "player" is a basic Sphere. What I'm trying to accomplish is that when space is pressed, the ball leaps into the air in the direction it's currently rolling.
This is what I've tried myself, but gave very strange results:
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
if (Input.GetKey("space"))
{
transform.position += transform.up * 20 * Time.deltaTime;
}
rb.AddForce(movement * speed); //rb = RigidBody
This resulted in the ball sometimes jumping in the wrong direction or simply just speeding into some direction without jumping at all. So obviously I'm getting closer, but not quite there yet. Could anyone explain what I'm doing wrong and how to fix it?
Not looking for a quick fix! Don't learn anything from that.

Have a try at this :)
if (Input.GetKey("space"))
{
rigidbody.AddForce(new Vector3(0, yourJumpForce, 0), ForceMode.Impulse);
}
You also might want to fiddle with the gravity settings in the rigidbody to get your desired jump as well!
EDIT Explanation:
I think it may be because you are applying you movement to your Rigidbody, but your jumping method to the Transform itself.
A Rigidbody is a physics component (see docs.unity3d.com/ScriptReference/Rigidbody.html), where a Transform is to do with position, rotation and scale.
A jump could be considered a physics problem - therefore altering the jump is to do with physics (Rigidbody), not the position (Transform). I tend to do all movement code with the Transform, as you are moving positions, and do all physics based work with the Rigidbody, as you are applying physics to the GameObject! :)

To add to the accepted answer: The jumping into random directions issue could have been caused by the transform.up. That vector is the up direction relative to your current transform. That's usually the same as the actual up direction, except if you rotate the game object. And as the object happens to be a rolling ball in this case, it's very likely that it's rotated.
You can fix it by using the global up direction instead - either by doing it like in the accepted answer or by using Vector3.up.

Related

How do I rotate an object using transform.forward taking into account the surface normal?

I have a tank that is supposed to move up a hill. I would like the tank to move parallel to the slope.
My current problem
My desired result
This problem has to do with the way I am rotating the tank, which is by transform.forward.
Vector3 newCoords = camera.TransformDirection(moveDirection.x, 0, moveDirection.y);
transform.forward = new Vector3(newCoords.x, 0f, newCoords.z);
moveDirection is the Vector2 from the controller's joystick. camera.TransformDirection is basically making the forward of the tank, the forward of the camera. I'm not exactly sure but transform.forward is somehow resetting one of the axes, which doesn't allow it on the surface.
My question is how do I rotate the tank using transform.forward while keeping the tank parallel to the slope at all times?
If you need any clarification please ask. Thank you for reading, help would be greatly appreciated!
You can try two different solutions:
Use a rigidbody and you don't have to do nothing.
You probably have to calculate angle between the tank and the ground.
For doing this, you have to use a raycast (or spherecast,boxcast,...):
RaycastHit slopeHit;
if(Physics.Raycast(transform.position, Vector3.down, out slopeHit, raycastLength))
{
float angleBetween = Vector3.Angle(slopeHit.normal, Vector3.up);
}
Try implement it and use angle returned for modify the angle of your tank.
I can't add comments. Please close the question and mark my or your answer as correct

Unity: RigidBody2D, how to move GameObject in straight lines (no curves)

Hello all, I'm very new to and very confused by Unity.
I'm creating a top-down, gravity-free test game, similar to PacMan (i.e. think of the movement of characters in straight lines).
Currently, I'm trying to move an object in straight lines (without curvature) (see image).
My GameObject has RigidBody2D attached, as well as Linear, Angular and Gravity set to 0.
I'm currently controlling my GameObject by adding force:
private Rigidbody2D _playerRB2D;
public float _speed;
private void FixedUpdate()
{
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Vector2 movement = new Vector2(moveHorizontal, moveVertical);
_playerRB2D.AddForce(movement * _speed);
}
The idea is that the game object won't get to slow down, so is constantly in motion (in straight lines). Collision with objects is obviously important too!
Any help or information to look at will help a lot, thank you!
Unity has a built-in physics engine that calculates movement based on velocity (and collisions, etc.) By using Rigidbody2D.AddForce, you are adding to your rigidbody's velocity. This means that if you press the up arrow and then the right arrow, the velocity from pressing the up arrow remains, causing a diagonal velocity and curved path. If you want straight lines, you can use Rigidbody2D.velocity or just use Transform.translate.
_playerRB2D.velocity = movement * _speed;
Edit: You said that collisions were important, so keep the rigidbody
or remove the rigidbody2D component and use
transform.Translate(movement * _speed);
The idea is basically to reset the force being applied on the rigidBody2D on each changed direction.
In fact, you would have to test if the direction input from horizontal is greater than vertical for x axis, and the inverse for y axis , and thus if it is true, change the opposite to 0f.
You would have normally:
Vector2 movement = new Vector2(moveHorizontal < moveVertical ? moveHorizontal: 0f, moveVertical < moveHorizontal ? moveVertical: 0f);
_playerRB2D.velocity = movement * speed;
Edit: By testing the input value, you can move your RigidBody2D with a analogic controller, and thus being straight as you wished !

Rotate object around player with mouse but have it still comply with physics

In my game I want the character to be able to have a pickaxe or weapon that can rotate around the player but when I do so it goes through the objects and is very glitchy.
I want it to still follow the mouse (which is invisible) and still stop when it has a collision. My code right now is just pretty standard code for mouse rotation and its attached to an empty gameobject which is the parent of the pickaxe/weapon
//rotation
Vector3 mousePos = Input.mousePosition;
mousePos.z = 5.23f;
Vector3 objectPos = Camera.main.WorldToScreenPoint(transform.position);
mousePos.x = mousePos.x - objectPos.x;
mousePos.y = mousePos.y - objectPos.y;
float angle = Mathf.Atan2(mousePos.y, mousePos.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(new Vector3(0, 0, angle));
Whenever you have a GameObject that you want to be physics enabled, you don't move it directly. You add a Rigidbody and use RigidBody.MoveRotation to rotate your GameObject. RigidBody has its set of movement and rotation methods that take into account collisions. Moving the Transform directly will cause problems.
This can still cause problems in some situations. If you're still experiencing physics weirdness then you can eliminate them by using a "physically correct" solution and use Rigidbody.angularVelocity. Based on the angle you can set the velocity to either rotate the object right or left until it faces the way you want.
Essentially the physics system hates teleportation. Instant movements and instant rotations are basically teleportation to it. So there's a hierarchy of how "physics system friendly" some actions are. And they go like this:
Adding Force to the RigidBody
Adding Velocity to the RigidBody
Moving the GameObject through appropriate RigidBody methods.
Moving the GameObject through Transform.

Unity: How can I find out what angle I need to shoot from for a physics projectile to land in a certain spot

I need a little help with the math for physics.
Imagine you are shooting bullets from a cannon and depending on angle of the cannon bullet lands at different spots. The force applied to bullet is Unity impulse type.
What would be the best way to calculate what angle I must shoot from to make sure bullet always lands at specific point on the ground?
Vector3 dir = Quaternion.AngleAxis(angle, Vector3.forward) * Vector3.up;
_Bullet.AddForce(dir * BulletSpeed, ForceMode.Impulse);
thanks in advance
The equations are
You can also try Projectile Shooter from Wolfram Alpha.

My gameObject does not rotate while jumping

My gameObject does not rotate while jumping. I used GetComponent().rotation = Quaternion.identity; for rotation but the gameObject still does not rotate. What is the problem? And how do I adjust the speed of the rotation? Here's my jump script:
Quaternion.identity means no rotation {0,0,0,0}, whenever this code block is called the gameObject's rotation will become the standard rotation value.
If this was intentional and the rotation of the gameObject is not {0,0,0,0} then perhaps you are modifying the rotation elsewhere?
GetComponent().rotation = Quaternion.identity;
Couple issues with this line. First off, just use transform.rotation... no need to call GetComponent() here. Also, Quaternion.identity is just the 'zero' rotation. What kind of rotation are you actually trying to apply here because you shouldn't see anything using identity.
http://docs.unity3d.com/ScriptReference/Quaternion-identity.html
To apply real rotation use something like (where "speed" is a float var where you can set how fast you want your cube to rotate):
transform.Rotate(Vector3.up, speed * Time.deltaTime);

Categories

Resources