몬스터가 플레이어를 인식하고 때리는 동작을 만들어보자
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class BaseController : MonoBehaviour
{
[SerializeField]
protected Vector3 _destPos;
[SerializeField]
protected Define.State _state = Define.State.Idle;
[SerializeField]
protected GameObject _lockTarget;
public Define.WorldObject WorldObjectType { get; protected set; } = Define.WorldObject.Unknown;
public virtual Define.State State
{
get { return _state; }
set
{
_state = value;
Animator anim = GetComponent<Animator>();
switch (_state)
{
case Define.State.Die:
break;
case Define.State.Idle:
anim.CrossFade("WAIT", 0.1f);
break;
case Define.State.Moving:
anim.CrossFade("RUN", 0.1f);
break;
case Define.State.Skill:
anim.CrossFade("ATTACK", 0.1f, -1, 0);
break;
}
}
}
private void Start()
{
Init();
}
void Update()
{
switch (State)
{
case Define.State.Die:
UpdateDie();
break;
case Define.State.Moving:
UpdateMoving();
break;
case Define.State.Idle:
UpdateIdle();
break;
case Define.State.Skill:
UpdateSkill();
break;
}
}
public abstract void Init();
protected virtual void UpdateDie() { }
protected virtual void UpdateMoving() { }
protected virtual void UpdateIdle() { }
protected virtual void UpdateSkill() { }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class MonsterController : BaseController
{
Stat _stat;
[SerializeField]
float _scanRange = 10;
[SerializeField]
float _attackRange = 2;
public override void Init()
{
WorldObjectType = Define.WorldObject.Monster;
_stat = gameObject.GetComponent<Stat>();
if (gameObject.GetComponentInChildren<UI_HPBar>() == null)
Managers.UI.MakeWorldSpaceUI<UI_HPBar>(transform);
}
protected override void UpdateIdle()
{
GameObject player = Managers.Game.GetPlayer();
if (player == null)
return;
float distance = (player.transform.position - transform.position).magnitude;
if (distance <= _scanRange)
{
_lockTarget = player;
State = Define.State.Moving;
return;
}
}
protected override void UpdateMoving()
{
if (_lockTarget != null)
{
_destPos = _lockTarget.transform.position;
float distance = (_destPos - transform.position).magnitude;
if (distance <= _attackRange)
{
NavMeshAgent nma = gameObject.GetOrAddComponent<NavMeshAgent>();
nma.SetDestination(transform.position);
State = Define.State.Skill;
return;
}
}
Vector3 dir = _destPos - transform.position;
if (dir.magnitude < 0.1f)
{
State = Define.State.Idle;
}
else
{
NavMeshAgent nma = gameObject.GetOrAddComponent<NavMeshAgent>();
nma.SetDestination(_destPos);
nma.speed = _stat.MoveSpeed;
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(dir), 20 * Time.deltaTime);
}
}
protected override void UpdateSkill()
{
if (_lockTarget != null)
{
Vector3 dir = _lockTarget.transform.position - transform.position;
Quaternion quat = Quaternion.LookRotation(dir);
transform.rotation = Quaternion.Lerp(transform.rotation, quat, 20 * Time.deltaTime);
}
}
void OnHitEvent()
{
if (_lockTarget != null)
{
Stat targetStat = _lockTarget.GetComponent<Stat>();
targetStat.OnAttacked(_stat);
if (targetStat.Hp > 0)
{
float distance = (_lockTarget.transform.position - transform.position).magnitude;
if (distance <= _attackRange)
State = Define.State.Skill;
else
State = Define.State.Moving;
}
else
{
State = Define.State.Idle;
}
}
else
{
State = Define.State.Idle;
}
}
}