Pink Transparent Star

Unity/개념 공부

[ 내일배움캠프 ] TIL.03 - 카드 선택 횟수 제한하기 _ 해결 방안 생각하기

채유나 2024. 4. 17. 23:58
728x90

 

어느 정도 완료된 카드를 제작하는 중 버그가 발생하였다. 버그인가..? 

다중 선택 가능.GIF

 

기존의 로직으로는 firstCard 와 SecondCard의 idx를 비교하여 맞거나 & 맞지않을 경우 비교를 다 한 후 변수를 Null을 처리하고있다. 

🔶 문제 

1. 애니메이션이 종료 되기전에 FirstCard와 SecondCard가 Null이 된다. 비교하는 카드의 상태가 이상해져서 맞더라도 체크가 안댐

2. 비교를 하기전 Null 처리가 되는 문제와 여러 개의 카드 선택으로 인한 덮어쓰기 문제로 매칭 오류로 체크가 안되는 것을 확인 하였다.

 

[ 해결 생각 ]

팀원들과 의견을 조율하여 카드를 2개만 선택할 수 있도록 하여 매칭 문제를 해결하자. 라고 의견이 나왔다.

 

하지만...

 

여러가지 의견이 나왔음에도 해결이 되지않아 튜터님의 도움으로 힌트를 받게 되었다.

 

 [ 튜터님의 힌트 ]

1, firstCard, secondCard 안에 카드가 다 들어가 있으면 체크가 되면 안됨.
 = secondCard가 null이 아닐 때(카드가 다 들어 있을 때) 클릭 불가능

2. 각 카드(firstCard, secondCard)에서 꺼내주는 타이밍이 달라야 함.
지금은 애니메이션이 다 돌기 전에 null을 처리하는데, 애니메이션이 다 끝나고 나서 null값을 다시 대입해 주는 형식으로 코드 구성

 

🔶 시도한 해결 방법 

OnMouseDown() 사용으로 카드에 Collider을 추가하여 마우스와 카드가 충돌할 때 Open 기준으로 되어있는 상황

 

OnMouseDown() 란? 

마우스가 GUIElement 또는 Collider를 클릭했을 때 발동하는 이벤트.

 

Unity - Scripting API: MonoBehaviour.OnMouseDown()

Success! Thank you for helping us improve the quality of Unity Documentation. Although we cannot accept all submissions, we do read each suggested change from our users and will make updates where applicable. Close

docs.unity3d.com

 

[ 방법 1 ] - 💣

🔸 Board 오브젝트에 Card가 자식 오브젝트로 들어가있는 것을 확인 

🔸 Second Card의 변수가 Null이 아닐 때 Card의 Collider를 enabled = false하면 OnMouseDown()를 사용하지 않아 방지 할 수 있지 않을까? 라는 생각을 하게 됨

 

🔸 GameManager에서 Board안의 Collider의 정보를 List안에 담고 Card에서 foreach를 돌려 활성화 & 비활성화 처리하는 것을 생각

public GameObject board;
public Transform[] allChildren;

private void Start()
{
	audioSource = GetComponent<AudioSource>();
	allChildren = board.GetComponentsInChildren<Transform>();
}

 

오.. 모든 자식 오브젝트가 다 들어가는 문제 발생..! 다른 방법으로 수정!

 

[ 방법2 ] - 💣

1. Card Prafab에 Tag를 붙어 해당하는 오브젝트를 배열에 담고 Card의 Collider를 담기

public GameObject[] allChildren;
public List<Collider2D> colAllChildren = new List<Collider2D>();
    
private void Start()
{
	allChildren = GameObject.FindGameObjectsWithTag("Card");
	foreach (var c in allChildren)
	{
		colAllChildren.Add(c.GetComponent<Collider2D>());
	}
}

GameManager.cs

private void FixedUpdate()
{
	if (GameManager.Instance.secondCard != null)
	{
		foreach(var c in GameManager.Instance.colAllChildren)
		{
			c.enabled = false;
		}
	}
	else
	{
		foreach (var c in GameManager.Instance.colAllChildren)
		{
			c.enabled = true;
		}
}

Card.cs

 

 

Collider이 담겨서 사용이 가능하고 두 개의 카드를 선택 했을 때 다른 카드는 뒤집히지 않는 걸 확인 했다.

하지만..

 

카드를 맞췄을 때 Destory가 된다는 사실을 잊고있었다.. 

 

배열에 담아둔 오브젝트가 사라져 Missing 오류창이 나타났다.

해당 방법에 대해 고민을 하면서 Destory가 아닌 해당 오브젝트를 비활성화 시키는 방법을 생각 해보았지만

1. 다른 팀원들이 작성하신 스크립트 수정

2. 쓸모없는 foreach문을 주기적으로 돌아 확인

 ➥ 해당 코드는 쓸대없는 과정을 거쳐야 하기 때문에 비효율적 이라는 판단을 하여 버렸다.

 

[ 방법 3 ]

튜터님에게 다시 요청을 드려 코드를 코칭 받게되었다. 애니메이션이 종료되는 시점을 찾아 해당하는 카드가 두번째 카드인지 확인하는 것을 과정하는 방법을 사용하라고 말씀하셨다.

 

애니메이션의 종료 시점이 코루틴이 다 끝난 시점이 애니메이션이 끝난 시점이라고 생각했는데 잘못생각을 했었다..

내가 Dotween으로 작성한 코드의 마지막이 애니메이션이 끝나는 시점이라 해당 코드에 내에서 확인을 해야한다고 말씀을 하셔서 수정을 하였다.

 

[ 체크사항 ]

1. ApeendCallback()을 통해 회전한 카드가 두번째 카드

2. 카드의 이미지가 변경되는 시점을 기준으로 frontImg.filipX의가 반대일 경우

 

을 이용하여 해결 할 수 있었다..!

 

  public void Rotate()
  {
      var seq = DOTween.Sequence();
      ...
      seq.AppendCallback(() =>
      {
          if (GameManager.Instance.secondCard == this && !frontImg.flipX)
          {
              GameManager.Instance.firstCard = null;
              GameManager.Instance.secondCard = null;
          }
      });
  }

 

 

✍ 괜히 쉽게 해결 할 수 있는 부분을 더 복잡하게 돌아간 것 같기도 하고 DOTween을 써보고 싶어서 사용해봤으나 좀 더 공부를 해봐야겠다고 생각이 들었다.

728x90