상세 컨텐츠

본문 제목

[개발일지] 2D 방치형 게임개발: 적 구현

카테고리 없음

by 강자이 2024. 6. 27. 09:01

본문

 

EnemyData 클래스

EnemyData 클래스는 적 캐릭터의 움직임을 관리하는 역할을 합니다. Rigidbody2D를 이용하여 주어진 방향과 속도에 따라 적을 이동시키는 Move 메서드를 포함하고 있습니다.

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

public class EnemyData : MonoBehaviour
{
    public float moveSpeed = 3.0f;
    private Rigidbody2D rb;

    private void Start()
    {
        rb = GetComponent<Rigidbody2D>();
    }

    public void Move(Vector2 dir)
    {
        if(rb == null) { return; }

        rb.velocity = dir * moveSpeed;
    }
}

 

EnemyController 클래스

EnemyController 클래스는 적의 행동을 결정하고 플레이어를 추적하는 로직을 포함하고 있습니다. 플레이어와의 거리에 따라 멈춤, 추적, 손실 처리를 결정하며, 추적 중일 때는 애니메이션을 업데이트합니다.

 

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

public class EnemyController : EnemyDetector
{
    private Vector2 targetPos;

    [Header("Detect")]
    [SerializeField][Range(0f, 2.0f)] private float stopRange = 2.0f;
    [SerializeField][Range(0f, 100f)] private float followRange = 50f;
    [SerializeField] private SpriteRenderer characterRenderer;

    private bool wasChasing = false;
    public GameObject enemySightObj;
    public int lostCount = 0;

    private void FixedUpdate()
    {
        Vector2 direction = Vector2.zero;

        if (DistanceToTarget() < stopRange)
        {
            direction = Vector2.zero;
            enemySightObj.SetActive(true);
        }
        else if (DistanceToTarget() < followRange)
        {
            direction = DirectionToTarget();
            wasChasing = true;
            enemySightObj.SetActive(false);
            targetPos = ClosestTarget.transform.position;
            UpdateAnimation();
        }
        else
        {
            if (!Achievement.Instance.isAchievementComplete[3])
            {
                if (wasChasing)
                {
                    lostCount++;
                    wasChasing = false;
                    StopAnimation(AnimationData.WalkParameterHash);
                    StartAnimation(AnimationData.IdleParameterHash);
                }
            }
        }
        enemyData.Move(direction);
    }

    private void UpdateAnimation()
    {
        StopAnimation(AnimationData.IdleParameterHash);
        float dirX = targetPos.x - enemyData.transform.position.x;
        float dirY = targetPos.y - enemyData.transform.position.y;

        StartAnimation(AnimationData.WalkParameterHash);
        SetAnimation(AnimationData.DirXParameterHash, AnimationData.DirYParameterHash, dirX, dirY);
    }
}

 

EnemyDetector 클래스

EnemyDetector 클래스는 적이 특정 대상을 감지하고 이에 대한 정보를 제공하는 기능을 제공합니다. 대상과의 거리 계산, 애니메이션 제어 등의 기본적인 기능을 포함하고 있습니다

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

public class EnemyDetector : MonoBehaviour
{
    public Transform ClosestTarget { get; private set; }
    public EnemyData enemyData;

    [SerializeField] public string playerTag = "Player";

    [field: SerializeField] public AnimationData AnimationData { get; private set; }
    public Animator Animator {  get; private set; }

    private void Awake()
    {
        AnimationData.Initialize();
        Animator = GetComponentInChildren<Animator>();
    }

    private void Start()
    {
        enemyData = GetComponent<EnemyData>();
        ClosestTarget = GameObject.FindGameObjectWithTag(playerTag).transform;
    }

    public float DistanceToTarget()
    {
        return Vector3.Distance(transform.position, ClosestTarget.position);
    }

    public Vector2 DirectionToTarget()
    {
        return (ClosestTarget.position - transform.position).normalized;
    }

    public void StartAnimation(int animatorHash)
    {
        Animator.SetBool(animatorHash, true);
    }

    public void SetAnimation(int animatorHashX, int animatorHashY, float DirX, float DirY)
    {
        Animator.SetFloat(animatorHashX, DirX);
        Animator.SetFloat(animatorHashY, DirY);
    }

    public void StopAnimation(int animatorHash)
    {
        Animator.SetBool(animatorHash, false);
    }
}

 

EnemySight 클래스
EnemySight 클래스는 적이 시각적으로 플레이어를 감지하고 상호작용하는 기능을 제공합니다. 플레이어와의 충돌 검사를 통해 플레이어의 체력을 감소시키고, 시각적 표시를 변경하는 등의 기능을 구현합니다.

 

using Unity.VisualScripting;
using UnityEngine;

public class EnemySight : EnemyDetector
{
    [SerializeField][Range(0f, 1.0f)] private float detactedOpacity = 1.0f;
    [SerializeField] private float detactSpeed = 200.0f;

    public PlayerSO playerData;
    private SpriteRenderer sightRenderer;
    private Transform parentTransform;
    private float opacity;
    private SoundDB soundDB;
    private LifeController _lifeController;
    private int health;
    private int calledDecreaseHealth;

    private void Start()
    {
        soundDB = SoundManager.Instance.soundDB;
        health = StatManager.Instance.health;
        calledDecreaseHealth = StatManager.Instance.calledDecreaseHealth;

        sightRenderer = GetComponent<SpriteRenderer>();
        parentTransform = transform.parent;
        opacity = 0f;
    }

    private void Update()
    {
        ChangeOpacity(opacity);
        transform.RotateAround(parentTransform.position, Vector3.forward, detactSpeed * Time.deltaTime);

        CheckPlayerDead();
    }

    private void CheckPlayerDead()
    {
        if (health == 0 && StatManager.Instance.loseHeartByEnemy)
        {
            StatManager.Instance.isGameOver = true;
            GameManagerTest.Instance.GameOver("불시검문에 걸렸다!!!");
        }
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (health > 0 && collision.CompareTag(playerTag)) 
        {
            SoundManager.Instance.PlayEffect(soundDB.enemyAttackSound, 0.5f, false);
            opacity = detactedOpacity;
            health--;
            calledDecreaseHealth++;
            StatManager.Instance.lifeController.ChangeLifeUI(--StatManager.Instance.health);
            StatManager.Instance.loseHeartByEnemy = true;
        }
    }

    private void OnTriggerExit2D(Collider2D collision)
    {
        opacity = 0f;
    }

    private void ChangeOpacity(float opacity)
    {
        Color color = sightRenderer.color;
        color.a = opacity;
        sightRenderer.color = color;
    }
}

 

Spawner 클래스

Spawner 클래스는 게임 내에서 필요한 오브젝트를 랜덤 위치에 생성하는 기능을 제공합니다. 게임 시작 시 설정된 프리팹을 이용하여 여러 개의 오브젝트를 생성합니다.

 

using UnityEngine;

public class Spawner: MonoBehaviour
{
    public GameObject prefab;

    private void Start()
    {
        for(int i=0;i<3;i++)
            SpawnObject();
    }

    private Vector3 SetRandomPos()
    {
        float X = Random.Range(-25.5f, 26f);
        float Y = Random.Range(.5f, 18.5f);

        Vector3 randomPos = new Vector3(X, Y);
        return randomPos;
    }

    private void SpawnObject()
    {
        Instantiate(prefab, SetRandomPos(), Quaternion.identity);
    }
}

 

요약

위 코드들은 2D 방치형 게임에서 적의 움직임, 추적, 감지, 애니메이션 처리 및 스폰을 담당하는 클래스들입니다. 각 클래스는 특정 기능을 구현하며, 적의 행동 패턴과 게임의 상호작용을 정의하는 데 사용됩니다.

 
 

댓글 영역