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

[챗GPT게임개발29] GPT-4, GPT-4o 활용해서 산탄 효과(Particle System)를 플레이어에 적용하기

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

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

오늘은 GPT-4, GPT-4o 활용해서 산탄 효과(Particle System)를 플레이어에 적용해볼께요.

[오늘의 목표] GPT-4, GPT-4o 활용해서 산탄 효과(Particle System)를 플레이어에 적용
1. 스크립트 만들기
2. 실행 결과 살펴 보기 

 

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

 

스크립트를 먼저 만들어볼께요.

지난 시간에 산탄효과 파티클을 만들어서 플레이어의 자식으로 추가했어요.

2024.05.18 - [디지털노마드] - [챗GPT게임개발28] GPT-4, GPT-4o 활용 Particle System을 사용해서 산탄 효과 구현하기

 

[챗GPT게임개발28] GPT-4, GPT-4o 활용 Particle System을 사용해서 산탄 효과 구현하기

안녕하세요. 인텔리원스튜디오(IntelliOneStudio)입니다.오늘은 GPT-4, GPT-4o 활용해서 산탄총처럼 여러 발의 총알이 퍼져 나가게 하는 파티클 시스템을 만들어봐요. [오늘의 목표] 산탄총처럼 여러 발

intellinomadlife.tistory.com

 

그리고 아래 글에서 PlayerAttack 이벤트도 만들었어요.

2024.05.17 - [디지털노마드] - [챗GPT게임개발25] GPT-4, GPT-4o로 게임 이벤트 시스템 최적화하기

 

[챗GPT게임개발25] GPT-4, GPT-4o로 게임 이벤트 시스템 최적화하기

안녕하세요. 인텔리원스튜디오(IntelliOneStudio)입니다.오늘은 ChatGPT를 활용하여 공격 관련 로직을 이벤트 기반으로 변경해볼까해요. 코드 개선: 공격 로직을 이벤트 기반으로 처리해봐요.기존에

intellinomadlife.tistory.com

 

이제 위 글을 참고해서,

다음과 같이 플레이어가 공격할 때 파티클이 실행될 수 있게 만들어볼께요.

[질문] 안녕 ChatGPT, 아래 두 소스를 참고해서 플레이어가 공격할 때 파티클 및 적에게 피해를 주는 기능들이 추가해줘. 그리고 플레이어의 방향에 따라 파티클의 방향이 변경될 수 있게 해줘
using static Platformer.Core.Simulation;
using Platformer.Core;
using Platformer.Mechanics;
using UnityEngine;

namespace Platformer.Gameplay
{
    /// <summary>
    /// Fired when the player initiates an attack.
    /// </summary>
    public class PlayerAttack : Simulation.Event<PlayerAttack>
    {
        public PlayerController player;

        public override void Execute()
        {
            if (player.jumpState == PlayerController.JumpState.InFlight || 
                player.jumpState == PlayerController.JumpState.Jumping || 
                player.jumpState == PlayerController.JumpState.WallJumping)
            {
                // 점프 중인 경우
                player.animator.SetTrigger("jumpAttack");
            }
            else
            {
                // 점프 중이 아닌 경우
                player.animator.SetTrigger("attack");
            }
            CheckHit();
            player.attackState = PlayerController.AttackState.Idle;
        }

        // 타격 범위를 설정하는 메서드
        private Vector2 GetAttackCenter()
        {
            return new Vector2(player.transform.position.x + (player.spriteRenderer.flipX ? -player.attackRange : player.attackRange), player.transform.position.y);
        }

        // 타격된 적을 처리하는 메서드
        private void HandleHit(Collider2D hit)
        {
            if (hit.gameObject.CompareTag("Enemy"))
            {
                Debug.Log("적 타격 감지됨!");
                var enemy = hit.GetComponent<EnemyController>();
                if (enemy != null)
                {
                    HandleEnemyHit(enemy);
                }
                else
                {
                    Debug.Log("타격된 객체에 적 컴포넌트가 없습니다.");
                }
            }
        }

        // 적의 체력을 감소시키고, 적이 죽었는지 여부를 확인하는 메서드
        private void HandleEnemyHit(EnemyController enemy)
        {
            var enemyHealth = enemy.GetComponent<Health>();
            if (enemyHealth != null)
            {
                enemyHealth.Decrement();
                if (!enemyHealth.IsAlive)
                {
                    Debug.Log("적이 처치되었습니다.");
                    Schedule<EnemyDeath>().enemy = enemy;
                }
                else
                {
                    Debug.Log("적은 타격을 받았으나 아직 살아있습니다.");
                }
            }
            else
            {
                Schedule<EnemyDeath>().enemy = enemy;
            }
        }

        // 타격 확인 메서드
        private void CheckHit()
        {
            Vector2 center = GetAttackCenter();
            Collider2D[] hits = Physics2D.OverlapCircleAll(center, player.attackRange, player.enemyLayer);
            foreach (var hit in hits)
            {
                HandleHit(hit);
            }
        }
    }
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Reflection;

[RequireComponent(typeof(ParticleSystem))]
public class EmitParticlesOnLand : MonoBehaviour
{

    public bool emitOnLand = true;
    public bool emitOnEnemyDeath = true;

#if UNITY_TEMPLATE_PLATFORMER

    ParticleSystem p;

    void Start()
    {
        p = GetComponent<ParticleSystem>();

        if (emitOnLand) {
            Platformer.Gameplay.PlayerLanded.OnExecute += PlayerLanded_OnExecute;
            void PlayerLanded_OnExecute(Platformer.Gameplay.PlayerLanded obj) {
                p.Play();
            }
        }

        if (emitOnEnemyDeath) {
            Platformer.Gameplay.EnemyDeath.OnExecute += EnemyDeath_OnExecute;
            void EnemyDeath_OnExecute(Platformer.Gameplay.EnemyDeath obj) {
                p.Play();
            }
        }

    }

#endif

}

[답변]

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Platformer.Mechanics;
using Platformer.Gameplay;
using static Platformer.Core.Simulation;

[RequireComponent(typeof(ParticleSystem))]
public class EmitParticlesOnLand : MonoBehaviour
{
    public bool emitOnLand = true;
    public bool emitOnEnemyDeath = true;
    public bool emitOnAttack = true; // 공격 시 파티클 재생 옵션 추가

    ParticleSystem p;
    PlayerController player;

    void Start()
    {
        p = GetComponent<ParticleSystem>();
        player = GetComponentInParent<PlayerController>(); // 부모 객체에서 PlayerController를 찾음

        if (emitOnLand)
        {
            PlayerLanded.OnExecute += PlayerLanded_OnExecute;
            void PlayerLanded_OnExecute(PlayerLanded obj)
            {
                p.Play();
            }
        }

        if (emitOnEnemyDeath)
        {
            EnemyDeath.OnExecute += EnemyDeath_OnExecute;
            void EnemyDeath_OnExecute(EnemyDeath obj)
            {
                p.Play();
            }
        }

        if (emitOnAttack)
        {
            PlayerAttack.OnExecute += PlayerAttack_OnExecute;
            void PlayerAttack_OnExecute(PlayerAttack obj)
            {
                AdjustParticleDirection();
                p.Play();
            }
        }
    }

    void AdjustParticleDirection()
    {
        var shape = p.shape;
        var velocityOverLifetime = p.velocityOverLifetime;

        if (player.spriteRenderer.flipX)
        {
            // Set the particle system to emit to the left
            shape.rotation = new Vector3(0, 270, 0);
            // velocityOverLifetime.x = new ParticleSystem.MinMaxCurve(-20.0f); // Adjust the speed as needed
            Debug.Log("Particle direction adjusted to left.");
        }
        else
        {
            // Set the particle system to emit to the right
            shape.rotation = new Vector3(0, 90, 0);
            // velocityOverLifetime.x = new ParticleSystem.MinMaxCurve(20.0f); // Adjust the speed as needed
            Debug.Log("Particle direction adjusted to right.");
        }
    }

    void OnParticleCollision(GameObject other)
    {
        Debug.Log("Particle collided with: " + other.name);

        if (other.CompareTag("Enemy") || other.CompareTag("Player"))
        {
            var enemy = other.GetComponent<EnemyController>();
            if (enemy != null)
            {
                HandleEnemyHit(enemy);
            }
        }
    }

    private void HandleEnemyHit(EnemyController enemy)
    {
        var enemyHealth = enemy.GetComponent<Health>();
        if (enemyHealth != null)
        {
            enemyHealth.Decrement();
            if (!enemyHealth.IsAlive)
            {
                Debug.Log("적이 처치되었습니다.");
                Schedule<EnemyDeath>().enemy = enemy;
            }
            else
            {
                Debug.Log("적은 타격을 받았으나 아직 살아있습니다.");
            }
        }
        else
        {
            Schedule<EnemyDeath>().enemy = enemy;
        }
    }
}

 

 

파티클 실행, 파티클 충돌 시 처리 그리고 플레이어 방향에 따라 파티클의 방향이 변하는 기능도 다 만들어졌어요.

정말 모두가 개발자가 되는 세상이 너무 빨리 다가오는 것 같아요.

파티클 시스템에 충돌 속성 추가 

산탄총 파티클에 Collison 을 추가해요.

 

중요한 부분은 Type은 World, Mode는 2D 그리고 충돌되는 레이어 설정이예요. 

충돌되는 레이어 지정을 하지 않을 경우 플레이어와 충돌을 하게 되어 원하지 않는 결과가 생길 수 있어요.

[파티클 시스템에 충돌 추가]

이제 실행해볼께요

스크립트를 적용하고 플레이 모드에서 실행을 해요.

[스크립트 적용]

 

아래 영상과 같이 원하는 산탄총이 만들어졌고 산탄총으로 적에게 피해를 줄 수 있어요.

 

오늘은 GPT-4, GPT-4o 활용해서 산탄 효과(Particle System)를 플레이어에 적용해봤어요.

[인텔리노마드라이프와 함께 행복하세요 : 인텔리원스튜디오]

 

지금까지,

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

감사합니다.

728x90