Когда реализуешь Breakout нет необходимости использовать физику через приложения силы или изменения Rigidbody.velocity, можно сделать шар isKinematic = true для коллизий и тригеров и двигать его вручную, только придётся просчитывать удары и отражать векторы, зато будет точнее. В любом случае, тебе всего лишь надо менять направление движения через векторы. Если ты изменяешь velocity, то тебе надо повернуть этот вектор. Скорость объекта это длина вектора velocity, т. е. velocity.magnitude, которую ты должен всегда держать неизменяемой для одинаковой скорости. Задать вектор velocity можно по-разному, чтобы повернуть на определённый градус можно написать так:
Код
void OnCollisionExit(Collision other)
{
if (other.transform.CompareTag("Доска"))
{
// Поворачиваем вектор на 10 градусов
rb.velocity = Quaternion.AngleAxis(10f, transform.up) * rb.velocity;
}
}
В общем ты должен сам определять на основании чего менять угол. В случае с доской - определяешь скорость движения доски для влияния на угол или как делают иногда в Breakout в зависимости от места удара доски, чем дальше от центра тем больше угол.
Посмотри готовый проект с Breakout, там контролируется макс. и мин. скорость:
Код
public class Ball : MonoBehaviour {
public float maxVelocity = 20;
public float minVelocity = 15;
void Awake () {
GetComponent<Rigidbody>().velocity = new Vector3(0, 0, -18);
}
void Update () {
//Make sure we stay between the MAX and MIN speed.
float totalVelocity = Vector3.Magnitude(GetComponent<Rigidbody>().velocity);
if(totalVelocity>maxVelocity){
float tooHard = totalVelocity / maxVelocity;
GetComponent<Rigidbody>().velocity /= tooHard;
}
else if (totalVelocity < minVelocity)
{
float tooSlowRate = totalVelocity / minVelocity;
GetComponent<Rigidbody>().velocity /= tooSlowRate;
}
//Is the ball below -3? Then we're game over.
if(transform.position.z <= -3){
BreakoutGame.SP.LostBall();
Destroy(gameObject);
}
}
}
Но здесь лучше вместо Update() использовать FixedUpdate() где изменяется скорость и если скорость всегда константная, то можно написать:
Код
void Start() {
rb = GetComponent<Rigidbody>();
}
void FixedUpdate() {
rb.velocity = rb.velocity.normalized * speed; // speed - это float с заданной скоростью
}
И в зависимости от центра доски немного смещается шар:
Код
public class Paddle : MonoBehaviour {
public float moveSpeed = 15;
void Update () {
float moveInput = Input.GetAxis("Horizontal") * Time.deltaTime * moveSpeed;
transform.position += new Vector3(moveInput, 0, 0);
float max = 14.0f;
if (transform.position.x <= -max || transform.position.x >= max)
{
float xPos = Mathf.Clamp(transform.position.x, -max, max); //Clamp between min -5 and max 5
transform.position = new Vector3(xPos, transform.position.y, transform.position.z);
}
}
void OnCollisionExit(Collision collisionInfo ) {
//Add X velocity..otherwise the ball would only go up&down
Rigidbody rigid = collisionInfo.rigidbody;
float xDistance = rigid.position.x - transform.position.x;
rigid.velocity = new Vector3(rigid.velocity.x + xDistance/2, rigid.velocity.y, rigid.velocity.z);
}
}