@YakutD

Как сделать лестницу в Unity 2D?

Здравствуйте, делаем простой 2d платформер, и возникли сложности с лестницей ._. Суть в том, что необходимо чтобы персонаж мог залезая на лестницу стоять на ней, и по нажатию стрелки вниз спускаться. Для того чтобы это сделать, мы использовали PlatformEffector2D у платформы с которой соприкасается лестница в своей верхней точке, и написали скрипт, который должен менять rotationalOffset при соприкосновении персонажа с коллайдером этой самой платформы, в зависимости от его текущего значения(0 или 180) и зажатой клавиши (вверх или вниз). Вот код:
private void OnCollisionStay2D(Collision2D col)
    {
        if (col.gameObject.name == "platform_ladder")
        {
            PlatformEffector2D pe = col.gameObject.GetComponent<PlatformEffector2D>();
            if (Input.GetKeyDown(KeyCode.DownArrow) && pe.rotationalOffset == 0)
            {
                pe.rotationalOffset = 180;
            }
            else if (Input.GetKeyDown(KeyCode.UpArrow) && pe.rotationalOffset == 180)
            {
                pe.rotationalOffset = 0;
            }
        }
    }

По итогу, персонаж забирается по лестнице, стоит на ней, но на нажатие клавиши вниз не реагирует. Если отойти и снова наступив нажить тогда скрипт срабатывает, и rotationoffset меняется. Однако тогда не получается стоять на платформе, и персонаж просто лазает сквозь нее туда сюда. Привожу пример записи с экрана (к сожалению сильно тормозит видео, но суть того что я написал на нем видно)
https://drive.google.com/open?id=1ccUi0sqtVxFS1UAK...

На всякий случай приведу код вскарабкивания по лестнице, вдруг ошибка кроется в нем:
/* CLimbing */
        //если персонаж находится в зоне подъема по лестнице
        raydistance = 0;
        RaycastHit2D hitinfo = Physics2D.Raycast(transform.position, Vector2.up, raydistance, whatisLadder);

        if (hitinfo.collider != null)
        {

            if (Input.GetKeyDown(KeyCode.UpArrow))
            {
                isClimbing = true;

            }
            else if (Input.GetKeyDown(KeyCode.RightArrow) || Input.GetKeyDown(KeyCode.LeftArrow))
            {
                isClimbing = false;
            }

        }
        else
        {
            isClimbing = false;
        }

        anim.SetBool("OnLadder", isClimbing);

        if (isClimbing && hitinfo.collider != null)
        {
            rb.velocity = new Vector2(rb.position.x, Input.GetAxisRaw("Vertical") * speed);
            // rb.gravityScale = 0;
            rb.isKinematic = true;
            anim.SetBool("Ground", true);//Принудительно блокируем анимацию прыжка
        }
        else
        {
            rb.isKinematic = false;
            // rb.gravityScale = 3;
        }


Мы не просим написать код решения, но просим объяснить нам принцип и направить в верную сторону, спасибо ^^
  • Вопрос задан
  • 2284 просмотра
Решения вопроса 1
@YakutD Автор вопроса
Ну что же, проблему решили самостоятельно. Лестница у нас представляет собой сложный объект из самой платформы, лестницы, и невидимого тригера. Лестница и тригер принадлежат двум разным слоям Ladder и Crutch (так мы их решили назвать), а платформа имеет тот же слой что и земля.
Мы используем Physics.IgnoreCollision(true) когда пользователь цепляет направленным вниз raycast слой Crutch (наш тригер), когда же луч не обнаруживает этот слой, или когда юзер нажимает клавишу вверх, то Physics.IgnoreCollision становится снова false. Для того, чтобы во время спуска Physics.IgnoreCollision не переключался на false раньше времени, и платформа своим коллайдером не толкала пользователя, размер коллайдера тригера равен половине высоты лестницы, и его верхняя точка ненамного превышает расположение самой платформы. Для того чтобы юзер поднимался вверх через платформу мы используем PlatformEffector, если вдруг кто не обратил внимание.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы