[Unity 강의] 뱀서라이크 강의 - 스킬 개선 , 마무리
카테고리: Class VamSurLike
태그: C#, Unity, VamSurLike
1. 스킬 개선
✔ 게임마다 스킬 설계가 달라진다.
✔ FireBall.cs 추가 - 파이어볼을 주기적으로 생성하는 cs
✔ EgoSword - Rigidbody2D.simulate를 고쳐서 키고 끄던 부분 -> 파티클 시스템 옵션 변경
Play On Awake, Stop Action으로 키고 끄는 방식
EgoSwordChild 코드 삭제, Rigidbody2D 제거.
2. 수정 코드
🔹 PlayerController - 스킬 관련 삭제 -> Skillbook으로, init에서 스킬 생성, 스킬에서 써야 할 변수 프로퍼티
🔹 CreatureController init() -> 스킬북 addcomponent
🔹 SkillBook 추가 스킬들 관리, Player에 컴포넌트 추가
🔹 RepeatSkill.cs 추가
🔹 FireBall.cs 추가 - 파이어볼을 생성
🔹 Egosword 수정 파티클 시스템에서 onoff , EgoswordcHILD 삭제- Egosword에서 관리
🔹 SkillController -> SkillBase
🔹 Define -> 스킬 타입 반복 스킬, 액티브 스킬
Creature, Player
✔ CreatureController init에서 스킬북 addcomponent
✔ PlayerController - Skillbook에서의 스킬을 추가하여 스킬을 얻는 형태
Indicator, FireSocket, ShootDir
Skills.AddSkill으로 스킬 추가.
PlayerController
public class CreatureController : BaseController
{
public SkillBook Skills { get; protected set; }
public override bool Init()
{
base.Init();
Skills = gameObject.GetOrAddComponent<SkillBook>();
return true;
}
}
public class PlayerController : CreatureController
{
public Transform Indicator { get { return _indicator; } }
public Vector3 FireSocket { get { return _fireSocket.position; } }
public Vector3 ShootDir { get { return (_fireSocket.position - _indicator.position).normalized; } }
public override bool Init()
{
if (base.Init() == false)
return false;
Skills.AddSkill<FireballSkill>(transform.position);
Skills.AddSkill<EgoSword>(_indicator.position);
return true;
}
}
SkillBook(SkillManager)
✔ 스킬들을 관리 반복 스킬, 발동 스킬 List로 관리
✔ 에고 소드, 파이어볼 스킬 생성, 파이어볼(오브젝트(부모) 위치 수정 필요)
SkillBook
public class SkillBook : MonoBehaviour
{
// 스킬 매니저.
public List<SkillBase> Skills { get; } = new List<SkillBase>();
public List<SkillBase> RepatedSkills { get; } = new List<SkillBase>();
public List<SequenceSkill> SequenceSkills { get; } = new List<SequenceSkill>();
public T AddSkill<T>(Vector3 position, Transform parent = null) where T : SkillBase
{
System.Type type = typeof(T);
if (type == typeof(EgoSword))
{
var egoSword = Managers.Object.Spawn<EgoSword>(position, SkillID.EGO_SWORD_ID);
egoSword.transform.SetParent(parent);
egoSword.ActivateSkill();
Skills.Add(egoSword);
RepatedSkills.Add(egoSword);
return egoSword as T;
}
else if (type == typeof(FireballSkill))
{
var fireBall = Managers.Object.Spawn<FireballSkill>(position,수정필요);
fireBall.transform.SetParent(parent);
fireBall.ActivateSkill();
Skills.Add(fireBall);
RepatedSkills.Add(fireBall);
return fireBall as T;
}
return null;
}
}
RepeatSkill
✔ RepeatSkill - 코루틴으로 쿨타임마다 스킬을 실행해 주는 코드
RepeatSkill
public abstract class RepeatSkill : SkillBase
{
public float CoolTime { get; set; } = 1.0f;
public RepeatSkill( ) : base(SkillType.Repeat)
{
}
#region CoSkill
Coroutine _coSkill;
public override void ActivateSkill()
{
if (_coSkill != null)
StopCoroutine(_coSkill);
_coSkill = StartCoroutine(CoStartSkill());
}
protected abstract void DoSkillJob();
protected virtual IEnumerator CoStartSkill()
{
WaitForSeconds wait = new WaitForSeconds(CoolTime);
while (true)
{
DoSkillJob();
yield return wait;
}
}
#endregion
}
FireBall
✔ FireBall.cs 추가 - 파이어볼을 주기적으로 생성
FireballSkill
public class FireballSkill : RepeatSkill
{
protected override void DoSkillJob()
{
PlayerController pc = Managers.Game.Player;
if (pc == null)
return;
Vector3 spawnPos = pc.FireSocket;
Vector3 dir = pc.ShootDir;
GenerateProjectile(SkillID.FIRE_BALL_ID, pc, spawnPos, dir, Vector3.zero);
}
}
Egosword
✔ Egosword 수정 파티클 시스템에서 onoff , EgoswordcHILD 삭제- Egosword에서 관리
EgoSword
public class EgoSword : RepeatSkill
{
[SerializeField]
ParticleSystem[] _swingParticles;
protected enum SwingType
{
First,
Second,
Third,
Fourth
}
protected override IEnumerator CoStartSkill()
{
WaitForSeconds wait = new WaitForSeconds(CoolTime);
while (true)
{
SetParticles(SwingType.First);
_swingParticles[(int)SwingType.First].gameObject.SetActive(true);
yield return new WaitForSeconds(_swingParticles[(int)SwingType.First].main.duration);
SetParticles(SwingType.Second);
_swingParticles[(int)SwingType.Second].gameObject.SetActive(true);
yield return new WaitForSeconds(_swingParticles[(int)SwingType.Second].main.duration);
SetParticles(SwingType.Third);
_swingParticles[(int)SwingType.Third].gameObject.SetActive(true);
yield return new WaitForSeconds(_swingParticles[(int)SwingType.Third].main.duration);
SetParticles(SwingType.Fourth);
_swingParticles[(int)SwingType.Fourth].gameObject.SetActive(true);
yield return new WaitForSeconds(_swingParticles[(int)SwingType.Fourth].main.duration);
yield return wait;
}
}
public override bool Init()
{
base.Init();
return true;
}
void SetParticles(SwingType swingType)
{
if (Managers.Game.Player == null)
return;
Vector3 tempAngle = Managers.Game.Player.Indicator.transform.eulerAngles;
transform.localEulerAngles = tempAngle;
transform.position = Managers.Game.Player.transform.position;
float radian = Mathf.Deg2Rad * tempAngle.z * -1;
var main = _swingParticles[(int)swingType].main;
main.startRotation = radian;
}
private void OnTriggerEnter2D(Collider2D collision)
{
MonsterController mc = collision.transform.GetComponent<MonsterController>();
if (mc.IsValid() == false)
return;
mc.OnDamaged(Owner, Damage);
}
}
SkillBase
🔹 SkillBase 스킬의 기본 정보들, 스킬 생성, 스킬 삭제
Owner, SkillType, SkillData, SkillLevel, IsLearnedSkill, Damage
FireballSkill
// EgoSword : 평타
// FireProjectile : 투사체
// PoisonField : 바닥
public class SkillBase : BaseController
{
public CreatureController Owner { get; set; }
public SkillType SkillType { get; set; } = SkillType.None;
public Data.SkillData SkillData { get; protected set; }
public int SkillLevel { get; set; } = 0;
public bool IsLearnedSkill { get { return SkillLevel > 0; } }
public int Damage { get; set; } = 100;
public SkillBase(SkillType skillType)
{
SkillType = skillType;
}
public virtual void ActivateSkill() { }
protected virtual void GenerateProjectile(int templateID, CreatureController owner, Vector3 startPos, Vector3 dir, Vector3 targetPos)
{
ProjectileController pc = Managers.Object.Spawn<ProjectileController>(startPos, templateID);
pc.SetInfo(templateID, owner, dir);
}
#region Destroy
Coroutine _coDestroy;
public void StartDestroy(float delaySeconds)
{
StopDestroy();
_coDestroy = StartCoroutine(CoDestroy(delaySeconds));
}
public void StopDestroy()
{
if (_coDestroy != null)
{
StopCoroutine(_coDestroy);
_coDestroy = null;
}
}
IEnumerator CoDestroy(float delaySeconds)
{
yield return new WaitForSeconds(delaySeconds);
if (this.IsValid())
{
Managers.Object.Despawn(this);
}
}
#endregion
}
DEFINE
DEFINE
public enum SkillType
{
None,
Sequence,
Repeat,
}
오류 수정
Player - Init()이 두 번 실행
✔ 스킬들 2개씩 생성
✅ Player init 2번 => 1번으로 수정 ObjectManager - 스폰 후 init 제거
FireballSkil의 오브젝트 위치
✔ FireballSkil는 빈 오브젝트에 스크립트만 있어도 된다.
✔ 스킬을 쓰는 Owner에게 추가? 스킬 관련 강의 다 들어보고 수정.
FireProjectile 삭제 안되는 오류
✔ SkillBase에서 상속받은 것을 사용하려고 하니까
✔ objectManager.Despawn 코드까지 실행이 되는데 ProjectileController, SkillBase 타입 관련해서 문제가 있는 것 같다.
✅ 일단 Projectile에서 코루틴을 따로 만들어서 실행해서 오류수정. (타입을 체크하는 방법으로 해결해 보기.)
✔ 다른 오류 pool에 들어갔다가 나오면 코루틴 stop 되어서 다시 삭제가 안 되는 부분
✅ Onenable로 코루틴 실행
이것저것 메모
스크립트 이름 변경 시 [SerializeField]
스크립트 이름 변경 시 [SerializeField]
로 드래그 앤 드롭으로 배치된 부분 재확인
MonoBehaviour
스킬북에 있는 스킬들, 스킬 정보들 MonoBehaviour 상속 안 하고 그냥 데이터로만? 고민
잡담, 일기?
강의 복습
코드 분류하는 연습, 상속설계, 상속 관련해서 type을 이용하여 해결하는 법
아직 상속 관련해서 미숙한 것 같다. 상속에 관한 강의, 연습 많이 해보기.
댓글남기기