Я начал изучать Unity, хотелось бы сделать управление таким, каким оно является в хороших платформерах. Сейчас я достиг неплохого результата, но есть вещи, которые мне не очень нравятся. Хотелось бы получить советы, правильно ли я вообще всё делаю или нет.
Основа управления простая:
void Start()
{
rb = gameObject.GetComponent<Rigidbody2D>();
}
private void ReactControlls()
{
if (Input.GetKey(KeyCode.D))
{
transform.Translate(new Vector2(Speed, 0) * Time.deltaTime);
}
else if (Input.GetKey(KeyCode.A))
{
transform.Translate(new Vector2(-Speed, 0) * Time.deltaTime);
}
}
if (Input.GetKeyDown(KeyCode.W))
{
if (IsGrounded)
{
rb.AddForce(new Vector2(0, JumpForce));
}
}
}
private void Checkers()
{
IsGrounded = Physics2D.OverlapArea(GroundCheck.bounds.min, GroundCheck.bounds.max, GroundLayers);
}
void Update()
{
Checkers();
ReactControlls();
}
GroundCheck – пустой объект, на который повесили BoxCollider2D и сделали триггером. Этот объект является дочерним для главного героя, находится у него в ногах.
На данном этапе возникают следующие проблемы:
1)персонаж не поворачивается, когда бегает в разные стороны;
2)если упереться в стену, то персонаж будет дёргаться, потому что ему удаётся немного проникнуть в коллайдер стены, после чего его оттуда выталкивает.
Пофиксим это:
void Start()
{
rb = gameObject.GetComponent<Rigidbody2D>();
sr = gameObject.GetComponent<SpriteRenderer>();
WayIsFreeR = true;
WayIsFreeL = true;
}
private void ReactControlls()
{
if (Input.GetKey(KeyCode.D))
{
if (WayIsFreeR)
{
transform.Translate(new Vector2(Speed, 0) * Time.deltaTime);
}
}
else if (Input.GetKey(KeyCode.A))
{
if (WayIsFreeL)
{
transform.Translate(new Vector2(-Speed, 0) * Time.deltaTime);
}
}
if (Input.GetKeyDown(KeyCode.W))
{
if (IsGrounded)
{
rb.AddForce(new Vector2(0, JumpForce));
}
}
}
private void Checkers()
{
IsGrounded = Physics2D.OverlapArea(GroundCheck.bounds.min, GroundCheck.bounds.max, GroundLayers);
WayIsFreeR = !Physics2D.OverlapArea(FaceR.bounds.min, FaceR.bounds.max, FaceLayers);
WayIsFreeL = !Physics2D.OverlapArea(FaceL.bounds.min, FaceL.bounds.max, FaceLayers);
}
private void Animations()
{
float direction = Input.GetAxisRaw("Horizontal") * Time.deltaTime;
if (direction < 0)
{
sr.flipX = true;
}
else if (direction > 0)
{
sr.flipX = false;
}
}
// Update is called once per frame
void Update()
{
Checkers();
Animations();
ReactControlls();
}
Объекты WayIsFreeR и WayIsFreeL – пустые объекты, на которые навесили BoxCollider2D и сделали триггером. Представляют они из себя тонкие прямоугольники, имеющие практически такую же высоту, какую имеет главный персонаж. Они являются дочерними объектами для главного персонажа и размещаются вплотную справа и слева от него. Выглядит это как-то так:
Тут посередине находится основной коллайдер персонажа, справа от него тонкий WayIsFreeR , слева WayIsFreeL а снизу – GroundCheck.
Идея следующая: как только WayIsFreeR пересекает какой-то коллайдер, персонаж тупо больше не может идти вправо (аналогично для WayIsFreeL). Возникает первая проблема – да, герой больше не пытается воткнуться в стену, но в разное время расстояние, на котором он останавливается от стены, немного разное. Допустим мы передвигаемся по X от координаты 0, каждый кадр наша координата увеличивается на 20. Длина буфера, который сигнализирует нам о том, что справа преграда и дальше двигаться нельзя, равна 7. Преграда начинается с координаты 105. Вот мы попали в аналогичную ситуацию, как мне кажется – на прошлом кадре мы были на координате 80, всё было хорошо и мы шли дальше. На этом кадре мы на координате 100, дальше идти не можем. При этом расстояние до преграды меньше буфера.
Я нашёл лишь одно возможное решение этой проблемы: подогнать скорость персонажа так, чтобы мы не могли проскочить в этот "буфер" в принципе (объекты нужно будет размещать тоже в определённых точках). Но это, как мне кажется, ооооочень затратно по времени.
Собственно, вопрос можно сформулировать следующим образом: целесообразно ли всё делать через коллайдеры, как это сделал я. Если да, то как можно пофиксить мою проблему. Если нет, то как сделать иначе (хотя бы в какую сторону смотреть).