커밋 : 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);
}
}