Начал изучение C# и юнити в целом неделю назад, так что я совсем еще чайник. В общем, всё работает почти идеально, не учитывая того, что через каждые 2-3 раза прыжок просто отказывается срабатывать, как бы упорно я не ебашил по пробелу. Подозреваю, что проблема связана с проверкой на касание земли, но без нее прыжками можно буквально взлететь. Как пофиксить? using UnityEngine; public class PlayerMovementJump : MonoBehaviour { public Rigidbody rb; public float forwardForce = 2000f; public float sidewaysForce = 500f; public float jumpForce = 5f; public float fallForce = -15f; private bool isGrounded = true; void FixedUpdate() { // Постоянное движение вперед rb.AddForce(0, 0, forwardForce * Time.deltaTime); // Движение вправо if (Input.GetKey("d")) { rb.AddForce(sidewaysForce * Time.deltaTime, 0, 0, ForceMode.VelocityChange); } // Движение влево if (Input.GetKey("a")) { rb.AddForce(-sidewaysForce * Time.deltaTime, 0, 0, ForceMode.VelocityChange); } // Проверка прыжка if (Input.GetKeyDown(KeyCode.Space) && isGrounded) { this.jump(); // Вызов метода jump } rb.AddForce(0, fallForce, 0); // Ускоряет падение объекта // Проверка падения if (rb.position.y < -1f) { FindObjectOfType<GameManager>().EndGame(); } } private void jump() { rb.AddForce(0, jumpForce, 0, ForceMode.VelocityChange); isGrounded = false; // Запретить прыжок до следующего касания земли } private void OnCollisionEnter(Collision collision) { if (collision.gameObject.CompareTag("Ground")) { isGrounded = true; // Разрешить прыжок } } } CSHARP using UnityEngine; public class PlayerMovementJump : MonoBehaviour { public Rigidbody rb; public float forwardForce = 2000f; public float sidewaysForce = 500f; public float jumpForce = 5f; public float fallForce = -15f; private bool isGrounded = true; void FixedUpdate() { // Постоянное движение вперед rb.AddForce(0, 0, forwardForce * Time.deltaTime); // Движение вправо if (Input.GetKey("d")) { rb.AddForce(sidewaysForce * Time.deltaTime, 0, 0, ForceMode.VelocityChange); } // Движение влево if (Input.GetKey("a")) { rb.AddForce(-sidewaysForce * Time.deltaTime, 0, 0, ForceMode.VelocityChange); } // Проверка прыжка if (Input.GetKeyDown(KeyCode.Space) && isGrounded) { this.jump(); // Вызов метода jump } rb.AddForce(0, fallForce, 0); // Ускоряет падение объекта // Проверка падения if (rb.position.y < -1f) { FindObjectOfType<GameManager>().EndGame(); } } private void jump() { rb.AddForce(0, jumpForce, 0, ForceMode.VelocityChange); isGrounded = false; // Запретить прыжок до следующего касания земли } private void OnCollisionEnter(Collision collision) { if (collision.gameObject.CompareTag("Ground")) { isGrounded = true; // Разрешить прыжок } } }
Проблема может быть связана с тем, что флаг isGrounded не успевает корректно обновиться при быстром взаимодействии между прыжком и касанием земли. Это может происходить, например, из-за микроскопических временных лагов или особенностей физического взаимодействия объекта с поверхностью. Вот несколько шагов для устранения проблемы: 1. Уточните проверку касания земли Добавьте проверку слоя или тегов для большей точности. Иногда коллайдер объекта может вступить в контакт с чем-то, что не является “землёй”. if (collision.gameObject.CompareTag("Ground")) { isGrounded = true; } 2. Добавьте минимальную задержку между прыжками Вместо использования только флага isGrounded, можно добавить небольшой таймер, чтобы избежать ложных срабатываний: private float jumpCooldown = 0.1f; // Минимальная задержка между прыжками private float lastJumpTime = 0f; private void jump() { if (Time.time - lastJumpTime >= jumpCooldown) { rb.AddForce(0, jumpForce, 0, ForceMode.VelocityChange); isGrounded = false; lastJumpTime = Time.time; } } 3. Используйте луч (Raycast) для проверки соприкосновения с землёй Физическая проверка с помощью луча обычно работает более надёжно, чем полагаться на события OnCollisionEnter. Пример: Добавьте проверку в метод FixedUpdate: private void CheckIfGrounded() { float rayLength = 1.1f; // Длина луча чуть больше радиуса коллайдера isGrounded = Physics.Raycast(transform.position, Vector3.down, rayLength); } Замените вызовы обновления isGrounded: void FixedUpdate() { CheckIfGrounded(); // Движение и прыжок остаются теми же } 4. Добавьте слои для точной проверки земли Убедитесь, что у объекта “земля” установлен соответствующий слой (например, “Ground”), и используйте его в проверке Raycast: LayerMask groundLayer; // Назначьте слой через инспектор private void CheckIfGrounded() { float rayLength = 1.1f; isGrounded = Physics.Raycast(transform.position, Vector3.down, rayLength, groundLayer); } 5. Проверка физического слоя коллайдеров Проверьте размеры и расположение коллайдеров для “земли” и игрока, чтобы избежать ложных срабатываний. Убедитесь, что игрок действительно касается земли. Итоговый код: Вот обновлённая версия с улучшенной проверкой касания земли: using UnityEngine; public class PlayerMovementJump : MonoBehaviour { public Rigidbody rb; public float forwardForce = 2000f; public float sidewaysForce = 500f; public float jumpForce = 5f; public float fallForce = -15f; public LayerMask groundLayer; private bool isGrounded = true; private float jumpCooldown = 0.1f; private float lastJumpTime = 0f; void FixedUpdate() { // Постоянное движение вперед rb.AddForce(0, 0, forwardForce * Time.deltaTime); // Движение вправо if (Input.GetKey("d")) { rb.AddForce(sidewaysForce * Time.deltaTime, 0, 0, ForceMode.VelocityChange); } // Движение влево if (Input.GetKey("a")) { rb.AddForce(-sidewaysForce * Time.deltaTime, 0, 0, ForceMode.VelocityChange); } // Проверка состояния земли CheckIfGrounded(); // Прыжок if (Input.GetKeyDown(KeyCode.Space) && isGrounded) { jump(); } rb.AddForce(0, fallForce, 0); // Проверка падения if (rb.position.y < -1f) { FindObjectOfType<GameManager>().EndGame(); } } private void jump() { if (Time.time - lastJumpTime >= jumpCooldown) { rb.AddForce(0, jumpForce, 0, ForceMode.VelocityChange); isGrounded = false; lastJumpTime = Time.time; } } private void CheckIfGrounded() { float rayLength = 1.1f; // Длина луча чуть больше радиуса коллайдера isGrounded = Physics.Raycast(transform.position, Vector3.down, rayLength, groundLayer); } } 6. Совет: настройка слоя “Ground” Убедитесь, что слой “Ground” назначен всем объектам, которые игрок может использовать для прыжка. Выберите объект в Unity, установите слой в поле Layer, а затем присвойте его переменной groundLayer в инспекторе. Этот подход должен устранить проблему с нерегулярным срабатыванием прыжков.
GetKeyDown возвращает true только в кадре, в котором была нажата клавиша. FixedUpdate не срабатывает в каждом кадре, поэтому он может пропустить тот, в котором была нажата кнопка. Нужно было просто изменить FixedUpdate на Update