#02.JobRepeatManager - 01
#02.JobRepeatManager - 02
이번 글은 마지막으로 JobRepeatManager 에 대한 간단한 구조 설명과
사용 예제로 마무리 하겠습니다.
다소 글이 길어질 수 있습니다. 만약 액기스만 뽑아먹을래! 하는 분은 샘플예제만 보셔도 됩니다.
해서...샘플 예제를 먼저 적어두겠습니다.
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using AT.JobManager; | |
public class JobRepeat_Sample : MonoBehaviour { | |
void Start () | |
{ | |
JobRepeatManager.Instance.AddDelegateJob("My_Job_01", OnExecuteTodo, 1.0f, 0, new object[] { "My_Job_01", 0}); | |
JobRepeatManager.Instance.AddDelegateJob("My_Job_02", OnExecuteTodo, 2.0f, 0, new object[] { "My_Job_02", 1}); | |
JobRepeatManager.Instance.AddDelegateJob("My_Job_03", OnExecuteTodo, 2.0f, 10, new object[] { "My_Job_03", 2}); | |
JobRepeatManager.Instance.AddDelegateJob("My_Job_04", OnExecuteTodo, 2.0f, 15, new object[] { "My_Job_04", 3}, OnEndActionWhenDrop); | |
JobRepeatManager.Instance.AddDelegateJob("My_Job_05", OnExecuteTodo, 1.0f, 20, new object[] { "My_Job_05", 4}, OnEndActionWhenDrop, OnCheckDoCondition); | |
JobRepeatManager.Instance.AddDelegateJob("My_Job_06", OnExecuteTodo, 1.0f, 20, new object[] { "My_Job_06", 5}, OnEndActionWhenDrop, OnCheckDoCondition, OnCheckDrop); | |
IEnumerator myJobCoroutine = CoJobExecuteTodo(); | |
JobRepeatManager.Instance.AddCoroutineJob("My_JobCoroutine", myJobCoroutine, 1.0f, 10, new object[] { "My_JobCoroutine" }); | |
} | |
public IEnumerator CoJobExecuteTodo(params object[] param) | |
{ | |
for(int i = 0; i < 10; i++) | |
{ | |
Debug.Log("{0} : JobCoroutine To do!!"); | |
yield return new WaitForSeconds(0.5f); | |
} | |
} | |
public void OnExecuteTodo(params object[] param) | |
{ | |
// To do | |
Debug.LogFormat("{0} : To do !!", param[0]); | |
} | |
public void OnEndActionWhenDrop(params object[] param) | |
{ | |
// Execute When Dropped | |
Debug.LogFormat("{0} : End Action!", param[0]); | |
} | |
public bool OnCheckDoCondition(params object[] param) | |
{ | |
// true -> Available Execute : false -> Block Execute | |
return true; | |
} | |
public bool OnCheckDrop(params object[] param) | |
{ | |
// true > Job Drop : false > Nothing | |
Debug.LogFormat("{0} : Job drop", param[0]); | |
return true; | |
} | |
} |
----------------------------------------
2. JobRepeatManager
JobRepeatManager 는 Singleton Pattern으로 인스턴스가 생성 됩니다.
싱글톤 패턴으로 생성 되어있는 인스턴스 이므로 만약 JobRepeatManager를 사용하실 분들은 간단히 static으로 인스턴스를 넣어주세요.
JobRepeatManager에는 다음과 같은 Public 함수와 멤버변수가 있습니다.
멤버변수 및 애트리뷰트 |
설명 |
public List<JobRepeatBase> JobList |
get; _jobList |
public float MinDelayTime |
get;set; => m_MinDelayTime |
메소드 이름 |
설명 |
public bool AddDelegateJob(string key, JobTodo toDo, float delay = 1.0f, int repeatCount = 0, object[] parameter = null, JobEndAction endActionWhenDrop = null, JobToDoCondition toDoCondition = null, JobAutoDropCondition autoDropCondition = null, bool isImmediately = true) |
- JobRepeatBase를 생성 및 등록하는 함수 - 일반적인 Delegate 형태의 Job을 등록할 수 있습니다. |
public AddCoroutineJob (string key, IEnumerator coroutineJobTodo, float delay = 1.0f, int repeatCount = 0, object[] param = null, JobToDoCondition toDoCondition = null, JobAutoDropCondition autoDropCondition = null, bool isImmediately = true) |
- JobRepeatBase를 생성 및 등록하는 함수 - Coroutine 형태의 Job을 생성합니다. - Todo를 추가로 Job에 등록하고 싶으실 땐 AddFunctionChain을 호출하여 사용합니다. |
public bool JobStart (string key) |
- 특정 등록되어진 Job을 key 값으로 찾아서 Job을 Execute 시킵니다. - 정상적인 실행이 성공되면 true를 리턴합니다. 실패 시 return false |
public bool RemoveJob(string key) |
- 특정 등록되어진 Job을 Key 값으로 찾아서 드랍(Drop)시킵니다. 정상적으로 드랍에 성공할 시 true를 리턴합니다. |
public int JobDropAll ( ) | - 등록되어진 모든 Job을 Drop 시킵니다. - 드랍시킨 Job 갯수를 리턴합니다. |
public bool ChangeJobDelay (string key, float newDelay) | - 특정 등록되어진 Job을 Key 값으로 찾은 뒤 해당 Job의 DelayTime을 변경합니다. - 만약 수행중(Job Started)인 Job 이었다면 다음 수행부터 Delay가 변경됩니다. - 변경에 선공하면 true 를 리턴합니다. |
public bool ChangeJobRepeatCount (string key, int repeatCount) | - 특정 등록되어진 Job을 Key 값으로 찾은 뒤 해당 Job의 RepeatCount를 변경합니다. - 만약 수행중(Job Started)인 Job 이었다면 다음 수행부터 RepeatCount가 변경됩니다. - 변경에 성공하면 true를 리턴합니다. |
public bool AddFunctionChain(string key, JobTodo todo = null, JobTodoCondition TodoCheck = null, JobAutoDropCondition autodropCondition = null, bool isExecuteImmediately = true) | - key값으로 찾은 Job에 등록되어진 Delegate를 추가로 등록하는 함수입니다. |
public bool RemoveFunctionChain(string key, JobTodo todo = null, JobTodoCondition todoCheck = null, JobAutoDropCondition autodropCondition = null, bool isExecuteImmediately = true) | -Key 값으로 찾은 Job에 등록되어진 Delegate를 삭제하는 함수입니다. |
public JobRepeatBase GetJobBase(string key) | - Key 값으로 JobRepeatBase 정보를 찾는 함수입니다. |
private IEnumerator CoAutoDropWorkers() | - Drop 상태가 된 Job을 삭제시키는 Coroutine 입니다. - JobRepeatManager 의 instance가 Start 될 때 실행 됩니다. - Drop 상태 체크는 private WaitForSeconds dropManagingDelay 마다 수행됩니다.
|
private IEnumerator CoJobHandle(string key) | - JobRepeatManager에 등록되어진 Job들을 동작시키는 Corotuine 입니다. - JobRepeatBase에 담겨져있는 Job.state 값에 따라 Job을 동작시킵니다. |
-------------------------------
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using JobTodo = AT.JobManager.JobRepeatBase.JobTodo; | |
using JobToDoCondition = AT.JobManager.JobRepeatBase.JobToDoCondition; | |
using JobAutoDropCondition = AT.JobManager.JobRepeatBase.JobAutoDropCondition; | |
using JobEndAction = AT.JobManager.JobRepeatBase.JobEndAction; | |
using JOB_STATE = AT.JobManager.JobRepeatBase.JOB_STATE; | |
#if UNITY_EDITOR | |
using UnityEditor; | |
namespace AT.JobManager | |
{ | |
[CustomEditor(typeof(JobRepeatManager))] | |
public class JobRepeatManagerEditor : Editor | |
{ | |
private JobRepeatManager manager; | |
public override void OnInspectorGUI() | |
{ | |
manager = (JobRepeatManager)target; | |
EditorGUILayout.BeginHorizontal(); | |
if (GUILayout.Button("Add Empty Job")) | |
{ | |
int EmptyJobCount = manager.JobList.FindAll(job => job.key.Contains("EmptyJob")).Count; | |
manager.AddDelegateJob(string.Format("EmptyJob_{0}", EmptyJobCount), null); | |
} | |
if (GUILayout.Button("Drop All Job")) | |
{ | |
if(manager.JobList.Count > 0) | |
{ | |
foreach(var jobItem in manager.JobList) | |
{ | |
DestroyImmediate(jobItem.gameObject); | |
} | |
manager.JobList.Clear(); | |
} | |
} | |
EditorApplication.update(); | |
EditorGUILayout.EndHorizontal(); | |
DrawDefaultInspector(); | |
} | |
} | |
} | |
#endif | |
namespace AT.JobManager | |
{ | |
[ExecuteInEditMode] | |
public class JobRepeatManager : SingletonBase<JobRepeatManager> | |
{ | |
// Job Information Container - Job Data Struct With Delegate Job | |
[SerializeField] protected List<JobRepeatBase> _jobList = new List<JobRepeatBase>(); | |
public List<JobRepeatBase> JobList { get { return _jobList; } } | |
// Coroutine Job Information Container - Job Data Struct With Coroutine Job | |
[SerializeField] protected Dictionary<string, Coroutine> _coroutineJobList = new Dictionary<string, Coroutine>(); | |
// Min DelayTime | |
protected float m_MinDelayTime = 0.1f; | |
public float MinDelayTime { get { return m_MinDelayTime; } set { m_MinDelayTime = value; } } | |
/// <summary> | |
/// Job RepeatManager > Adding Job | |
/// <para>key = JobKeyName, | |
/// todo = ExecuteFunctionPointer, | |
/// delay = Update Sequence Delay(Seconds), | |
/// repeatCount = Total Execute Count, | |
/// parameter = params object[] : Your Parameter | |
/// todoCondition = Execute Condition(true = Available Execute, false = Block Execute), | |
/// autoDropCondition = Job Drop Condition(Flag : true = Drop, false = MoveNext)</para> | |
/// </summary> | |
public bool AddDelegateJob(string key, JobTodo toDo, float delay = 1.0f, int repeatCount = 0, object[] parameter = null, | |
JobEndAction endActionWhenDrop = null, | |
JobToDoCondition toDoCondition = null, JobAutoDropCondition autoDropCondition = null, bool isImmediately = true) | |
{ | |
// Already Registered Job Check | |
if (JobList.Find(job => job.key.Equals(key)) != null) | |
return false; | |
GameObject JobObject = new GameObject(key); | |
JobObject.transform.parent = this.transform; | |
JobRepeatBase newJob = JobObject.AddComponent<JobRepeatBase>(); | |
newJob.key = key; | |
newJob.jobCoroutine = null; | |
newJob.jobTodo = toDo; | |
newJob.repeatDelay = delay; | |
newJob.repeatCount = repeatCount; | |
newJob.excuteCount = 0; | |
newJob.jobToDoCheck = toDoCondition; | |
newJob.jobAutoDropCheck = autoDropCondition; | |
newJob.jobEndAction = endActionWhenDrop; | |
newJob.state = JOB_STATE.JOB_STANDBY; | |
newJob.worker = CoJobHandle(key); | |
newJob.parameter = parameter; | |
if(toDo == null) | |
{ | |
Debug.LogWarningFormat("Are You Sure Adding Empty Job? Todo Parameter is null (key:{0})", key); | |
newJob.state = JOB_STATE.JOB_EMPTY; | |
} | |
newJob.repeatDelay = newJob.repeatDelay < m_MinDelayTime ? m_MinDelayTime : newJob.repeatDelay; | |
JobList.Add(newJob); | |
if (isImmediately) | |
{ | |
StartCoroutine(newJob.worker); | |
} | |
return true; | |
} | |
/// <summary> | |
/// Job RepeatManager > Coroutine Type Adding Job | |
/// <para>key = JobKeyName, | |
/// todo = Coroutine Type Todo, | |
/// delay = Update Sequence Delay(Seconds), | |
/// repeatCount = Total Execute Count, | |
/// parameter = params object[] : Your Parameter | |
/// todoCondition = Execute Condition(Flag : true = Available Execute, false = Block Execute), | |
/// autoDropCondition = Job Drop Condition(Flag : true = Drop, false = MoveNext), | |
/// </summary> | |
public bool AddCoroutineJob(string key, IEnumerator coroutineJobTodo, float delay = 1.0f, int repeatCount = 0, object[] param = null, | |
JobToDoCondition toDoCondition = null, JobAutoDropCondition autoDropCondition = null, | |
bool isImmediately = true) | |
{ | |
// Already Registered Job Check | |
if (JobList.Find(job => job.key.Equals(key)) != null) | |
return false; | |
GameObject JobObject = new GameObject(key); | |
JobObject.transform.parent = this.transform; | |
JobRepeatBase newJob = JobObject.AddComponent<JobRepeatBase>(); | |
newJob.key = key; | |
newJob.jobCoroutine = coroutineJobTodo; | |
newJob.jobTodo = null; | |
newJob.repeatDelay = delay; | |
newJob.repeatCount = repeatCount; | |
newJob.excuteCount = 0; | |
newJob.jobToDoCheck = toDoCondition; | |
newJob.jobAutoDropCheck = autoDropCondition; | |
newJob.state = JOB_STATE.JOB_STANDBY; | |
newJob.worker = CoJobHandle(key); | |
newJob.parameter = param; | |
if (coroutineJobTodo == null) | |
{ | |
Debug.LogWarningFormat("Are You Sure Adding Empty Job? Todo Parameter is null (key:{0})", key); | |
newJob.state = JOB_STATE.JOB_EMPTY; | |
} | |
newJob.repeatDelay = newJob.repeatDelay < m_MinDelayTime ? m_MinDelayTime : newJob.repeatDelay; | |
JobList.Add(newJob); | |
if (isImmediately) | |
{ | |
StartCoroutine(newJob.worker); | |
} | |
return true; | |
} | |
private void Start() | |
{ | |
StartCoroutine(CoAutoDropWorkers()); | |
} | |
public bool RemoveJob(string key) | |
{ | |
JobRepeatBase findJob = JobList.Find(job => job.key.Equals(key)); | |
if (findJob == null) | |
return false; | |
DestroyImmediate(findJob.gameObject); | |
return JobList.Remove(findJob); | |
} | |
public bool JobStart(string key) | |
{ | |
JobRepeatBase findJob = JobList.Find(job => job.key.Equals(key)); | |
if (findJob == null) | |
return false; | |
StopCoroutine(findJob.worker); | |
findJob.state = JOB_STATE.JOB_STANDBY; | |
StartCoroutine(findJob.worker); | |
return true; | |
} | |
public int JobDropAll() | |
{ | |
int droppedJobCount = 0; | |
if(JobList.Count > 0) | |
{ | |
JobList.Clear(); | |
droppedJobCount = transform.childCount; | |
transform.DestroyAllChildren(); | |
} | |
return droppedJobCount; | |
} | |
public bool ChangeJobDelay(string key, float newDelay) | |
{ | |
JobRepeatBase findJob = JobList.Find(job => job.key.Equals(key)); | |
if (findJob == null) | |
return false; | |
findJob.repeatDelay = newDelay; | |
StopCoroutine(findJob.worker); | |
findJob.state = JOB_STATE.JOB_STANDBY; | |
StartCoroutine(findJob.worker); | |
return true; | |
} | |
public bool ChangeRepeatCount(string key, int repeatCount) | |
{ | |
JobRepeatBase findJob = JobList.Find(job => job.key.Equals(key)); | |
if (findJob == null) | |
return false; | |
findJob.repeatCount = repeatCount; | |
StopCoroutine(findJob.worker); | |
findJob.state = JOB_STATE.JOB_STANDBY; | |
StartCoroutine(findJob.worker); | |
return true; | |
} | |
public bool AddFunctionChain(string key, JobTodo Todo = null, JobToDoCondition toDoCheck = null, JobAutoDropCondition autoDropCondition = null, bool isExecuteImmediately = true) | |
{ | |
JobRepeatBase Job = JobList.Find(job => job.key.Equals(key)); | |
if (Job == null) | |
return false; | |
StopCoroutine(Job.worker); | |
Job.jobTodo += Todo; | |
Job.jobToDoCheck += toDoCheck; | |
Job.jobAutoDropCheck += autoDropCondition; | |
if (Job.jobTodo == null) | |
{ | |
Job.state = JOB_STATE.JOB_EMPTY; | |
return true; | |
} | |
if (isExecuteImmediately) | |
{ | |
Job.state = JOB_STATE.JOB_STANDBY; | |
StartCoroutine(Job.worker); | |
} | |
return true; | |
} | |
public bool RemoveFunctionChain(string key, JobTodo Todo = null, JobToDoCondition toDoCheck = null, | |
JobAutoDropCondition autoDropCondition = null, bool isExecuteImmediately = true) | |
{ | |
JobRepeatBase Job = JobList.Find(job => job.key.Equals(key)); | |
if (Job == null) | |
return false; | |
StopCoroutine(Job.worker); | |
Job.jobTodo -= Todo; | |
Job.jobToDoCheck -= toDoCheck; | |
Job.jobAutoDropCheck -= autoDropCondition; | |
if (Job.jobTodo == null) | |
{ | |
Job.state = JOB_STATE.JOB_EMPTY; | |
return true; | |
} | |
if (isExecuteImmediately) | |
{ | |
Job.state = JOB_STATE.JOB_STANDBY; | |
StartCoroutine(Job.worker); | |
} | |
return true; | |
} | |
public JobRepeatBase GetJobBase(string key) | |
{ | |
return JobList.Find(x => x.key == key); | |
} | |
private WaitForSeconds _dropManagingDelay = new WaitForSeconds(3.0f); | |
private IEnumerator CoAutoDropWorkers() | |
{ | |
while (gameObject.activeSelf) | |
{ | |
var dropItems = JobList.FindAll(Job => Job.state == JOB_STATE.JOB_DROP); | |
foreach(var dropItem in dropItems) | |
{ | |
dropItem.jobEndAction?.Invoke(dropItem.parameter); | |
JobList.Remove(dropItem); | |
DestroyImmediate(dropItem.gameObject); | |
} | |
yield return _dropManagingDelay; | |
} | |
} | |
private IEnumerator CoJobHandle(string key) | |
{ | |
yield return null; | |
JobRepeatBase findJob = JobList.Find(x => x.key == key); | |
if (findJob == null) | |
yield break; | |
switch (findJob.state) | |
{ | |
case JOB_STATE.JOB_EMPTY: | |
yield break; | |
case JOB_STATE.JOB_STANDBY: | |
if (findJob.jobToDoCheck != null) | |
{ | |
if (findJob.jobToDoCheck(findJob.parameter)) | |
{ | |
findJob.state = JOB_STATE.JOB_WORKING; | |
findJob.jobTodo?.Invoke(findJob.parameter); | |
if (findJob.jobCoroutine != null) | |
yield return StartCoroutine(findJob.jobCoroutine); | |
findJob.excuteCount++; | |
if (findJob.excuteCount >= findJob.repeatCount && findJob.repeatCount != 0) | |
findJob.state = JOB_STATE.JOB_DROP; | |
else | |
findJob.state = JOB_STATE.JOB_WAITING; | |
} | |
} | |
else | |
{ | |
findJob.state = JOB_STATE.JOB_WORKING; | |
findJob.jobTodo?.Invoke(findJob.parameter); | |
if (findJob.jobCoroutine != null) | |
yield return StartCoroutine(findJob.jobCoroutine); | |
findJob.excuteCount++; | |
if (findJob.excuteCount >= findJob.repeatCount && findJob.repeatCount != 0) | |
findJob.state = JOB_STATE.JOB_DROP; | |
else | |
findJob.state = JOB_STATE.JOB_WAITING; | |
} | |
if (findJob.jobAutoDropCheck != null) | |
{ | |
if (findJob.jobAutoDropCheck(findJob.parameter)) | |
{ | |
findJob.state = JOB_STATE.JOB_DROP; | |
break; | |
} | |
} | |
break; | |
case JOB_STATE.JOB_WAITING: | |
WaitForSeconds WaitForDelay = new WaitForSeconds(findJob.repeatDelay); | |
yield return WaitForDelay; | |
findJob.state = JOB_STATE.JOB_STANDBY; | |
break; | |
case JOB_STATE.JOB_DROP: | |
yield break; | |
} | |
yield return StartCoroutine(CoJobHandle(findJob.key)); | |
} | |
} | |
} | |
'Unity Engine > Unity3D Engine' 카테고리의 다른 글
#04.C# Job System_01 (0) | 2018.12.22 |
---|---|
#03.JobSequenceManager (0) | 2018.12.21 |
#02.JobRepeatManager - 02 (0) | 2018.12.20 |
#02.JobRepeatManager - 01 (0) | 2018.12.19 |
#01.A에서 B로 일정 시간동안 움직이기 (0) | 2018.12.18 |