이 글에서는 현재 진행중인 개인 프로젝트의 코드들을 리뷰를 해보려 한다
캐릭터파트, 스킬파트 크게 두개로 나뉘어 리뷰를 해보려 한다.
👇 캐릭터 Class UML
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Interactable : MonoBehaviour
{
public interactType currentInteractType;
public allyType currentAllyType;
public virtual void Interaction(Interactable obj)
{
}
public virtual void ClaimInteract(Interactable from)
{
}
public virtual interactType CheckInteractTypes(Interactable other)
{
if(other == this)
{
return interactType.없음;
}
else if(CheckAllyType(other))
{
return other.currentInteractType;
}
else
{
return interactType.공격;
};
}
public virtual bool CheckAllyType(Interactable type)
{
if (this.currentAllyType == allyType.작동 || type.currentAllyType == allyType.작동)
{
return true;
}
if (this.currentAllyType == allyType.파괴물 || type.currentAllyType == allyType.파괴물)
{
return false;
}
return this.currentAllyType == type.currentAllyType;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
[RequireComponent(typeof(NavMeshAgent))]
public class Movable : Interactable
{
public NavMeshAgent agent;
public Vector3 moveLocation;
public virtual void Start()
{
agent = GetComponent<NavMeshAgent>();
}
public virtual void MoveTo(Vector3 destination)
{ if (gameObject.GetComponent<NavMeshAgent>().enabled)
{
agent.SetDestination(destination);
moveLocation = destination;
}
}
public virtual void Stop()
{
if (gameObject.GetComponent<NavMeshAgent>().enabled)
{
agent.SetDestination(transform.position);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Character : Movable, Hittable
{
[Header("생명력 부분")]
public int healthCurrent;
public int healthMax;
[Header("마나 부분")]
public float manaCurrent;
public float manaMax;
[Header("공격 부분")]
public float attackRange;
public int attackDamage;
public float attackCoolTime;
private float time = 0f;
[Header("상호작용 부분")]
public float pickUpRange;
public float interactRange;
[Header("애니메이터 입력 부분")]
public CharacterAnimator anim;
[Header("캐릭터의 주목")]
public Interactable focusTarget;
public interactType focusInteraction;
[Header("무적 상태")]
public bool isInvincible = false;
[Header("스킬")]
public List<SkillBase> skillList = new List<SkillBase>();
public List<CharacterAction> actionList = new List<CharacterAction>();
int currentActionIndex = -4;
public List<float> skillCoolList = new List<float>();
public override void Start()
{
base.Start();
anim = GetComponentInChildren<CharacterAnimator>();
if(anim)
{
anim.owner = this;
}
}
public override void Interaction(Interactable obj)
{
focusInteraction = CheckInteractTypes(obj);
focusTarget = obj;
switch (focusInteraction)
{
case interactType.없음:
focusTarget = null;
break;
case interactType.획득:
interactRange = pickUpRange;
break;
case interactType.공격:
interactRange = attackRange;
break;
};
}
protected virtual void Update()
{
if (time > 0)
{
time -= Time.deltaTime;
}
for (int i = 0; i < skillCoolList.Count; i++)
{
skillCoolList[i] -= Time.deltaTime;
}
if (actionList.Count > 0)
{
if(currentActionIndex < 0)
{
currentActionIndex = 0;
actionList[currentActionIndex].OnStart(this);
}
if (actionList[currentActionIndex].isEnd)
{
actionList[currentActionIndex].OnExit(this);
currentActionIndex++;
if(currentActionIndex >= actionList.Count)
{
actionList.Clear();
currentActionIndex = -4;
}
else
{
actionList[currentActionIndex].OnStart(this);
}
}
else
{
actionList[currentActionIndex].OnUpdate(this);
}
}
if (focusTarget != null)
{
float distance = Vector3.Distance(transform.position, focusTarget.transform.position);
if (distance < interactRange)
{
//transform.LookAt(focusTarget.transform.position);
if (focusInteraction == interactType.공격)
{
//transform.LookAt(focusTarget.transform.position);
if (time <= 0)
{
anim?.IdleMotion();
transform.LookAt(focusTarget.transform.position);
anim?.AttackMotion();
time = attackCoolTime;
}
}
else if ( focusInteraction == interactType.대화 || focusInteraction == interactType.획득)
{
focusTarget.ClaimInteract(this);
}
Stop();
}
else
{
base.MoveTo(focusTarget.transform.position);
anim?.MoveMotion();
}
}
else
{
if (Vector3.Distance(transform.position, moveLocation) <= 0.7f)
{
Stop();
}
}
}
public virtual void Attack()
{
focusTarget.GetClass<Character>()?.GetHit(attackDamage);
focusTarget = null;
}
public virtual int GetHit(int damage)
{
if (isInvincible)
{
return 0;
}
healthCurrent -= damage;
return damage;
}
public override void MoveTo(Vector3 destination)
{
base.MoveTo(destination);
anim?.MoveMotion();
}
public override void Stop()
{
base.Stop();
anim?.IdleMotion();
}
public virtual void UseSkill(int index)
{
if (actionList.Count > 0)
{
return;
}
if (index < 0 || index >= skillList.Count)
{
return;
}
SkillBase currentSkill = skillList[index];
if (manaCurrent >= currentSkill.mana && GetSkillCool(index) <= 0)
{// [1]
SetSkillCool(index, currentSkill.coolDown);
actionList = currentSkill.GetActionClone();
manaCurrent -= currentSkill.mana;
}
}
public void ActivateSkill(SkillBase skillName)
{
actionList.AddRange(skillName.GetActionClone());
}
public virtual float SetSkillCool(int index, float wantCoolTime)
{
if (index < 0 || index > skillList.Count)
{
return 0f;
}
while (index >= skillCoolList.Count)
{
skillCoolList.Add(0);
}
return skillCoolList[index] = wantCoolTime;
}
public virtual float GetSkillCool(int index)
{
if (index < 0 || index > skillList.Count)
{
return 0f;
}
while (index >= skillCoolList.Count)
{
skillCoolList.Add(0);
}
return skillCoolList[index];
}
public virtual float GetSkillPercent(int index)
{
float currentLeft = GetSkillCool(index);
if (currentLeft <= 0)
{
return 0;
}
else
{
return skillCoolList[index] / skillList[index].coolDown;
}
}
public virtual void ColliderOn()
{
}
public virtual void ColliderOff()
{
}
}