본문 바로가기
AI/AI활용

[ChatGPT][Unity] 간단한 게임 만들어보기 (2)

by OhEasy 2023. 4. 5.
728x90
 

[ChatGPT][Unity] 간단한 게임 만들어보기 (1)

[ChatGPT][연습] ChatGPT만 가지고 Unity 게임 만들어 보기 일단 엄청 오래걸려 만들어본 결과물 배배배뱀 - Google Play 앱 배배배뱀! 로그라이크 던전에서 몬스터를 처치하라! play.google.com 배배배뱀은 요

525easy.tistory.com

이전 글에서 

1. 프로젝트 설정:
	Unity를 열고 새 2D 프로젝트를 만듭니다.
	새 장면을 만들고 여기에 카메라를 추가합니다.
	카메라 위치를 (0, 0, -10)으로 설정하여 장면의 중앙에 오도록 합니다.
2. 플레이어 만들기: 
	플레이어용 스프라이트를 추가하고 여기에 Rigidbody2D 구성 요소를 추가합니다. 
	중력 스케일을 0으로 설정하고 스크립트를 추가하여 플레이어의 움직임을 제어합니다. 
	화살표 키 또는 WASD 키를 사용하여 플레이어를 왼쪽, 오른쪽, 위, 아래로 이동할 수 있습니다.
3. 적 추가: 
	적의 스프라이트를 만들고 여기에 Rigidbody2D 구성 요소를 추가합니다. 
	중력 스케일을 0으로 설정하고 스크립트를 추가하여 적의 움직임을 제어합니다. 
	무작위 이동을 사용하거나 적이 따라갈 경로를 설정할 수 있습니다. 
	스폰 스크립트를 사용하여 일정한 간격으로 적을 인스턴스화합니다.
---------------------------------- 완료 -----------------------------------------------------
4. 사격 추가: 
	플레이어의 총알에 대한 스프라이트를 만들고 총알의 움직임을 제어하는 스크립트를 추가합니다. 
	플레이어가 스페이스바 키를 누르면 총알을 인스턴스화합니다. 
	총알과 적의 충돌을 확인하고 충돌하면 적을 파괴하는 스크립트를 추가하십시오.
5. 점수 추가: 
	게임에 점수 카운터를 추가하고 플레이어가 적을 파괴하면 증가합니다. 
	텍스트 구성 요소를 사용하여 화면에 점수를 표시합니다.
6. 파워업 추가: 
	파워업 스프라이트를 만들고 스크립트를 추가하여 동작을 제어합니다. 
	생성 스크립트를 사용하여 임의의 간격으로 파워업을 인스턴스화합니다. 
	플레이어가 파워업을 수집하면 추가 포인트, 추가 생명 또는 강화된 무기를 제공할 수 있습니다.
7. 오디오 추가: 
	게임에 음향 효과와 배경 음악을 추가하여 플레이어의 경험을 향상시킵니다

3번까지 구현이 되었다.

ChatGPT가 알려준 대로 진행을 하되,
아이디어가 떠오르면 추가하는 방식으로 진행하기로 했다.


4번부터 이어서 진행을 한다.
4번의 과정을 나누면
1. 총알을 만든다.
2. 총알을 이동 시키는 스크립트를 만든다.
3. 기존 플레이어 스크립트에 총알을 만드는 코드를 추가한다.
4. 총알 스크립트에 적과 충돌하면 파괴되는 코드를 추가한다.
이다.

우선 3번부터 진행한다.

번역된 내용이라 말이 이상하다.

플레이어에게 달려있는 PlayerMovement 스크립트를 첨부하고
코드를 추가하는 방식으로 진행한다.

그러다보면 답변 길이 때문인지

부분만 보내준다.

특정 함수 또는 변경되는 부분만 보내준다.
그냥 코드 카피로 하고 싶을 경우
전체 코드를 보내달라 하면 보내준다.

다음은 총알을 만드는 방법인데

설명이 다 나온다.

업데이트만 알려줬기 때문에
전체 코드를 알려달라 해본다.

원하는대로 나왔다.

우선 총알의 움직임을 제어하는 스크립트를 받았다.

적과 충돌하면 파괴되는 부분을 추가해달라 한다.

후번역이라 말이 이상함

이러면 아래와 같은 코드를 알려준다.

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

public class BulletMovement : MonoBehaviour
{
    public float speed = 10f; // Speed of the bullet
    public float lifeTime = 2f; // Time before the bullet disappears

    void Start()
    {
        Destroy(gameObject, lifeTime); // Destroy the bullet after a certain amount of time
    }

    void Update()
    {
        transform.Translate(Vector2.right * speed * Time.deltaTime); // Move the bullet forward
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Enemy"))
        {
            Destroy(other.gameObject); // Destroy the enemy
            Destroy(gameObject); // Destroy the bullet
        }
    }
}

일단 위 코드는
Rgidbody 2D만 추가했기 때문에
동작하지 않는다.

위 코드가 동작하기 위해서는
Collider 컴포넌트도 추가해야 한다.

동작하지 않는다 물어보았더니

함수는 트리거에서 콜리전엔터로 수정해주었다.

함수는 트리거에서 콜리전엔터로 수정해주었다.
하지만
추가적으로 콜라이더를 설정하라는 말도 없고,
Tag가 설정되었는지 확인하라는 말도 없다.

=> ChatGPT가 빼놓는 정보들이 너무 많다.

어쨌든 여전히 관통된다 물어보니
콜라이더 또는 태그를 추가하거나,
Enemy 스크립트를 변경하라고 한다.

기존과 다른 클래스다.

기존과 다른 클래스를 보내주어서
기존 클래스에 추가해달라고 한다.

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

public class EnemyMovement : MonoBehaviour
{
    public float speed = 3f;
    public int health = 3;

    private Transform player;

    void Start()
    {
        player = GameObject.FindGameObjectWithTag("Player").transform;
    }

    void Update()
    {
        transform.position = Vector3.MoveTowards(transform.position, player.position, speed * Time.deltaTime);
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Bullet"))
        {
            BulletMovement bullet = other.GetComponent<BulletMovement>();
            if (bullet != null)
            {
                health -= bullet.damage;
                if (health <= 0)
                {
                    Destroy(gameObject);
                }
            }
            Destroy(other.gameObject);
        }
    }
}

위 코드를 넣고 그냥 돌리면 당연히 에러가 나올 것이다.
왜냐면 총알에 damage라는 공용 변수가 없기 때문

이런식으로 물어본다.

 그러면

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

public class BulletMovement : MonoBehaviour
{
    public float speed = 10f; // Speed of the bullet
    public float lifeTime = 2f; // Time before the bullet disappears
    public int damage = 1; // Amount of damage the bullet does to enemies

    void Start()
    {
        Destroy(gameObject, lifeTime); // Destroy the bullet after a certain amount of time
    }

    void Update()
    {
        transform.Translate(Vector2.right * speed * Time.deltaTime); // Move the bullet forward
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Enemy"))
        {
            EnemyMovement enemy = other.GetComponent<EnemyMovement>();
            if (enemy != null)
            {
                enemy.health -= damage; // Decrease the enemy's health by the bullet's damage value
                if (enemy.health <= 0)
                {
                    Destroy(other.gameObject); // Destroy the enemy
                }
            }
            Destroy(gameObject); // Destroy the bullet
        }
    }
}

이렇게 damage가 public으로 잘 들어가져있다.

여기서 좀 문제인게
총알과 적이 충돌 시
적 체력 감소를 총알과 적 둘이 한다는 것이다.
=> 데미지가 2배로 들어갈 것이다.

일단 총알에 있는 데미지 처리 부분은 지워주고
적 스크립트에 달린
OnTriggerEnter 함수를 OnCollisionEnter로 바꿔 주었다.

뭔가 한방에 되는게 없다.

이런건 잘 해준다.

여기까지로는 4번까지 완료가 된다.
하지만
총알이 오른쪽으로만 이동한다.

매직 서바이벌이나 뱀서류를 보면 가장 가까운 적을 타겟으로 한다.
그렇게 바꾸기 위해서는 다음과 같은 기능이 필요하다.

1. 플레이어가 플레이어와 가장 가까운 적을 알고 있어야 한다.
2. 총알은 지정된 Position(targetPos) 방향으로 이동해야 한다.
3. 플레이어가 총알을 생성할 때 총알의 targetPos를 전달해야 한다.

우선 1. 플레이어가 가장 가까운 적을 알기위한 코드를 요청한다.

빠르게 알려준다.

2. 총알이 캐릭터가 전달해준 위치 방향으로 이동하는 부분을 요청한다.

한번에 PlayerMovement와 BulletMovement를 준다.

여기서 좀 오래 걸리는 것이
자기가 알려준 코드가 갱신이 안된 것인지
예전 코드 기반으로 준다.

추가 질문 1
추가 질문 2

위와 같은 추가 질문을 했다.
여기까지 보면
사람이 쓰는게 빠르지 않을까 싶기도 하다.

어쨌든 수정된 코드가 왔다.

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

public class PlayerMovement : MonoBehaviour
{
    public GameObject bulletPrefab;

    public float speed = 5f;

    public List<Transform> enemies = new List<Transform>();

    void Update()
    {
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");

        transform.position += new Vector3(horizontal, vertical, 0) * speed * Time.deltaTime;

        if (Input.GetKeyDown(KeyCode.Space))
        {
            // Find the nearest enemy
            Transform nearestEnemy = null;
            float minDistance = Mathf.Infinity;
            foreach (Transform enemy in enemies)
            {
                float distance = Vector3.Distance(transform.position, enemy.position);
                if (distance < minDistance)
                {
                    minDistance = distance;
                    nearestEnemy = enemy;
                }
            }

            // Fire bullet towards nearest enemy
            if (nearestEnemy != null)
            {
                Vector2 direction = (nearestEnemy.position - transform.position).normalized;
                GameObject bullet = Instantiate(bulletPrefab, transform.position, Quaternion.identity);
                bullet.GetComponent<BulletMovement>().SetDirection(direction);
            }
        }
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Enemy"))
        {
            enemies.Add(other.transform);
        }
    }

    void OnTriggerExit2D(Collider2D other)
    {
        if (other.CompareTag("Enemy"))
        {
            enemies.Remove(other.transform);
        }
    }
}

코드를 보면 플레이어와 충돌한 적을 담고
충돌에서 벗어났을 때 타겟에서 제외 시킨다.
( 바꿀거라 트리거는 무시한다. )

원하는 기능이 아니기 때문에
거리만 가지고 타겟을 설정하도록 요청한다.

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

public class PlayerMovement : MonoBehaviour
{
    public GameObject bulletPrefab;

    public float speed = 5f;

    public List<Transform> enemies = new List<Transform>();

    void Update()
    {
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");

        transform.position += new Vector3(horizontal, vertical, 0) * speed * Time.deltaTime;

        // Check for enemies in range and add them to the list
        Collider2D[] colliders = Physics2D.OverlapCircleAll(transform.position, 10f);
        foreach (Collider2D collider in colliders)
        {
            if (collider.CompareTag("Enemy") && !enemies.Contains(collider.transform))
            {
                enemies.Add(collider.transform);
            }
        }

        if (Input.GetKeyDown(KeyCode.Space))
        {
            // Find the nearest enemy
            Transform nearestEnemy = null;
            float minDistance = Mathf.Infinity;
            foreach (Transform enemy in enemies)
            {
                float distance = Vector3.Distance(transform.position, enemy.position);
                if (distance < minDistance)
                {
                    minDistance = distance;
                    nearestEnemy = enemy;
                }
            }

            // Fire bullet towards nearest enemy
            if (nearestEnemy != null)
            {
                Vector2 direction = (nearestEnemy.position - transform.position).normalized;
                GameObject bullet = Instantiate(bulletPrefab, transform.position, Quaternion.identity);
                bullet.GetComponent<BulletMovement>().SetDirection(direction);
            }
        }
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Enemy"))
        {
            enemies.Add(other.transform);
        }
    }

    void OnTriggerExit2D(Collider2D other)
    {
        if (other.CompareTag("Enemy"))
        {
            enemies.Remove(other.transform);
        }
    }
}

전체 코드를 받으면 잘 동작하긴 하는 것을 확인할 수 있다.

하지만 문제점도 있다.

그건 다음 글에 이어서

728x90

댓글