Я разработал скрипт, который управляет движением персонажа с помощью клавиатуры и предотвращает его выход за пределы камеры. Скрипт функционирует должным образом, однако я добавил Canvas и поместил изображение, которое будет служить статус-баром, в верхней части экрана.
Теперь моя задача заключается в том, чтобы персонаж не могла пересечь зону статус-бара. Я пытался учесть высоту статус-бара в своих расчетах, переводя координаты из GUI в мировые, но мне это не удалось.
Вот мой код:
<pre><code class="cs">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);
Чтобы ограничить движение персонажа так, чтобы он не выходил за пределы видимости камеры и учитывал высоту статус-бара, необходимо выполнить следующие шаги:
1. Узнать высоту статус-бара в мировых координатах.
2. Изменить ограничения для вертикального перемещения персонажа, учитывая высоту статус-бара.
### Шаг 1: Определите высоту статус-бара
Вы можете получить положение статус-бара в мировых координатах, а затем использовать его высоту, чтобы скорректировать границы перемещения персонажа.
Если статус-бар является объектом с компонентом RectTransform, вы можете сделать это так:
```csharp
public RectTransform statusBar; // Ваш статус-бар
```
### Шаг 2: Измените ограничения в расчётах.
Теперь вам нужно будет учитывать высоту статус-бара при обновлении ограничений `minBounds` и `maxBounds`.
Пример исправленного кода:
```csharp
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;
public RectTransform statusBar; // Ссылка на статус-бар в редакторе
void Start()
{
mainCamera = Camera.main;
// Получаем размеры спрайта персонажа
SpriteRenderer sr = GetComponent<SpriteRenderer>();
halfWidth = sr.bounds.extents.x;
halfHeight = sr.bounds.extents.y;
}
void Update()
{
Movement();
}
void UpdateBounds()
{
// Размечаем границы камеры
minBounds = mainCamera.ViewportToWorldPoint(new Vector3(0, 0, mainCamera.nearClipPlane));
maxBounds = mainCamera.ViewportToWorldPoint(new Vector3(1, 1, mainCamera.nearClipPlane));
// Получаем высоту статус-бара в мировых координатах
float statusBarHeight = statusBar.rect.height * (1f / CanvasScaler.referencePixelsPerUnit); // Умножаем на 1 / PixelsPerUnit, чтобы получить высоту в мировых координатах
float statusBarWorldY = statusBar.anchoredPosition.y + statusBarHeight * 0.5f;
// Ограничиваем максимальные Y-границы на высоту статус-бара
maxBounds.y = statusBarWorldY - halfHeight;
}
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);
newPosition.y = Mathf.Clamp(newPosition.y, minBounds.y + halfHeight, maxBounds.y - halfHeight);
transform.position = newPosition; // Обновляем позицию персонажа
}
}
```
### Примечания:
1. Убедитесь, что в инспекторе Unity вы назначили ссылку на ваш статус-бар.
2. Если у вас есть CanvasScaler, используйте `referencePixelsPerUnit` для коррекции высоты в мировых координатах.
3. Каждая игра может иметь свои уникальные настройки, поэтому вам может потребоваться дальнейшая настройка.
Этот код позволяет вашему персонажу оставаться внутри видимых границ камеры и избегать пересечения статус-бара.
Используя комментарий пользователя 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; } }