프로젝트를 진행하다가 플레이어가 화면 밖으로 나가는 문제를 마주해서 해결하기로 했다.
화면 구성이 위 이미지처럼 되어 있는데 밑의 UI까지 제외하고 다른 영역에서만 움직일 수 있어야 한다.
메인 카메라는 게임에서 움직이지 않을 계획이다.
두 가지 방법을 고려해봤는데 화면 테두리에 Collider를 가진 경계를 배치하는 방법과 Player의 트랜스폼에 Clamp를 적용하는 방법이다.
그런데 플레이어가 가지고 있는 리지드바디가 Kinematic속성이라 경계를 배치해서 충돌을 통해 화면 바깥으로 나가는 것을 막으려면 경계도 리지드바디를 들고 있어야 하는데 굳이 그럴 필요가 없다고 생각됐다.
게다가 그렇게 하면 적을 스폰할 때 화면 바깥에서 스폰하고 화면 안으로 진입하는 것도 불가능하게 된다. 적도 리지드바디를 가지고 있을 것이기 때문이다.
그래서 두 번째 방법인 트랜스폼에 Clamp를 적용하기로 했다.
아래는 해당 코드다.
// 클래스 내부의 필드들
private float _positionClampValueX;
private float _positionClampValueY;
private float _playerUIHeight;
// Start에서 호출해줄 초기화 함수
private void Init()
{
Camera _camera = Camera.main;
float camHeightSize = _camera.orthographicSize * 2;
float meterPerPixel = camHeightSize / Screen.height;
float halfWidthSize = meterPerPixel * Screen.width / 2;
float halfHeightSize = _camera.orthographicSize;
Bounds bounds = SpriteRenderer.sprite.bounds;
float maxExtentValue = Mathf.Max(bounds.extents.x * 2, bounds.extents.y * 2);
_positionClampValueX = halfWidthSize - maxExtentValue;
_positionClampValueY = halfHeightSize - maxExtentValue;
// 밑의 내용은 UI에 해당하는 부분도 이동하지 못하도록 계산하기 위함이다.
Vector2 sizeDelta = GameManager.Instance.PlayerUI.transform.Find(PLAYER_UI_BAR).GetComponent<RectTransform>().sizeDelta;
_playerUIHeight = sizeDelta.y * meterPerPixel;
}
// 이 함수를 Update에서 실행한다.
private void ClampPlayerPosition()
{
Vector3 position = Character.transform.position;
// x축 clamp
if (position.x > _positionClampValueX || position.x < -_positionClampValueX)
{
position.x = Mathf.Clamp(position.x, -_positionClampValueX, _positionClampValueX);
}
// y축 clamp
if (position.y > _positionClampValueY || position.y < -_positionClampValueY + _playerUIHeight)
{
position.y = Mathf.Clamp(position.y, -_positionClampValueY + _playerUIHeight, _positionClampValueY);
}
Character.transform.position = position;
}
카메라를 통해서 화면의 크기를 구해서 해당 값으로만 Clamp를 하면 플레이어의 스프라이트가 절반이 가려지는 것을 막을 수 없기 때문에 플레이어의 스프라이트가 가질 수 있는 최대 값을 구해서 그 값도 더해서 가려지는 것을 막았다.
그리고 UI 부분의 크기만큼 Y축 Clamp에서 적용되도록 했기 때문에 UI도 피하고 실제 보여지는 화면 안에서만 움직이게 되었다.
만약 3D라고 하더라도 로직이 크게 바뀔 것 같지는 않고 축 계산이 하나 더 늘어나고 UI를 계산하는 부분이 빠지면 될 것이다.
'부트캠프' 카테고리의 다른 글
팀 프로젝트 마무리(협업을 잘하자) (0) | 2023.09.14 |
---|---|
코루틴으로 적 움직임 구현해보기 (1) | 2023.09.14 |
HP bar를 스프라이트로 구현하기 (0) | 2023.09.11 |
버튼에 리스너 달기 (0) | 2023.09.07 |
타일맵에서 장애물 투명하게 만들기 (0) | 2023.09.06 |