Задать вопрос
@Lalka-Game-Studio

Как запретить персонажу (2D) выход за границы камеры, с учётом высоты статус бара?

Я написал скрипт, который вешается на персонажа, осуществляет его движение с помощью клавиатуры и не даёт выйти за границы камеры. Скрипт работает, но теперь я добавил Canvas, поместил картинку (которая будет у меня статус баром) в верхнюю часть экрана.

Задача: нужно чтобы персонаж не мог зайти в зону статус бара.
Я пытался учесть высоту статус бара в расчётах, переводил из Gui координат в мировые, но всё безуспешно.

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    private float speed = 10f;

    private Camera mainCamera;
    private Vector2 minBounds;
    private Vector2 maxBounds;

    private float halfWidth;
    private float halfHeight;

    void Start()
    {
        mainCamera = Camera.main;

        // Получаем размеры спрайта персонажа
        SpriteRenderer sr = GetComponent<SpriteRenderer>();
        halfWidth = sr.bounds.extents.x;
        halfHeight = sr.bounds.extents.y;
    }

    void Update()
    {
        Movement();
    }

    void Movement()
    {
        UpdateBounds();

        float horDirection = Input.GetAxis("Horizontal");
        float vertDirection = Input.GetAxis("Vertical");

        Vector3 newPosition = transform.position + speed * Time.deltaTime * new Vector3(horDirection, vertDirection, 0);

        // Ограничиваем позицию по X и Y с учётом размеров персонажа и границ камеры
        newPosition.x = Mathf.Clamp(newPosition.x, minBounds.x + halfWidth, maxBounds.x - halfWidth);
        // TODO: я добавил статус бар, теперь нужно учитывать его высоту в расчетах
        newPosition.y = Mathf.Clamp(newPosition.y, minBounds.y + halfHeight, maxBounds.y - halfHeight);

        transform.position = newPosition;
    }

    void UpdateBounds()
    {
        // Получаем границы камеры в мировых координатах
        Vector3 bottomLeft = mainCamera.ViewportToWorldPoint(new Vector3(0, 0, mainCamera.nearClipPlane));
        Vector3 topRight = mainCamera.ViewportToWorldPoint(new Vector3(1, 1, mainCamera.nearClipPlane));

        minBounds = bottomLeft;
        maxBounds = topRight;
    }
}


Вот так выглядят параметры Canvas:
680e321d25079482030538.png
  • Вопрос задан
  • 26 просмотров
Подписаться 1 Средний 2 комментария
Решения вопроса 1
@Lalka-Game-Studio Автор вопроса
Используя комментарий пользователя DrRen7, я решил задачу. Полный рабочий скрипт выглядит вот так:

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    [SerializeField] GameObject canvasObject;
    [SerializeField] GameObject statusBarObject;

    private float speed = 10f;

    private Camera mainCamera;
    private Vector2 minBounds;
    private Vector2 maxBounds;

    private float halfWidth;
    private float halfHeight;

    private float statusBarRealHeight;

    void Start()
    {
        mainCamera = Camera.main;

        // Получаем размеры спрайта персонажа
        SpriteRenderer sr = GetComponent<SpriteRenderer>();
        halfWidth = sr.bounds.extents.x;
        halfHeight = sr.bounds.extents.y;
    }

    void Update()
    {
        Movement();
    }

    void Movement()
    {
        UpdateBounds();
        CalcStatusBarRealHeight();

        float horDirection = Input.GetAxis("Horizontal");
        float vertDirection = Input.GetAxis("Vertical");

        Vector3 newPosition = transform.position + speed * Time.deltaTime * new Vector3(horDirection, vertDirection, 0);

        // Ограничиваем позицию по X и Y с учётом размеров персонажа и границ камеры, а также высоты статус бара
        newPosition.x = Mathf.Clamp(newPosition.x, minBounds.x + halfWidth, maxBounds.x - halfWidth);
        newPosition.y = Mathf.Clamp(newPosition.y, minBounds.y + halfHeight, maxBounds.y - halfHeight - statusBarRealHeight);

        transform.position = newPosition;
    }

    void UpdateBounds()
    {
        // Получаем границы камеры в мировых координатах
        Vector3 bottomLeft = mainCamera.ViewportToWorldPoint(new Vector3(0, 0, mainCamera.nearClipPlane));
        Vector3 topRight = mainCamera.ViewportToWorldPoint(new Vector3(1, 1, mainCamera.nearClipPlane));

        minBounds = bottomLeft;
        maxBounds = topRight;
    }

    // Вычисляем высоту статус бара
    void CalcStatusBarRealHeight()
    {
        float canvasScale = canvasObject.GetComponent<RectTransform>().localScale.y;
        float absoluteHeight = statusBarObject.GetComponent<RectTransform>().sizeDelta.y;
        statusBarRealHeight = absoluteHeight * canvasScale;
    }
}
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

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

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