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.
Related
I am creating a Jump and run game but you are driving with a car. I use the the Wheel Joint 2D collider and I am also able to jump. Here is my code for the movement:
void Update()
{
movement = Input.GetAxis("Horizontal");
if (Input.GetButtonDown("Jump") && IsGrounded())
{
carRb.velocity = new Vector2(carRb.velocity.x, jumpForce);
}
if (Input.GetButtonUp("Jump") && carRb.velocity.y > 0f)
{
carRb.velocity = new Vector2(carRb.velocity.x, carRb.velocity.y * 0.5f);
}
}
private void FixedUpdate()
{
backTire.AddTorque(-movement * speed * Time.fixedDeltaTime);
frontTire.AddTorque(-movement * speed * Time.fixedDeltaTime);
carRb.AddTorque(-movement * carTorque * Time.fixedDeltaTime);
}
It works just fine but when I am fast and jump I rotate completely around my own axis and I land on my head and can't move anymore. Therefore I want to limit the rotation of the z-axis to a certain degree so that it won't happen anymore. I looked up how to do it but it doesn't fit for my car-context. Do you have any idea?
I would be very grateful
You have multiple options to solve this:
Freeze the rotation axis on the rigibody (very limiting option)
Detect the faulty position as "upside-down + grounded" and respawn the vehicle after 2s
Forcefully rotate the vehicle back to normal rotation when it's grounded (not in air anymore, so you still allow flips in the air)
Limit the angle via script.
Last thing could be done like this:
Vector3 eulerRot = rb.rotation.eulerAngles; // read current rotation
eulerRot.z = Mathf.Clamp(eulerRot .y, minRotation, maxRotation); // clamp it only on z axis.
rb.rotation = Quaternion.Euler(eulerRot); // set clamped rotation
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
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.
Im making a game in Unity. My task is to when player presses the "1' key, it shoots out a sphere to the player.transform.forward position, until it collides with an enemy.
The problem is, when the sphere has been shot, while its flying, I can controll its moving X value by turning the player right or left. So the sphere moves with me, but it should not. This is of course because in Update(), I move it in the player's facing direction. How can I make the sphere start facing at the players direction, but after move independently?
This is the code that moves the sphere
private float speed = 4.0f;
void Update()
{
transform.Translate(player.transform.forward * Time.deltaTime * speed);
}
You could save it's inital "forward" direction and reference it afterwards
public GameObject player;
private float speed = 4.0f;
private Vector3 direction;
private void Awake() //I used Awake() as example asuming you are instantiating the sphere,
{ //but you could set the value of the direction when you press "1" too
direction = player.transform.forward;
}
void Update()
{
transform.Translate(direction * Time.deltaTime * speed);
}
Instantiate it with the correct orientation
Instantiate(rangedAttack, spawnPosition, player.transform.rotation);
Now its own forward vector points the same direction as the one of the player.
And then simply do
private float speed = 4.0f;
void Update()
{
transform.Translate(Vector3.forward * Time.deltaTime * speed);
}
Note Translate by default works in the Space.Self so the local space of this transform. You do not want to pass in a worldspace Vector here but rather move only in the local Z axis!
If you pass in a worldspace vector you will nee to pass Space.World
transform.Translate(vector, Space.World);
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.