Я работаю над проектом, в котором я хочу, чтобы игрок, обозначенный белым кругом, ходил по сетке тайловой карты при нажатии WASD и останавливался, когда перед направлением его движения стояла стена. Но когда я запускаю игру и пытаюсь переместить игрока, он просто проходит сквозь стену. Я некоторое время решал этот вопрос и понятия не имею, что я сделал не так.
Я попытался удалить составной коллайдер 2d, игрок получил блок у стены. Однако иногда, когда игрок врезается в стену, он отскакивает от стены. Например, когда игрок идет к левой стороне стены, он получит выстрел влево и окажется слева от стены. Я пытаюсь уменьшить скорость движения игрока, уменьшив moveTimePerGrid в моем сценарии движения игрока, но это не работает. Я также установил слой для игрока и стен и настроил их так, чтобы они могли сталкиваться друг с другом в матрице коллайдера, но это не работает.
(https://i.sstatic.net/bmRXpIcU.png)
Поскольку вы неоднократно устанавливаете положение объекта, чтобы заставить его двигаться, система разрешения столкновений Unity не работает. Если вы хотите, чтобы движение по сетке имело столкновения, вам придется проверять и разрешать столкновения внутри функции MovePlayer. Вы можете использовать raycasts, поместив что-то вроде этого в функцию MovePlayer:
if (Physics2D.Raycast(transform.position, direction, (transform.position
- targetPosition).magnitude) == 1){
// move the player because the raycast found no object in front of
// the player other than the player itself
transform.position = targetPosition;
}
else{
// player should not move because of an object in the way.
transform.position = playerPosition;
}
Перемещение твердого тела должно выполняться в пределах FixedUpdate
, и вы не можете использовать transform.position
, иначе столкновения не будут разрешены.
Однако для этого я бы просто использовал свойство velocity
вашего твердого тела, которое будет двигаться за вас. Вместо этого ваш код должен выглядеть примерно так:
[SerializeField] private Rigidbody2D body;
float movementEndTime;
void FixedUpdate() {
if (Time.time > movementEndTime) {
if (Input.GetKeyDown(KeyCode.W)) {
body.velocity = Vector2.up * (1f / moveTimePerGrid);
movementEndTime = moveTimePerGrid;
} else if (Input.GetKeyDown(KeyCode.A)) {
body.velocity = Vector2.left * (1f / moveTimePerGrid);
movementEndTime = moveTimePerGrid;
} else if (Input.GetKeyDown(KeyCode.S)) {
body.velocity = Vector2.down * (1f / moveTimePerGrid);
movementEndTime = moveTimePerGrid;
} else if (Input.GetKeyDown(KeyCode.D)) {
body.velocity = Vector2.right * (1f / moveTimePerGrid);
movementEndTime = moveTimePerGrid;
}
}
}
Если вам нужна помощь, вам нужно будет показать код, который вы используете.