Study/Unity

[미니 프로젝트] 03. 카드 미리보기, 애니메이션 기능

죈트 2025. 1. 22. 17:53

카드 미리보기 기능

  • 게임 카드로 나타나는 여러 이미지를 미리볼수 있도록 구성.
  • 비교적 간단한 리니어한 애니메이션이지만, 절차적 애니메이션을 해보고싶어,
    유니티 내에서 조작 가능하도록 옵션을 만들었다.
  • 카드가 일정 범위를 넘어가면, 그 카드 기준 전 카드를 찾아 upVec과 Distance를 통해 새로운 위치로 전환

화살표 방향으로 지정 속도만큼 이동


Frame이 어긋나서 간격이 벌어지는 상황이 있었지만,
김주안 튜터님과의 이야기를 통해 원인을 파악할 수 있었고,
위치, 거리, 방향을 명확히 할수 있었다.

애니메이션 수정 기능

이후 3D로 넘어가 본업과 가까워질 때,
절차적 애니메이션(procedural animation)을 구현해보기 위해
미리 유니티와 친해지는 단계에서 가볍게 구현해 보았다.

  • Start Position Game: 게임 카드가 시작될 위치
  • Start Position Member: 팀원 카드가 시작될 위치
  • Up Vec: 게임 카드 기준으로 다음 카드가 생성될 위치 (팀원카드는 반대방향으로 생성)
  • Speed: 카드가 움직이는 속도
  • Card Distance: 카드와 카드사이의 거리
  • Opacity: 카드의 투명도
  • Card Rotation: 카드의 z축 회전


CardBoard 구성

  • start, update 함수는 최대한 간결하게
void Start()
{
    CardInit();
    CreateCard(gameArr, gArr, StartPosition_game, Signed(true));
    CreateCard(memberArr, mArr, StartPosition_member, Signed(false));
}

void Update()
{
    upVec.Normalize();
    MoveCard(gArr, Signed(false));
    MoveCard(mArr, Signed(true));

    RepositionCard(gArr, StartPosition_game, Signed(true));
    RepositionCard(mArr, StartPosition_member, Signed(false));
}

 

  • 카드 입력과 생성함수
// 카드 입력
private void CardInit()
{
    gameArr[0] = game0;
    gameArr[1] = game1;
    gameArr[2] = game2;
    gameArr[3] = game3;
    memberArr[0] = member0;
    memberArr[1] = member1;
    memberArr[2] = member2;
    memberArr[3] = member3;
}

// 카드 생성 함수
private void CreateCard(GameObject[] inArr, GameObject[] outArr, Vector2 startPos, float signed)
{
    upVec.Normalize();
    for (int i = 0; i < RepeatCount; i++)
    {
        int idx = i % inArr.Length;
        GameObject go = Instantiate(inArr[idx], this.transform);

        // 카드 위치 지정
        float x = signed * i * CardDistance * upVec.x + startPos.x;
        float y = signed * i * CardDistance * upVec.y + startPos.y;

        // 카드 transform 설정
        Vector3 cardPosition = new Vector3(x, y, 0);
        go.transform.position = cardPosition;
        go.transform.rotation = Quaternion.Euler(0, 0, CardRotation);

        // 투명도 설정
        SetOpacity(go, Opacity);

        // update를 위해 반환
        outArr[i] = go;
    }
}

 

  • 카드 움직이는 함수
// 카드 움직이는 함수
private void MoveCard(GameObject[] inArr, float signed)
{
    for (int i = 0; i < inArr.Length; i++)
    {
        inArr[i].transform.position += signed * Speed * upVec * Time.deltaTime;
        inArr[i].transform.rotation = Quaternion.Euler(0, 0, CardRotation);
    }
}

 

  • Signed값 구하는 함수
// 숫자 부호를 bool 값으로 입력 받아, float값으로 출력
// true: 양수, false: 음수
float Signed(bool b)
{
    return b ? 1f : -1f;
}

 

  • 투명도 설정
// 투명도 설정
void SetOpacity(GameObject go, float opacity)
{
    SpriteRenderer spriteRender = go.GetComponent<SpriteRenderer>();
    Color color = spriteRender.color;
    color.a = opacity;
    spriteRender.color = color;
}

 

  • 카드 위치 재조정
// 위치 재조정
void RepositionCard(GameObject[] inArr, Vector2 startPos, float signed)
{
    for (int i = 0; i < RepeatCount; i++)
    {
        int num = i - 1;
        if (i == 0)
            num = inArr.Length - 1;

        Vector3 position = inArr[i].transform.position;

        // 게임 카드의 재조정 조건             || 팀원 카드의 재조정 조건
        if ((position.x < -3.5f && signed > 0) || (position.x > 3.5f && signed < 0))
        {
            float x = signed * CardDistance * upVec.x + inArr[num].transform.position.x;
            float y = signed * CardDistance * upVec.y + inArr[num].transform.position.y;
            Vector3 newPos = new Vector3(x, y, 0);
            inArr[i].transform.position = newPos;
        }
    }
}