참고 : ECS에서 엔티티를 생성할 줄 알고, 제일 기초인 IJobForEach에 대해 이해하고 있어야 한다.
사실 아주 간단하게 처리하였지만 많은 고민을 했었지만 제일 시간을 많이 잡아 먹은건 아래와 같았다.
1. 많은 오브젝트에 대해 SIMO를 실현할 수 있을까?
-> 사실 ECS의 Job 시스템이 이를 처리하는 역할을 한다. 다만 어떤게 더 효율적일까 고민하였다.
2. SharedComponentData를 적용해볼 수 있을까?
-> 조금만 생각해보면 알 수 있는 것인데, 공유된 컴포넌트 데이터는 변경이 최소화 되어야한다. 실시간 입력같은 행위를 했다간 효율이 뚝 떨어진다.
3. 아직 ECS에서는 없는 기능이 많다. 그 없는 기능 중에 "InputSystem"도 있다.
-> 어쩌겠는가. 모노비헤비어를 이용해야지
생각해보면 별거 아니지만 밤새 문서를 보면서 실습하다보니 간단한 사실을 놓치고 있었다.
그렇다 기본에 충실하기로 했다. 어차피 복잡한 시스템 자체는 고급 문법에 대한 예제에 진입할 때 해보면된다. 지금은 가능한한 심플하게에 집중한다.
그래서 플로우를 이렇게 정했다.
1. 아무 변수도 갖추지 않은 PlayerMovement 컴포넌트 데이터를 정의한다.
-> 사실 이 마저도 필요 없다. Translation만 이용해도 되기 떄문, 다만 이 예제에서는 원하는 엔티티만 움직이길 바래서 이리 하였다.
2. 이동하길 원하는 오브젝트에 이를 등록한다.
3. PlayerMovement System에서 1회 입력을 처리 후 Job에게 넘겨준다.
4. Job은 1회의 입력을 해당하는 Entity 들에게 적용한다.
때론 간단한 것이 명답인 것 같다.
using Unity.Entities;
namespace ECS.Labs.InputNmove {
public struct PlayerMovementComponent : IComponentData
{
//아무런 변수를 갖고있지 않습니다.
//단순히 이번 예제에서는 이동할 엔티티를 결정하는 요소로서 작용합니다.
}
}
1. 아무 변수도 갖추지 않은 컴포넌트 데이터를 갖춘다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Entities;
namespace ECS.Labs.InputNmove {
public class PlayerMovementAuthoring : MonoBehaviour,IDeclareReferencedPrefabs,IConvertGameObjectToEntity
{
void IConvertGameObjectToEntity.Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
{
dstManager.AddComponentData(entity, new PlayerMovementComponent());
}
void IDeclareReferencedPrefabs.DeclareReferencedPrefabs(List<GameObject> referencedPrefabs)
{
referencedPrefabs.Add(gameObject);
}
}
}
2. 이동하길 원하는 오브젝트를 엔티티로 등록해준다.
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Transforms;
using UnityEngine;
//사용자의 입력을 받아 작업에 입력하여 오브젝트가 움직일 수 있도록 한다.
namespace ECS.Labs.InputNmove {
public class PlayerMovementSystem : JobComponentSystem
{
struct PlayerMovementJob : IJobForEach<PlayerMovementComponent, Translation>
{
public float3 Dir; //이동 방향을 정한다.
public void Execute([ReadOnly] ref PlayerMovementComponent PMC, [WriteOnly] ref Translation translation)
{
//단순히 더하기만 해주면된다.
translation.Value += Dir;
}
}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
//주의할 점은 struct로 선언된 Job은 메인스레드에서 호출되는 것이 아니란 것 입니다.
//Input와 같은 UnityEngine에 포함된 클래스들은 메인스레드에서만 호출될 수 있음을 인지해야합니다.
//즉, 메인스레드인 이 곳에서 미리 입력 정보를 받아 넘겨줘야 합니다.
var PlayerMovementJob = new PlayerMovementJob {
Dir = new float3(Input.GetAxis("Horizontal"), 0,Input.GetAxis("Vertical")) * 3f * Time.deltaTime
}.Schedule(this, inputDeps);
return PlayerMovementJob;
}
}
}
3. 입력을 받고 Job에게 넘겨준다.
파일을 남긴다.
'Unity > DOTS' 카테고리의 다른 글
Unity DOTS 자료모음 (0) | 2020.07.29 |
---|---|
Unity에서 소개하는 DOTS에 대해 주관적 감상 (0) | 2020.07.29 |
DOTS 학습을 위한 기초 정리 #16 샘플 학습 - 프리팹 등록과 생성 (7) | 2019.05.31 |
DOTS 학습을 위한 기초 정리 #15 엔티티 데이터 접근 - IJobForEach (0) | 2019.05.29 |