일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- FPS
- 게임제작
- 퐁
- 게임 개발
- 자바스크립트
- 1인 개발
- 유니티
- unity3d
- 자바스크립트 게임
- 합격
- Unity2D
- portal
- 게임
- 1인 게임 제작
- Pong
- 3회차
- 정보처리기사
- Unity #Unity2D #Portal
- 유니티3d
- 유니티 3D
- Vampire Survivors
- 정처기
- 1인 게임 개발
- 정처기 필기
- 토이 프로젝트
- Unity
- 1인 게임
- 프로그래머스 #최소힙 #우선순위 큐
- 필기
- 게임 제작
- Today
- Total
Coding Feature.
[Unity 2D] Portal 같은 게임 만들기 #6 포탈, 포탈건, 캐릭터의 버그 해결 본문
[Unity 2D] Portal 같은 게임 만들기 #6 포탈, 포탈건, 캐릭터의 버그 해결
codingfeature 2024. 1. 8. 15:50이제 앞서 만든 포탈과 포탈건 매커니즘에 대해서 발생할 수 있는 여러 가지 버그 또는 리스크 들을 해결하여 더욱 완벽한 게임 플레이 경험을 만들어 보겠습니다!
- 두 포탈이 겹치는 경우 처리
포탈건으로 같은 벽면에 블루, 오렌지 포탈을 쏜다면 겹쳐질 것입니다.
이를 해결하기 위해 블루, 오렌지 포탈의 Collider가 겹치는지 확인하는 코드를 작성했습니다.
private void HandlePortalCreation()
{
if (Input.GetKeyDown(KeyCode.Mouse0))
{
m_tempVector = bluePortal.transform.position; // 이전 포탈 위치 저장.
m_tempQuaternion = bluePortal.transform.rotation; // 이전 포탈 각도 저장.
bluePortal.transform.position = new Vector3(portal_X, portal_Y, 0);
bluePortal.transform.rotation = m_pointedGameObject.transform.rotation;
m_lastPortalMade = 1; // 블루 포탈 생성됨 표시.
}
if (Input.GetKeyDown(KeyCode.Mouse1))
{
m_tempVector = orangePortal.transform.position; // 이전 포탈 위치 저장.
m_tempQuaternion = orangePortal.transform.rotation; // 이전 포탈 각도 저장.
orangePortal.transform.position = new Vector3(portal_X, portal_Y, 0);
orangePortal.transform.rotation = m_pointedGameObject.transform.rotation;
m_lastPortalMade = 2; // 오렌지 포탈 생성됨 표시.
}
// 두 포탈이 겹치는 경우,
if (bluePortal.GetComponent<BoxCollider2D>().bounds.Intersects(orangePortal.GetComponent<BoxCollider2D>().bounds))
{
// 마지막으로 쏜 포탈이 블루 포탈인 경우,
if (m_lastPortalMade == 1)
{
bluePortal.transform.position = m_tempVector;
bluePortal.transform.rotation = m_tempQuaternion;
m_lastPortalMade = 0;
}
// 마지막으로 쏜 포탈이 오렌지 포탈인 경우,
if (m_lastPortalMade == 2)
{
orangePortal.transform.position = m_tempVector;
orangePortal.transform.rotation = m_tempQuaternion;
m_lastPortalMade = 0;
}
}
}
위 함수는 포탈 생성과 관련된 함수입니다.
우선 각 마우스 버튼을 클릭하면서 포탈을 생성하기 이전에 포탈의 이전 위치와 각도를 저장합니다.
(m_tempvector, m_tempQuaternion)
이후 포탈을 생성하고 생성한 포탈 번호를 저장합니다. (m_lastPortalMade -> Blue : 1, Orange : 2)
그 다음 각 포탈의 Collider가 겹치는지 확인합니다.
이는 다음 코드를 사용했습니다.
bluePortal.GetComponent<BoxCollider2D>().bounds.Intersects(orangePortal.GetComponent<BoxCollider2D>().bounds
겹치게 된다면 if문 내에서 마지막으로 생성된 포탈을 번호로 확인하고(m_lastPortalMade) 그 포탈의 이전 위치와 각도로 되돌려놓습니다.
HandlePortalCreation은 Update 함수에서 사용합니다.
void Update()
{
DrawAimLine();
HandlePortalCreation();
}
- 포탈이 벽면 밖으로 넘어가는 경우 처리.
처음에는 벽면 양쪽에 포탈이 벽면 바깥으로 넘어가는 것을 detect하는 Collsion을 추가해서 닿는 경우 포탈이 생성되지 못하게 해볼까 생각했지만 너무 복잡해지는 것 같아서 버렸습니다..
그래서 생각한 것은 아래 그림처럼 Portalable의 크기를 포탈 크기에 맞게 조정해서 줄이는 것이었습니다.
포탈건으로 가리키는 Portalable Collider의 크기를 줄임으로써 포탈이 벽면 밖으로 생성되지 못하도록 하기로 했습니다.
이 부분은 현재로써는 레벨 디자인을 하면서 수작업으로 Collider를 조절해야겠지만 추후에 스크립트를 작성해서 자동으로 조절할 수 있도록 해보겠습니다!
- 포탈 통과 시 플레이어가 트리거로 바뀌면서 생기는 문제 해결.
이전 게시글에서 플레이어가 포탈에서 나오면서 벽에 끼이는 것을 방지하기 위해 플레이어의 Collider를 잠시동안 트리거 형식으로 바꿔줌으로써 해결했었습니다.
다만 이 방법은 한계가 있는데 다음과 같은 경우입니다.
포탈에서 나가면서 플레이어의 트리거가 해제되지 않아 일반 벽 또는 땅을 뚫고 지나가는 현상입니다.
이 현상을 해결하기 위해 플레이어를 포탈의 위치에 스폰시키는 것이 아니라 포탈을 나가는 방향으로 스폰의 위치를 조금 옮기고, 대신 트리거를 토글시키는 코드를 삭제함으로써 해결하였습니다.
위 내용을 구현하기 위해 코드를 다음과 같이 작성했습니다.
if (isTouchingOrange && !m_EnteredPortal) // 오렌지 포탈에 닿은 경우 + 이미 들어간 적이 없는 경우.
{
m_EnteredPortal = true;
player.transform.position = bluePortal.transform.position + desiredDirection.normalized * portalPlayerDistance; // 오렌지 포탈로 위치 변환.
player.GetComponent<Rigidbody2D>().velocity = desiredDirection.normalized * m_playerVelocity.magnitude; // 포탈을 나갈때 속도의 방향 변환.
}
if (isTouchingBlue && !m_EnteredPortal) // 블루 포탈에 닿은 경우 + 이미 들어간 적이 없는 경우.
{
m_EnteredPortal = true;
player.transform.position = orangePortal.transform.position + desiredDirection.normalized * portalPlayerDistance; // 블루 포탈로 위치 변환.
player.GetComponent<Rigidbody2D>().velocity = desiredDirection.normalized * m_playerVelocity.magnitude; // 포탈을 나갈때 속도의 방향 변환.
}
플레이어의 위치를 바꿀 때 각 포탈의 위치 벡터에 플레이어의 속도 단위 벡터 * portalPlayerDistance (float형)을 더해줌으로써 포탈에서부터 위치를 조금 떨어지게 했습니다. 그리고 트리거로 변경하던 코드를 삭제했습니다.
위처럼 플레이어가 트리거로 변하면서 벽을 뚫고 나가는 현상을 해결하였습니다!
추가로 캐릭터의 움직임을 좀더 자연스럽고 UX가 더 좋아질 수 있도록 하기 위해,
Player의 2D collider를 캡슐형으로 바꾸고 캡슐형 아래에 또 다른 트리거 형식의 Circle Collider를 추가해서 캐릭터가 바닥에 닿았는지 확인을 하게 했습니다.
그리고 사용자가 땅에 닿아있는 경우가 아니면(m_isGrounded == false)
사용자가 좌, 우로 움직일 수 없게 해서 떠 있는 동안의 움직임을 강제했습니다.
void Update()
{
if (Input.GetKey(KeyCode.A) && m_isGrounded)
{
Vector3 newVelocity= new Vector3(-1 * playerSpeed, m_rb.velocity.y, 0);
m_rb.velocity = newVelocity;
//transform.Translate(new Vector3(-1 * playerSpeed * Time.deltaTime, 0, 0));
}
if (Input.GetKey(KeyCode.D) && m_isGrounded)
{
Vector3 newVelocity = new Vector3(1 * playerSpeed, m_rb.velocity.y, 0);
m_rb.velocity = newVelocity;
//transform.Translate(new Vector3(1 * playerSpeed * Time.deltaTime, 0, 0));
}
if (Input.GetKey(KeyCode.Space) && m_isGrounded)
{
m_rb.AddForce(transform.up * playerJumpForce);
}
}
이외의 버그 또는 리스크에 대해서는 추가적으로 게임을 구현하면서 수정해보도록 하겠습니다.
이제 mini-portal의 핵심인 포탈과 포탈건을 어느정도 구현하였으니 이를 이용해 레벨 디자인과 Scene을 만들어보도록 하겠습니다!
'Toy Project > mini-portal [Unity2D]' 카테고리의 다른 글
[Unity 2D] Portal 같은 게임 만들기 #8 캐릭터 애니메이션 / 효과음 (0) | 2024.01.09 |
---|---|
[Unity 2D] Portal 같은 게임 만들기 #7 레벨 1 디자인, Scene Controller (0) | 2024.01.09 |
[Unity 2D] Portal 같은 게임 만들기 #5 포탈건 매커니즘 구현하기 2 (포탈 생성하기) (0) | 2024.01.07 |
[Unity 2D] Portal 같은 게임 만들기 #4 포탈건 매커니즘 구현하기 1 (조준선 그리기) (0) | 2024.01.06 |
[Unity 2D] Portal 같은 게임 만들기 #3 포탈 매커니즘 구현하기 2(속도 변환) (0) | 2024.01.05 |