유니티 방치형 프로젝트 - 타겟을 향해 날아가는 스킬 구현하기

반응형

커밋 : 94500ae1731b61a8722b589e6130b6644011d4b7

타겟을 향해 날아가는 스킬 구현하기

구현한 기능

  • 스킬 발동 시 파티클 오브젝트는 플레이어의 지팡이 위치에서 시작해서 타겟 몬스터를 향해 날아가도록 구현
  • 파티클 오브젝트는 몬스터를 향해 날아가며 거리가 0,1f 정도 되면 맞았다고 판정하고 풀에 반환 하고 터지는 이펙트를 Play()
  • 여러 캐릭터의 다른 투사체 & 이펙트를 쉽게 관리하기 위해 딕셔너리로 파티클 관리

변수 설명

_target : 타겟 몬스터의 transform을 대입해두고 다양한 용도로 사용한다. 몬스터의 위치인 targetPos를 구하거나 getcompoenent 해서 몬스터 체력을 깎거나 등등

_targetPos : 대상 위치 저장

_dmg : 타겟 적중 시 데미지를 부여하기 위해

_charactername : 현재는 플레이어가 한 명이지만, 앞으로 여러 플레이어를 생성할 예정이며, 각 플레이어마다 스킬과 해당 스킬의 이펙트가 모두 다를 것입니다. 이를 유연하게 관리하기 위해, 플레이어가 스킬을 사용할 때 스킬 이름(characterName)을 매개변수로 전달한다

예를 들어, CH_01이 스킬 이름이라면 이를 전달하면, Dictionary에서 해당 스킬 이름을 키로 사용하여 적절한 스킬 오브젝트나 이펙트를 가져와 사용할 수 있다
이렇게 하면 플레이어마다 다른 스킬을 효과적으로 관리할 수 있으며, 새로운 스킬이 추가되더라도 딕셔너리에 데이터만 추가하면 쉽게 확장할 수 있다

 

 

코드 설명

 

1. Awake

우선 위 사진부터 오브젝트 게층구조를 보면 Bullet 밑에 Projectiles,Muzzles가 있고 각각 자식으로 CH_01이 있다 Bullet은 Bullet 스크립트가 있는 것이고 getChild를 아래처럼 해서 변수에 담으면 또 각각의 Projectiles와 Muzzles의 자식들이 몇 개인지 아래 for문에서 확인이 가능하고 개수만큼 돌면서 _projectiles 딕셔너리에 CH_01와 같은 이름을 키로 해서 넣는다

 

 

2. Init

Init 에서는 위에서 딕셔너리에 넣은 이펙트들을 아래 _characterName를 사용하여 찾고 Setactive true를 시켜준다.

Update에서는 타겟을 향해 이동하는 로직이고 타겟과 가까우면 아까 true시켯던 오브젝트를 다시 false 시키고 피격 이펙트르 실행시킨다.

 

전체코드

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

public class Bullet : MonoBehaviour
{
    [SerializeField] private float m_speed;
    Transform _target;
    Vector3 _targetPos;
    double _dmg;
    string _characterName;
    bool _getHit = false;

    Dictionary<string, GameObject> _projecTiles = new Dictionary<string, GameObject>();
    Dictionary<string, ParticleSystem> _muzzles = new Dictionary<string, ParticleSystem>();

    private void Awake()
    {
        Transform projectiles = transform.GetChild(0);
        Transform muzzles = transform.GetChild(1);

        for(int i = 0; i < projectiles.childCount; i++)
        {
            _projecTiles.Add(projectiles.GetChild(i).name, projectiles.GetChild(i).gameObject);
        }
        for(int i = 0; i <muzzles.childCount; i++)
        {
            _muzzles.Add(muzzles.GetChild(i).name,muzzles.GetChild(i).GetComponent<ParticleSystem>());
        }
    }
    public void Init(Transform target, double dmg, string characterName)
    {
        _target = target;
        transform.LookAt(_target);
        _getHit = false;
        _targetPos = _target.position;

        this._dmg = dmg;
        _characterName = characterName;
        _projecTiles[_characterName].gameObject.SetActive(true);
    }

    private void Update()
    {
        if (_getHit) return;
        _targetPos.y = 0.5f;
        transform.position = Vector3.MoveTowards(transform.position, _targetPos, Time.deltaTime * m_speed);

        if(Vector3.Distance(transform.position, _targetPos) <= .1f)
        {
            if(_target != null)
            {
                _getHit = true;
                _target.GetComponent<Character>().HP -= _dmg;
                _projecTiles[_characterName].gameObject.SetActive(false);
                _muzzles[_characterName].Play();

                StartCoroutine(ReturnObject(_muzzles[_characterName].duration));
            }
        }
    }

    IEnumerator ReturnObject(float timer)
    {
        yield return new WaitForSeconds(timer);
        Base_Mng.Pool.m_pool_Dictionary["Bullet"].Return(this.gameObject);
    }
}

 

 

 

반응형