본문 바로가기
디지털노마드

[챗GPT게임개발22] ChatGPT를 활용하여 적 공격 처리 추가하기(2)

by 인텔리노마드라이프 2024. 5. 12.
728x90

안녕하세요. 인텔리원스튜디오(IntelliOneStudio)입니다.

오늘은 ChatGPT를 활용하여 Unity 플랫포머 게임에서 적을 공격하는 기능을 추가해볼께요.

 

참고로 공격 처리는 총 3회에 걸쳐 게시될거에요.

제목 내용
[챗GPT게임개발21] ChatGPT를 활용하여 적 공격 처리 추가하기(1) OnCollisionEnter2D를 활용한 충동 감지 기능 개발
[챗GPT게임개발22] ChatGPT를 활용하여 적 공격 처리 추가하기(2) 애니메이션 이벤트로 콜라이더 위치 조정 
[챗GPT게임개발23] ChatGPT를 활용하여 적 공격 처리 추가하기(3) Physics2D.OverlapCircleAll을 이용한 충돌 감지 

 

[오늘의 목표] 애니메이션 이벤트로 콜라이더 위치 조정 + OnCollisionEnter2D를 활용한 충동 감지 기능 개발 완료
1. 애니메이션 이벤트로 콜라이더 위치 조정
2. OnCollisionEnter2D 이벤트 활용

3. 실행 결과 살펴 보기 

 

 ChatGPT 답변 내용 중 제가 별도로 표시한 파란색 내용을 기준으로 읽으시면 좀 더 이해가 쉽게 될거예요.

애니메이션에서 콜라이더 위치 조정이 가능하지 않을까?

아래 글에서 충돌 이벤트를 활용하는데 실패를 했어요. 

[챗GPT게임개발21] ChatGPT를 활용하여 적 공격 처리 추가하기(1)

 

그런데 궁금했어요. 

애니메이션 수정을 통해서 콜라이더(Collider)의 위치 조정이 가능하지 않을까

 

콜라이더 위치 조정만 되면 적과 충돌이 가능해지고,

지난 시간이 만든 OnCollisionEnter2D 스크립트를 사용할 수 있어요. 

 

챗GPT에게 물어봤어요.

[질문] 안녕 ChatGPT, 애니메이션 수정을 통해서는 콜라이더의 위치 조정이 가능하니? 

[답변]

Unity에서 애니메이션 클립을 사용하여 콜라이더의 위치를 조정하는 것은 완전히 가능하고 때로는 바람직한 방법입니다. 애니메이션 클립 내에서 애니메이션 이벤트를 사용하여 특정 시점에서 콜라이더의 위치를 조정할 수 있습니다. 이 방법은 특히 시각적인 애니메이션과 물리적 상호작용이 밀접하게 연결되어 있을 때 유용합니다.

애니메이션 이벤트로 콜라이더 위치 조정하기

  1. 애니메이션 클립 열기: Unity 에디터에서 플레이어 캐릭터의 공격 애니메이션 클립을 엽니다.
  2. 애니메이션 이벤트 추가: 애니메이션 타임라인에 적절한 위치에 마우스 오른쪽 버튼을 클릭하고, "Add Event"를 선택합니다. 이 이벤트는 공격이 실제로 발동되는 순간에 위치해야 합니다.
  3. 이벤트 함수 지정: 이벤트에 함수를 지정합니다. 이 함수는 PlayerController 스크립트 내에 정의되어야 하며, 콜라이더의 위치를 업데이트하는 로직을 포함합니다.

스크립트에 콜라이더 위치 업데이트 함수 추가

public void UpdateColliderForAnimation()
{
    float offsetDistance = 0.5f; // 적절한 오프셋 거리 설정
    if (collider2d != null)
    {
        collider2d.offset = new Vector2(spriteRenderer.flipX ? -offsetDistance : offsetDistance, collider2d.offset.y);
    }
}

 

애니메이션 이벤트 함수 연결

애니메이션 이벤트 윈도우에서 UpdateColliderForAnimation 함수를 선택합니다. 이렇게 설정하면, 애니메이션 클립이 해당 프레임에 도달했을 때 자동으로 콜라이더의 위치를 업데이트합니다.

추가적인 고려사항

  • 애니메이션 이벤트의 정밀성: 애니메이션 이벤트는 매우 정확하게 특정 프레임에 함수를 호출할 수 있습니다. 이를 이용해 공격 애니메이션의 특정 동작에서 콜라이더의 위치를 조정해야 할 때 정확히 조정할 수 있습니다.
  • 테스트와 조정: 애니메이션 이벤트를 사용한 후에는 반드시 게임을 실행하여 콜라이더의 위치가 올바르게 조정되는지 테스트해야 합니다. 필요에 따라 애니메이션 클립 내의 이벤트 위치를 조정하거나, 콜라이더 오프셋 값을 미세 조정할 수 있습니다.

이 방법을 사용하면 애니메이션과 게임 로직 간의 일관성을 유지하면서, 시각적인 부분과 물리적인 상호작용을 정확히 조율할 수 있습니다. 이는 플레이어의 직관적인 경험을 향상시키고, 게임의 전반적인 품질을 높이는 데 기여합니다.

 

애니메이션 이벤트 생성하기

챗GPT가 알려준대로 애니메이션 이벤트를 만들고 함수를 연결했어요.

물론 이벤트 함수도 PlayerController 스크립트에 추가했어요.

[애니메이션 이벤트 생성하기]

 

변경사항을 저장하고 실행모드에서 시험을 했어요.

[플레이어 이동 방향에 따라 콜라이더 이동]

 

플레이어 방향에 따라 콜라이더가 잘 이동했어요.

하지만 공격 애니메이션이 끝이나면 다시 콜라이더가 원래 자리로 돌아오지 않았어요. 

애니메이션 종료 시 콜라이더는 원래 자리로 돌아와야해

콜라이더가 원래 자리로 돌아오는 방법을 물었어요.

[질문] 안녕 ChatGPT, 아래 콜라이더 업데이트를 실행하고 애니메이션 종료 시에는 원래 콜라이더 위치로 다시 돌아와야해. 원래 위치로 돌아오는 함수를 추가로 만들어줘
public void UpdateColliderForAnimation()
{
    float offsetDistance = 0.5f; // 적절한 오프셋 거리 설정
    if (collider2d != null)
    {
        collider2d.offset = new Vector2(spriteRenderer.flipX ? -offsetDistance : offsetDistance, collider2d.offset.y);
    }
}

[답변]

공격 애니메이션이 끝날 때 콜라이더를 원래 위치로 복원하는 함수를 추가하는 것은 게임의 물리적 일관성을 유지하는 데 중요합니다. 여기에서는 UpdateColliderForAnimation 함수와 함께 콜라이더의 위치를 초기화하는 ResetColliderPosition 함수를 구현해 보겠습니다.

콜라이더 위치 초기화 함수

이 함수는 콜라이더의 offset을 초기 값으로 설정하는 역할을 합니다. 이 초기 값은 캐릭터의 디폴트 물리적 크기와 위치에 기반하여 정의되어야 합니다.

public void ResetColliderPosition()
{
    if (collider2d != null)
    {
        // 여기에서는 collider2d.offset.y를 유지하고 x 값을 0으로 설정합니다.
        collider2d.offset = new Vector2(0, collider2d.offset.y);
    }
}

 

애니메이션 클립에 이벤트 추가하기

  1. 애니메이션 클립 열기: Unity 에디터에서 공격 애니메이션 클립을 열고 애니메이션이 끝나는 지점을 찾습니다.
  2. 애니메이션 이벤트 추가: 애니메이션의 마지막 프레임에 마우스 오른쪽 버튼을 클릭하고 "Add Event"를 선택합니다.
  3. 이벤트 함수 지정: 이벤트에 ResetColliderPosition 함수를 지정합니다. 이렇게 하면 애니메이션이 끝날 때 자동으로 콜라이더의 위치를 초기화합니다.

사용 사례

  • 공격 애니메이션 실행: 공격 애니메이션이 시작될 때 UpdateColliderForAnimation 함수를 호출하여 콜라이더의 위치를 조정합니다.
  • 애니메이션 종료: 공격 애니메이션이 끝나는 시점에 ResetColliderPosition 함수를 호출하여 콜라이더를 원래 위치로 복원합니다.

이 방식은 플레이어 캐릭터의 물리적 상태가 애니메이션에 따라 동적으로 변화하면서도 게임의 물리적 일관성과 정확성을 유지할 수 있도록 합니다. 게임을 테스트할 때는 이러한 변화가 예상대로 작동하는지 확인해야 하며, 필요에 따라 offset 값의 조정이 필요할 수 있습니다.

 

UpdateColliderForAnimation를 추가한 프레임보다 한 프레임 뒤에 ResetColliderPosition함수를 호출하는 이벤트를 만들었어요.

 

변경사항을 저장하고 실행모드에서 시험을 했어요.

원하는 대로 콜라이더가 이동해요. 

[콜라이더 이동]

공격 준비를 완료했어요.

이제 공격 애니메이션이 동작할 때 플레이어의 콜라이더가 이동되요. 

플레이어의 콜라이더가 적의 콜라이더와 부딪히면 되요. 

그럼 아래 스크립트가 적에게 피해를 주고 적을 없애는 역할을 해요.

using Platformer.Core;
using Platformer.Mechanics;
using Platformer.Model;
using UnityEngine;
using static Platformer.Core.Simulation;

namespace Platformer.Gameplay
{
    /// <summary>
    /// Fired when a Player collides with an Enemy.
    /// </summary>
    /// <typeparam name="EnemyCollision"></typeparam>
    public class PlayerEnemyCollision : Simulation.Event<PlayerEnemyCollision>
    {
        public EnemyController enemy;
        public PlayerController player;

        PlatformerModel model = Simulation.GetModel<PlatformerModel>();

        public override void Execute()
        {
            Debug.Log("Collision detected between player and enemy.");
            Debug.Log("Current Player Attack State: " + player.attackState); // player.attackState 값을 항상 출력

            if (player.attackState == PlayerController.AttackState.Idle)
            {
                Debug.Log("Player is attacking. Handling attack collision.");
                HandleAttackCollision();
            }
            else
            {
                Debug.Log("Handling regular collision based on player position.");
                HandleRegularCollision();
            }
        }

        void HandleAttackCollision()
        {
            var enemyHealth = enemy.GetComponent<Health>();
            if (enemyHealth != null)
            {
                enemyHealth.Decrement();
                Debug.Log("Enemy health decremented by player attack.");
                
                if (!enemyHealth.IsAlive)
                {
                    Debug.Log("Enemy has died from player attack.");
                    Schedule<EnemyDeath>().enemy = enemy;
                    // player.Bounce(2);
                }
                else
                {
                    Debug.Log("Enemy hurt but still alive; player bounces higher.");
                    // player.Bounce(7);
                }
            }
            else
            {
                Debug.Log("No Health component found on enemy during attack.");
                Schedule<EnemyDeath>().enemy = enemy;
                // player.Bounce(2);
            }
        }

        void HandleRegularCollision()
        {
            var willHurtEnemy = player.Bounds.center.y >= enemy.Bounds.max.y;

            if (willHurtEnemy)
            {
                Debug.Log("Player is positioned to hurt the enemy.");
                var enemyHealth = enemy.GetComponent<Health>();
                if (enemyHealth != null)
                {
                    enemyHealth.Decrement();
                    Debug.Log("Enemy health decremented by player jump attack.");

                    if (!enemyHealth.IsAlive)
                    {
                        Debug.Log("Enemy has died from player jump attack.");
                        Schedule<EnemyDeath>().enemy = enemy;
                        player.Bounce(2);
                    }
                    else
                    {
                        Debug.Log("Enemy hurt by jump attack but still alive.");
                        player.Bounce(7);
                    }
                }
                else
                {
                    Debug.Log("No Health component found on enemy for jump attack.");
                    Schedule<EnemyDeath>().enemy = enemy;
                    player.Bounce(2);
                }
            }
            else
            {
                Debug.Log("Player will be hurt and possibly die due to collision.");
                Schedule<PlayerDeath>();
            }
        }
    }
}

 

이제 적을 공격해봐요. 

플레이어를 적과 가까운 위치에 두고 공격을 해볼께요.

 

이번에는 오른쪽에서 적을 공격해볼께요.

 

모두 잘 되네요. 

 

오늘은 ChatGPT를 활용하여 Unity 플랫포머 게임에서 적을 공격하는 기능을 만들기 위해

애니메이션 이벤트로 콜라이더 위치 조정하는 방법을 살펴봤어요.

 

다음 시간에는 Physics2D.OverlapCircleAll을 이용한 충돌 감지를 알아볼께요. 

[농구하는 인텔리원스튜디오 개발자. 인텔리노마드라이프와 함께 행복하세요 from IntelliOneStudio ]

 

지금까지,

언제나 성장하는 인텔리원스튜디오(IntelliOneStudio)입니다.

감사합니다.

728x90