Hi,

I just started learning Unity and I was trying to make a 3D breakout game. I have a script attached to the ball object. It adds force to the ball when the ball is fired. After being fired, the movement and bouncing behavior of the ball is totally controlled by physics. It works well until at some point the ball moves vertically or horizontally, then it just keeping bouncing forever between walls. Here is my initial code:

 void Update(){
             if (Input.GetButtonDown ("Fire1") && isFired == false) {
                 transform.parent = null;
                 isFired = true;
                 rb.isKinematic = false;
                 rb.AddForce (new Vector3 (velocity, velocity, 0));
 
             }
     }

To avoid this situation, I added some code that detects if the ball is moving along only one axis, and was trying to change its moving direction when the situation happens. However, I’m not sure which function or property that I am supposed to use to change the moving direction without changing the speed. I tried transform.Rotate() and transform.forward, but didn’t work. I would really appreciate it if anyone can show me what is the right way to do this task. Thank you very much!!

Here is my current code

void Update(){
 
         if (isFired) {
             previousX = posX;
             previousY = posY;
             posX = transform.position.x;
             posY = transform.position.y;
 
 //Compare ball's current position with last frame
             if ((posX - previousX) * (posX - previousX) <= 0.001 ||(posY - previousY) * (posY - previousY) <= 0.001) {
                 count++;
         }
         }
 // if the x or y position hasn't changed for 50 frames, I would consider it as the 'perfect bouncing' situation. 
         if(count > 50) {
 //the targetPos(target position) is the center of the screen. So when the situation happens, the ball will tilt to that direction. 
             Vector3 targetDir = transform.position - targetPos;
 //            HERE. I don't know what to write to change the moving direction of the ball without changing its speed. 
             count = 0;
         }
 
             if (Input.GetButtonDown ("Fire1") && isFired == false) {
                 transform.parent = null;
                 isFired = true;
                 rb.isKinematic = false;
                 rb.AddForce (new Vector3 (velocity, velocity, 0));
 
             }    
     }

I had same problem dude !

I solved it by adding following code on ball script:

    Vector2 vel;
	Vector2 currentVel, targetVel;
	void LateUpdate () {
		currentVel = this.rb.velocity; // save current velocity
		vel = currentVel.normalized; // get direction
		targetVel = vel * startVelocity; // set target velocity according to default speed of ball
		this.rb.velocity = Vector2.Lerp (currentVel, targetVel, Time.deltaTime * 10);

		// Direction control
		if(GameManager.instance.gamestate == GameManager.GameState.GamePlay) {
			// Horizontal movement				
			if(vel.y >= -0.3f && vel.y <= 0) { //&& vel.y <= 0.3f) {
				HorizontalDown();
			}
			else if(vel.y >= 0 && vel.y <= 0.3f) {
				HorizontalUp();
			}

			// Vertical movement				
			if(vel.x >= -0.2f && vel.x <= 0) { //&& vel.y <= 0.3f) {
				VerticalDown();
			}
			else if(vel.x >= 0 && vel.x <= 0.2f) {
				VerticalUp();
			}
		}

	}

    // Ball direction control
	bool isHorizontalDown = false;
	public void HorizontalDown() {
		
		if (!isHorizontalDown) {
			isHorizontalDown = true;
			vel.y -= 0.3f;
			Vector2 v2 = new Vector3(vel.x, vel.y);
			this.rb.AddForce(v2 * 50);
			Invoke("ResetHorizontalDown", 1);
		}
		
	}
	
	bool isHorizontalUp = false;
	public void HorizontalUp() {
		
		if (!isHorizontalUp) {
			isHorizontalUp = true;
			vel.y += 0.3f;
			Vector2 v2 = new Vector2(vel.x, vel.y);
			this.rb.AddForce(v2 * 50);
			Invoke("ResetHorizontalUp", 1);
		}
		
	}

	bool isVerticalDown = false;
	public void VerticalDown() {

		if(!isVerticalDown) {
			isVerticalDown = true;
			vel.x -= 0.3f;
			Vector2 v2 = new Vector3(vel.x, vel.y);
			this.rb.AddForce(v2 * 50);
			Invoke("ResetVerticalDown", 1);
		}
	}

	bool isVerticalUp = false;
	public void VerticalUp() {

		if(!isVerticalUp) {
			isVerticalUp = true;
			vel.x += 0.3f;
			Vector2 v2 = new Vector2(vel.x, vel.y);
			this.rb.AddForce(v2 * 50);
			Invoke("ResetVerticalUp", 1);
		}
	}
	
	void ResetHorizontalDown() {
		isHorizontalDown = false;
	}
	
	void ResetHorizontalUp() {
		isHorizontalUp = false;
	}

	void ResetVerticalDown() {
		isVerticalDown = false;
	}
	
	void ResetVerticalUp() {
		isVerticalUp = false;
	}

PS. I used velocity instead of force, so be careful for choose ‘startvelocity’ value !!