디자인 패턴을 이용해 몬스터 제작
- Entity를 Player, Monster에 상속시키켜 컴포넌트 관리
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[
RequireComponent(typeof(Rigidbody)),
RequireComponent(typeof(CapsuleCollider)),
RequireComponent(typeof(StateMachine)),
RequireComponent(typeof(Animator)),
RequireComponent(typeof(CustomTag)),
RequireComponent(typeof(SkillControllerJ)),
RequireComponent(typeof(SkillControllerJ_V2))
]
public abstract class EntityJ : MonoBehaviour
{
protected StateMachine stateMachine;
protected Rigidbody rigidbody;
protected virtual StaterType EnityStaterType => StaterType.None;
void Awake()
{
stateMachine = GetComponent<StateMachine>();
rigidbody = GetComponent<Rigidbody>();
rigidbody.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ;
}
protected virtual void Start()
{
stateMachine.Run(EnityStaterType);
}
// Update is called once per frame
void Update()
{
stateMachine?.UpdateState();
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
[
RequireComponent(typeof(Blackboard_Monster))
]
public class MonsterJ : EntityJ
{
Blackboard_Monster monster;
protected override StaterType EnityStaterType => StaterType.Monster;
protected override void Start()
{
base.Start();
monster = GetComponent<Blackboard_Monster>();
}
private void OnEnable()
{
MonsterManagerJ.Instance.AddMonster(this);
}
private void OnDisable()
{
if(!MonsterManagerJ.Instance.IsUnityNull())
MonsterManagerJ.Instance.RemoveMonster(this);
}
public void OnDetectPlayer(PlayerJ player)
{
Debug.Log(player);
monster.target = player;
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Blackboard_Monster : MonoBehaviour, IBlackboardBase
{
public float moveSpeed = 3.0f;
public float attackRange = 6.0f;
[NonSerialized] public Animator animator;
[NonSerialized] public Rigidbody rigidbody;
[NonSerialized] public SkillControllerJ SkillController;
[NonSerialized] public EntityJ target;
public new void InitBlackboard()
{
animator = GetComponent<Animator>();
rigidbody = GetComponent<Rigidbody>();
SkillController = GetComponent<SkillControllerJ>();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class CommonState_MonsterJ : MonoBehaviour , IState
{
public StateMachine Fsm { get; set; }
public Blackboard_Monster Blackboard { get; set; }
public void InitState(IBlackboardBase blackboard)
{
Blackboard = blackboard as Blackboard_Monster;
}
public virtual void Enter()
{
throw new System.NotImplementedException();
}
public virtual void UpdateState(float deltaTime)
{
throw new System.NotImplementedException();
}
public virtual void Exit()
{
throw new System.NotImplementedException();
}
}
- 몬스터의 State : Idle, Chase, Skill
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[State("IdleState")]
public class IdleState_MonsterJ : CommonState_MonsterJ
{
public override void Enter()
{
Blackboard.animator.Play("Idles");
Blackboard.animator.SetFloat("Speed", 0.0f);
}
public override void UpdateState(float deltaTime)
{
if (Blackboard.target != null)
{
Fsm.ChangeState(StateTypesClasses.StateTypes.ChaseState);
}
}
public override void Exit()
{
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[State("ChaseState")]
public class ChaseState_MonsterJ : CommonState_MonsterJ
{
public override void Enter()
{
Blackboard.animator.Play("Idles");
Blackboard.animator.SetFloat("Speed", 1.0f);
}
public override void UpdateState(float deltaTime)
{
if (Blackboard.target == null)
{
Fsm.ChangeState(StateTypesClasses.StateTypes.IdleState);
return;
}
var (skillDistance, skillIndex) = Blackboard.SkillController.GetNearSkillDistanceAndIndex();
if (0 > skillIndex)
{
Fsm.ChangeState(StateTypesClasses.StateTypes.IdleState);
return;
}
float attackRnageSqr = skillDistance * skillDistance;
if (Vector3.SqrMagnitude(Blackboard.target.transform.position - Fsm.transform.position) > attackRnageSqr)
{
Vector3 newPos = Vector3.MoveTowards(
Fsm.transform.position,
Blackboard.target.transform.position,
Blackboard.moveSpeed * deltaTime
);
Blackboard.rigidbody.MovePosition(newPos);
return;
}
Fsm.ChangeState(StateTypesClasses.StateTypes.SkillState);
Debug.Log("ChaseState_MonsterJ.Enter");
}
public override void Exit()
{
}
}
using System.Collections;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
[State("SkillState")]
public class SkillState_MonsterJ : CommonState_MonsterJ
{
public override void Enter()
{
Debug.Log("SkillState_MonsterJ.Enter");
FireSkill();
}
public override void UpdateState(float deltaTime)
{
}
public override void Exit()
{
Debug.Log("SkillState_MonsterJ.Exit");
}
async void FireSkill()
{
var (distance, skillIndex) = Blackboard.SkillController.GetNearSkillDistanceAndIndex();
var skillData = Blackboard.SkillController.FireSkillByIndex(skillIndex);
Blackboard.animator.Play(skillData.skillAnimation);
await UniTask.Delay((int)(skillData.skillDuration * 1000));
Debug.Log("OnFireSkill 2");
Fsm.ChangeState(StateTypesClasses.StateTypes.IdleState);
}
}