📝23.12.26
짧은 연휴가 끝나고 다시 캠프를 진행하게 되니 더 버거운 느낌이다. 하지만 오늘도 미니 프로젝트 완성을 위해 열심히 공부하였다.
오늘 진행한 것은 크게 두가지이다. 첫번째는 카드 배분 애니메이션을 만든 것이고, 두번째는 1일차에 만들었던 매칭 시 등장하는 텍스트에 애니메이션 효과를 부여한 것이다.
위의 이미지와 같이 하단에서부터 순서대로 카드가 배분되는 듯한 애니메이션을 구현하였다. 카드 오브젝트들은 Instantiate를 통해 생성되는 로직으로 구성되어 있기 때문에, 각각 애니메이션을 구현할 수가 없어 함수로 이동 애니메이션을 구현하였다.
void Start() {
// ...생략
isCardGenerated = false;
generateCard();
}
void Update()
{
if(!isCardGenerated)
{
StartCoroutine(moveCard(0.03f));
}
}
void generateCard()
{
int[] cards = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9 };
//OrderBy 정렬하겠다 Random.Range 랜덤한 순서로 ToArray() 배열로 만든다
cards = cards.OrderBy(item => Random.Range(-1.0f, 1.0f)).ToArray();
for (int i = 0; i < 20; i++)
{
GameObject newCard = Instantiate(card);
//newCard를 cards 밑으로 옮겨줘
newCard.transform.parent = GameObject.Find("cards").transform;
float x = (i / 5) * 1.4f - 2.1f;
float y = (i % 5) * 1.4f - 3.5f;
newCard.transform.position = new Vector3(-2.1f, -3.5f, 0);
newCard.transform.Find("front").GetComponent<SpriteRenderer>().sprite = sprites[cards[i]];
newCard.GetComponent<card>().cardName = sprites[cards[i]].name.Substring(0, 3);
cardList.Add(newCard, new Vector3(x, y, 0));
}
}
IEnumerator moveCard(float waitSeconds)
{
foreach (KeyValuePair<GameObject, Vector3> item in cardList)
{
GameObject card = item.Key;
Vector3 to = item.Value;
card.transform.position = Vector3.Lerp(card.transform.position, to, 0.5f);
//card.transform.rotation = Quaternion.Lerp(Quaternion.Euler(90f, 0, 0), Quaternion.Euler(0, 0, 0), 0.1f);
yield return new WaitForSeconds(waitSeconds);
}
isCardGenerated = true;
}
이 중 애니메이션에 해당하는 부분은 IEnumerator moveCard(float waitSeconds) 인터페이스 부분이다. card 오브젝트의 position을 시간의 흐름에 따라 목표하는 위치로 이동시키면 당연히 원하는 카드 등장 애니메이션을 실행할 수 있겠지만, 나는 단순히 카드가 등장하는 것이 아닌 카드가 배분되는 듯한 부드러운 움직임을 만들고 싶어 더 나은 방법이 없나 고민하였다.
그래서 찾은 것이 바로 Lerp 함수이다.
Vector3.Lerp(기존 위치 벡터, 목표 위치 벡터, 가중치f)
유니티에서 오브젝트의 position 값이 Vector3 값으로 표현되기 때문에 Vector3.Lerp()를 사용하였지만 Lerp 함수는 mathf, Quaternion 등 다양한 자료형에서 사용할 수 있다.
그래서 이 Lerp 함수가 무엇이냐, 하면 바로 선형 보간 함수이다. 그러면 선형 보간은 또 무엇인가? 하는 의문이 들 것이다. 물론 나도 들어서 찾아보았다.
선형 보간법(線型補間法, linear interpolation)은 끝점의 값이 주어졌을 때 그 사이에 위치한 값을 추정하기 위하여 직선 거리에 따라 선형적으로 계산하는 방법이다. 🔗
즉, 목표에 일직선으로 도달하는 것이 아닌 무한하게 목표에 가까워져가는 방식으로 목표에 도달할 수 있게 하는 함수이다.
예를 들어서 (0)에 있는 물체가 (1)이라는 목표에 도달하기 까지의 가중치를 0.8이라고 두면, 1차 이동 시 물체는 (0.8)에 도달할 수 있다. 2차는 (0.8)과 (1)을 기준으로 0.8 가중치를 두면 물체는 (0.96)에 도달한다. 3차에는 (0.96)과 (1)을 기준으로 또 0.8의 가중치를 연산하고 이렇게 하다보면 목표에서 먼 곳에서는 더 빠르게, 목표에 도달했을때는 더 느리게 이동하는 자연스러운 이동을 구현할 수 있게 되는 것이다.
이를 이용해서 애니메이션을 구현한 것이 위의 moveCard() 인터페이스이다. 위의 함수에서는 가중치를 0.1로 두어 오히려 출발지에서 더 천천히, 목표지점에는 더 빠르게 이동하는 애니메이션을 구현한 것이다. 이처럼 Lerp 함수를 통해 한 개씩 같은 속도로 이동하는 물체보다는 훨씬 자연스러운 모양새로 카드 등장 애니메이션이 구현되었다.
두번째는 성공, 실패 여부를 보이는 매칭 텍스트 애니메이션이다.
사실 이건 생소한 부분은 전혀 없었고, 그저 새로운 애니메이션을 matchTxt UI에 추가해주었을 뿐이다. matchTxt 오브젝트의 size의 값을 (0,0,0)에서 (1,1,1)로 커지도록 한 후, 일정 시간은 (1,1,1)이 유지되도록 하였다. 그 후에 다시 (0,0,0)으로 사라지는 방향으로 구현하였더니 이처럼 자연스럽고 확실한 텍스트 애니메이션 효과를 구현할 수 있었다.
이젠 간단한 효과를 주는 애니메이션에 대한 감은 확실히 생긴 것 같다.
오늘 팀 미니 프로젝트에서 작업하고 배운 것은 이것이 전부이다. 이외에 이후는 이전보다 작업을 조금 진행하긴 하였는데, 스파게티처럼 이곳 저곳 들어가있는 스크립트들을 정리하고 오류를 지우는 작업만 해서 딱히 추가할 내용이 없다. 내일은 팀원들과 함께 프로젝트를 마무리 지을 예정이다.