addforce moving diagonally faster - c#

I am still a novice with Unity and am trying to make a top down 2D game and am stuck with the movement script where the movement is faster when I move diagonally. When I use normalized on the "axis" vector2 and start moving the player keeps moving for a bit and then stops moving suddenly when I stop pressing on any key and when I remove the normalized the movement goes back to normal and the player stops moving slowly and perfectly, but still when I move diagonally it is faster.
Here is my code:
{
Rigidbody2D rb;
Vector2 axis;
public float Speed = 400;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void FixedUpdate()
{
movement();
}
void movement()
{
axis = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical")).normlized * Speed;
rb.AddForce(axis, ForceMode2D.Force);
rb.drag = 60;
}
}

What happens is that the returned values of GetAxis are smoothed over some frames. So when you normalize the vector it returns a magnitude of 1 for a while even though your input is actually smaller than that since it is smoothing out.
In general instead of
new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical").normalized`
which always returns magnitude 1 also for smaller input you rather want to use Vector2.ClampMagnitude
axis = Vector2.ClampMagnitude(new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical")), 1f) * Speed;
which only clamps if the vector has a total magnitude > 1

Related

Unity - Vector3.MoveTowards does not move at constant speed

I'm trying to design a spitball/poison type projectile that will travel until it reaches the point clicked on screen and then destroys itself.
The problem is that contrary to what almost everyone says, Vector3.Movetowards is not moving the ball at a constant speed. If the target location is close to the launcher it moves slowly, if it is further away it moves much faster.
public float speed = 5f;
public Vector3 target = new Vector3();
void Update()
{
transform.position = Vector3.MoveTowards(transform.position, target,speed * Time.deltaTime);
}
Adding the launcher script
private void Shooting()
{
if (Input.GetMouseButton(0))
{
if (Time.time >= shotTime)
{
GameObject poison = Instantiate(Projectile, shotPoint.position, transform.rotation);
Vector3 target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
target.z = 10f;
poison.GetComponent<PoisonBall>().target = target;
shotTime = Time.time + timeBetweenShots;
}
}
}
Is the balls start position also at z=10f? Otherwise the difference in the speed most probably is a perspective issue in a 2D game and results in your bullet traveling in the Z direction but from your camera perspective you don't see that.
=> The closer you will be to the target the more movement will only happening on the Z axis, the further away the more movement is happening on X and Y.
Make sure to also do
var spawn = shotPoint.position;
spawn.z = 10f;
GameObject poison = Instantiate(Projectile, spawn, transform.rotation);
Or alternatively keep target.z = 0 (just remove the line target.z = 10f as per default the ScreenToWorld uses the Z component of given vector as depth and you are passing in a 2D vector with 0 depth anyway) and instead use Vector2.MoveTowards which will ignore ant depth on Z.

Rigidbody2D.MovePosition cause lags in physic, for example, gravity

I tested and this script cause lags in physic. It seems to me that it call physic not per 0,2 seconds, but much-much more rarely and because of this object falling much more slower.
Here's a gif to demonstrate what happens: The purple one without script, the blue one with script.
So how can I fix that?
public class PlayerMovement : MonoBehaviour
{
Rigidbody2D rb;
Vector2 movement = new Vector2(0, 0);
public float movementSpeed = 10f;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
private void Update()
{
movement = new Vector2(Input.GetAxisRaw("Horizontal"), 0);
}
void FixedUpdate()
{
rb.MovePosition(rb.position + movement * movementSpeed * Time.fixedDeltaTime);
}
}
As said MovePosition overrules the movement => don't use it if you want physics (force) based movements and reaction to collisions etc.
You want to use the input only for the horizontal movement but use physics for the vertical. MovePosition affects both directions.
Try directly setting the Rigidbody.velocity instead
private void Update()
{
// Get the current velocity
var velocity = rb.velocity;
// Only overwrite the x velocity
// since the velocity is only applied in the FixedUpdate anyway
// there is no problem setting this already in Update
// And since it is the velocity which is already frame-rate independent
// there is no need for Time.deltaTime
velocity.x = Input.GetAxisRaw("Horizontal") * movementSpeed;
// Assign back the changed velocity
rb.velocity = velocity;
}
There is an issue with the logic of your code if I understand what you want to do.
You seem to be moving in a vertical fashion yet only have the x component of your vector2 from the horizontal input.
new Vector2(Input.GetAxisRaw("Horizontal"), 0);
If the GIF you attached, the object is just in freefall, so that would be a vertical drop, or the y component of the vector2, which you are setting to 0. Think of this as (x,y) or (move horizontally (left/right), move vertically (up/down)).
I would change the above line to:
movement = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
You can now move vertically using vertical input. Something else which would not cause your issue, but is mentioned on the MovePosition docs is to mark your Rigidbody2D as Interpolate. It is the bottom field in the Rigidbody2D component labeled Interpolate, set it from None to Interpolate.
The reason your object is moving slowly without any input is because you still have your Gravity Scale on the Rigidbody set to 1 instead of 0. If you are trying to simulate gravity with this script, add the vertical component to your input vector and set the Gravity Scale field on the Rigidbody to 0. The MovePosition is fighting the current gravity attempting to affect it.

Bouncing all gets magnitude and velocity 0 after a while and stops

Im trying to simply get a ball to bounce with constant speed and without any infinite bounces. To avoid infinite bouncing I have added some drifting on each bounce in the collision event like this:
private void OnCollisionEnter2D(Collision2D collision)
{
Vector2 veclocityTweak = new Vector2(Random.Range(0f, 0.2f), Random.Range(0f, 0.2f));
rigigidBody2D.velocity += veclocityTweak;
}
I have also rotated the colliders (the ball is bouncing within this box)
This works ok. not perfect. But my real problem is that the ball suddenly stops and the rigidBody2D.velocity sets to (0.0, 0.0) as well as the magnitude.
I tried to prevent this by this function running in the update function checking the velocity. The idea is that it should prevent the ball to go to 0 in velocity but still that happens after a while:
private void checkVelocity()
{
Vector2 vel = rigigidBody2D.velocity;
float minSpeed = 0.8f;
if (vel.magnitude < minSpeed)
{
float multipl = Random.Range(-1.0f, 1.0f);
rigigidBody2D.velocity = vel.normalized * multipl;
}
}
Here is my settings in the Project Settings:
And I have set the material for the ball to:
How can I prevent the ball from stopping?
I would recomend doing this:
float minVelocity = 10;
float maxTurn = 10;
void OnCollisionEnter2D (Collision2D collision)
{
Quaternion randomRotation = Quaternion.Euler(0, 0, Random.Range(-maxTurn, maxTurn));
rb.velocity = randomRotation * (rb.velocity.normalized * minVelocity);
}
This code will set the velocity of the ball to its previous velocity, but with a magnitude of minVelocity. It will also rotate that vector a random amount of degrees to make it bounce in different directions.

Unity Move rotating object

I have a ball which rotates around the point 0,0,0 in the Z-axis. When the space button is pressed, the ball has to go inside the large circle. Now my code looks like this. When you press space, the ball does not behave as they should. I want to know how to make a balloon down exactly down
that's how the ball should behave ->
behavior image
my code:
void Update () {
if (Input.GetKeyDown (KeyCode.Space)) {
transform.position = new Vector3 (transform.position.x - 1, transform.position.y - 1, 0);
} else {
transform.RotateAround(new Vector3(0,0,0), new Vector3(0,0,1), 2);
}
}
Your code to 'jump' the orbit doesn't do what you want because Transform.RotateAround modifies both the rotation and the position of the object's transform.
So jumping to (position - 1,1,0) in the world is going to return wildly different results every time.
What you want to do instead is calculate the (Vector) direction from the object to the centre of orbit (the difference), then scale that down to how far you want it to move, then apply it to the position.
private Vector3 _orbitPos = Vector3.zero;
private float _orbitAngle = 2f;
private float _distanceToJump = 2f;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
var difference = (_orbitPos - transform.position).normalized * _distanceToJump;
transform.Translate(difference);
}
transform.RotateAround(_orbitPos, Vector3.forward, _orbitAngle);
}
This will move the object to be orbiting 2 units closer when space is pressed immediately.
If you wanted to have a smooth transition instead of a jump, look into using Mathf.Lerp, Vector3.Lerp and the routines involved.

Vector3.Lerp with code in Unity

I'm making a basic 2D space shooter game in unity. I have the movements working fine and the camera follows the player. I've been scratching my head over how to give the camera a slight delay from the player moving to the camera moving to catch up to it without it teleporting. I was told to use a Vector3.Lerp and tried a few things from stackoverflow answers but none seemed to work with the way my code is set up. Any suggestions?
(myTarget is linked to the player)
public class cameraFollower : MonoBehaviour {
public Transform myTarget;
void Update () {
if(myTarget != null){
Vector3 targPos = myTarget.position;
targPos.z = transform.position.z;
transform.position = targPos;
}
}
}
If you linear interpolate (Lerp) you risk that Time.deltaTime * speed > 1 in which case the camera will start to extrapolate. That is, instead of following it will get in front if your target.
An alternative is to use pow in your linear interpolation.
float speed = 2.5f;
float smooth = 1.0f - Mathf.Pow(0.5f, Time.deltaTime * speed);
transform.position = Vector3.Lerp(transform.position, targetPos, smooth);
Mathf.Pow(0.5, time) means that after 1/speed second, half of the distance to the target point will be travelled.
The idea with Lerping camera movement is to gradually and smoothly have the camera make its way to the target position.
The further away the camera is, the bigger the distance it will travel per frame, but the closer the camera is, the distance per frame becomes smaller, making the camera ease into its target position.
As an example, try replacing your transform.position = targPos; line with:
float speed = 2.5f; // Set speed to whatever you'd like
transform.position = Vector3.Lerp(transform.position, targPos, Time.deltaTime * speed);

Categories

Resources