여러 IEnumrator를 시간 관리하면서 처리하는 Coroutine
만든 것
TaskScheduler
만들려고 생각한 계기
스테이지 클리어형의 퍼즐 게임의 스테이지 셀렉트 화면에서 축소한 맵을 단번에 3x4의 12개 동적으로 읽어들이면서, 표시. 같은 것을 StartCoroutine으로 하고 있으면 FPS가 가타 떨어지고 UI의 반응이 나빠져 버렸기 때문에.
예를 들면
한 GameObject는 어떤 Prefab을 10개 Instantiate
하고 아이 요소로서 붙여 둘 필요가 있다고 한다.
그러나 Unity의 Instantiate
는 무겁다. 그래서, StartCoroutine
를 사용해, yield return null
하면서 1개씩 Instantiate
하기로 했다. (자주 있음)
public class HogeObject : MonoBehaviour
{
public GameObject prefab;
public void Start()
{
StartCoroutine(CreateIterator());
}
private IEnumrator CreateIterator()
{
for(int i = 0;i < 10;++i)
{
var go = Instantiate(prefab) as GameObject;//heavy work
go.transform.SetParent(this.transform,false);
yield return null;
}
}
}
그러나이 HogeObject
는 화면에 100 개 있었다! (자주 있는(?))
그러면 StartCoroutine
가 100번 불리고 1프레임에 100개 Instantiate
되게 되어 쁘띠 동결과 같은 상태로.
무엇이 나쁜지
Unity의 StartCoroutine
의 구조에는 옆의 연결이 없고, 독립적으로 움직이고 있기 때문에, 몇개 StartCoroutine
되어 왔는지 알았어야 한다는 것.
그래서
처음으로 돌아온다. 자전거 StartCoroutine의 작성.
위의 예는 다음과 같습니다.
public class HogeObject : MonoBehaviour
{
public GameObject prefab;
public void Start()
{
//StartCoroutine(CreateIterator());//この1行が
TaskScheduler.Instance.AddIterator(CreateIterator());//これになる
}
private IEnumrator CreateIterator()
{
for(int i = 0;i < 10;++i)
{
var go = Instantiate(prefab) as GameObject;//heavy work
go.transform.SetParent(this.transform,false);
yield return null;
}
}
}
StartCoroutine
이었던 부분을 TaskScheduler.Instance.AddIterator
로 바꾸는 것으로, TaskScheduler(Singletone)로 1개만 달리고 있다 StartCoroutine
개가 있어도 처리 떨어지지 않는다.
메커니즘
스테이지 클리어형의 퍼즐 게임의 스테이지 셀렉트 화면에서 축소한 맵을 단번에 3x4의 12개 동적으로 읽어들이면서, 표시. 같은 것을 StartCoroutine으로 하고 있으면 FPS가 가타 떨어지고 UI의 반응이 나빠져 버렸기 때문에.
예를 들면
한 GameObject는 어떤 Prefab을 10개 Instantiate
하고 아이 요소로서 붙여 둘 필요가 있다고 한다.
그러나 Unity의 Instantiate
는 무겁다. 그래서, StartCoroutine
를 사용해, yield return null
하면서 1개씩 Instantiate
하기로 했다. (자주 있음)
public class HogeObject : MonoBehaviour
{
public GameObject prefab;
public void Start()
{
StartCoroutine(CreateIterator());
}
private IEnumrator CreateIterator()
{
for(int i = 0;i < 10;++i)
{
var go = Instantiate(prefab) as GameObject;//heavy work
go.transform.SetParent(this.transform,false);
yield return null;
}
}
}
그러나이 HogeObject
는 화면에 100 개 있었다! (자주 있는(?))
그러면 StartCoroutine
가 100번 불리고 1프레임에 100개 Instantiate
되게 되어 쁘띠 동결과 같은 상태로.
무엇이 나쁜지
Unity의 StartCoroutine
의 구조에는 옆의 연결이 없고, 독립적으로 움직이고 있기 때문에, 몇개 StartCoroutine
되어 왔는지 알았어야 한다는 것.
그래서
처음으로 돌아온다. 자전거 StartCoroutine의 작성.
위의 예는 다음과 같습니다.
public class HogeObject : MonoBehaviour
{
public GameObject prefab;
public void Start()
{
//StartCoroutine(CreateIterator());//この1行が
TaskScheduler.Instance.AddIterator(CreateIterator());//これになる
}
private IEnumrator CreateIterator()
{
for(int i = 0;i < 10;++i)
{
var go = Instantiate(prefab) as GameObject;//heavy work
go.transform.SetParent(this.transform,false);
yield return null;
}
}
}
StartCoroutine
이었던 부분을 TaskScheduler.Instance.AddIterator
로 바꾸는 것으로, TaskScheduler(Singletone)로 1개만 달리고 있다 StartCoroutine
개가 있어도 처리 떨어지지 않는다.
메커니즘
public class HogeObject : MonoBehaviour
{
public GameObject prefab;
public void Start()
{
StartCoroutine(CreateIterator());
}
private IEnumrator CreateIterator()
{
for(int i = 0;i < 10;++i)
{
var go = Instantiate(prefab) as GameObject;//heavy work
go.transform.SetParent(this.transform,false);
yield return null;
}
}
}
Unity의
StartCoroutine
의 구조에는 옆의 연결이 없고, 독립적으로 움직이고 있기 때문에, 몇개 StartCoroutine
되어 왔는지 알았어야 한다는 것.그래서
처음으로 돌아온다. 자전거 StartCoroutine의 작성.
위의 예는 다음과 같습니다.
public class HogeObject : MonoBehaviour
{
public GameObject prefab;
public void Start()
{
//StartCoroutine(CreateIterator());//この1行が
TaskScheduler.Instance.AddIterator(CreateIterator());//これになる
}
private IEnumrator CreateIterator()
{
for(int i = 0;i < 10;++i)
{
var go = Instantiate(prefab) as GameObject;//heavy work
go.transform.SetParent(this.transform,false);
yield return null;
}
}
}
StartCoroutine
이었던 부분을 TaskScheduler.Instance.AddIterator
로 바꾸는 것으로, TaskScheduler(Singletone)로 1개만 달리고 있다 StartCoroutine
개가 있어도 처리 떨어지지 않는다.
메커니즘
public class HogeObject : MonoBehaviour
{
public GameObject prefab;
public void Start()
{
//StartCoroutine(CreateIterator());//この1行が
TaskScheduler.Instance.AddIterator(CreateIterator());//これになる
}
private IEnumrator CreateIterator()
{
for(int i = 0;i < 10;++i)
{
var go = Instantiate(prefab) as GameObject;//heavy work
go.transform.SetParent(this.transform,false);
yield return null;
}
}
}
StartCoroutine
는 IEnumerator
를 건네주고 실행하고 있지만, 구조로서는 IEnumerator#MoveNext
를 부르는 것으로 처리를 중단→계속시키고 있다. 이 MoveNext
를 부르는 처리를 스스로 만들면 자전 StartCoroutine
같은 일이 생긴다. IEnumrator
를 받고, 순차적으로 MoveNext
다) yield return null;
의 확장을 Unity의 IEnumrator
를 사용하는 것으로 구현한 느낌 (무슨 말을 했는지 그 2). public void Start()
{
StartCoroutine(Iterator());
}
private IEnumerator Iterator()
{
while (true)
{
var ts = Time.realtimeSinceStartup;
do
{
if (iteratorList.Count <= 0) break;
foreach (var itr in iteratorList.ToList())
{
if (itr.Value.MoveNext() == false)
{
iteratorList.Remove(itr.Key);
}
if (Time.realtimeSinceStartup - ts > targetTime) yield return null;
}
} while (Time.realtimeSinceStartup - ts <= targetTime);
yield return null;
}
}
보충
StartCoroutine
StartCoroutine
등에는 미대응. 라고 할까, 처리의 부하 분산 목적이며, 순차 처리 목적으로의 StartCoroutine은 보통 StartCoroutine으로 해 주면 되는 것은 아니다. StartCoroutine
그리고 TaskScheduler.Instance.AddAction(()=>Instantiate(hogeObj));
라든지는 가치가 있지만 미대응. yield return new WaitForSeconds(ms);
로 하면 사용할 수 있다고 생각한다(시험하지 않는다) Reference
이 문제에 관하여(여러 IEnumrator를 시간 관리하면서 처리하는 Coroutine), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/divideby_zero/items/2f5362fbb2b6dc4d8e99텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)