Entitas 实现 点击创建物体在屏幕上面
1.创建四个 Component
每个 Componet 都是只包含自身的数据。
[Game]
public class TransformComponent : IComponent //使用Gameobject 也行
{
public Transform transform;
}
[Game]
public class PositionComponent : IComponent
{
public Vector2 position;
}
[Game]
public class SpriteComponent : IComponent
{
public string spriteName;
}
以及记录输入数据的 InputComponent。
[Input, Unique]//Unique 全局唯一
public class MouseComponent : IComponent
{
public EMouseEventType mouseEventType;
}
2.创建 MouseSystem
负责检测鼠标点击。
public enum EMouseEventType
{
Down,
Press,
Up
}
public class MouseSystem : IExecuteSystem //每一帧都会执行的System
{
private InputContext _context;
public MouseSystem(Contexts contexts)
{
this._context = contexts.input;
}
public void Execute()
{
if (Input.GetMouseButtonDown(0))
{
this._context.ReplaceInputExampleMouse(EMouseEventType.Down);
}
if (Input.GetMouseButtonDown(1))
{
this._context.ReplaceInputExampleMouse(EMouseEventType.Down);
}
}
}
3.创建 CreateSystem
负责监听鼠标点击事件。
public class CreateSystem : ReactiveSystem<InputEntity>
{
private Transform _parent;
private GameContext _gameContext;
public CreateSystem(Contexts contexts) : base(contexts.input)
{
this._gameContext = contexts.game;
this._parent = new GameObject("CreateParent").transform;
}
protected override ICollector<InputEntity> GetTrigger(IContext<InputEntity> context)
{
return context.CreateCollector(InputMatcher.InputExampleMouse);
}
protected override bool Filter(InputEntity entity)
{
return entity.hasInputExampleMouse && entity.inputExampleMouse.mouseEventType == EMouseEventType.Down;
}
protected override void Execute(List<InputEntity> entities)
{
foreach (InputEntity entity in entities)
{
GameEntity gameEntity = this._gameContext.CreateEntity();
Transform transform = this.GetEntityTransform(gameEntity);//添加Transform组件
gameEntity.AddInputExampleTransform(transform);
Vector2 worldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);//添加Position组件
gameEntity.AddInputExamplePosition(worldPos);
string spriteName = "Test Sprite Name";//添加Sprite组件
gameEntity.AddInputExampleSprite(spriteName);
}
}
private Transform GetEntityTransform(GameEntity gameEntity)
{
GameObject go = new GameObject("Clone");
go.transform.SetParent(this._parent);
go.Link(gameEntity, this._gameContext);//物体与Entity进行 链接
return go.transform;
}
}
4.创建 ChangePositonSystem
负责物体修改坐标。
public class ChangePositionSystem : ReactiveSystem<GameEntity>
{
public ChangePositionSystem(Contexts contexts) : base(contexts.game)
{
}
protected override ICollector<GameEntity> GetTrigger(IContext<GameEntity> context)
{
return context.CreateCollector(GameMatcher.InputExamplePosition);
}
protected override bool Filter(GameEntity entity)
{
return entity.hasInputExamplePosition && entity.hasInputExampleTransform;
}
protected override void Execute(List<GameEntity> entities)
{
foreach (GameEntity entity in entities)
{
Vector2 postion = entity.inputExamplePosition.position;
Transform transform = entity.inputExampleTransform.transform;
transform.position = postion;
}
}
}
5.创建 ChangeSpriteSystem
负责修改图片显示。
public class RenderSpriteSystem : ReactiveSystem<GameEntity>
{
public RenderSpriteSystem(Contexts contexts) : base(contexts.game)
{
}
protected override ICollector<GameEntity> GetTrigger(IContext<GameEntity> context)
{
return context.CreateCollector(GameMatcher.InputExampleSprite);
}
protected override bool Filter(GameEntity entity)
{
return entity.hasInputExampleSprite && entity.hasInputExampleTransform;
}
protected override void Execute(List<GameEntity> entities)
{
foreach (GameEntity entity in entities)
{
Transform transform = entity.inputExampleTransform.transform;
SpriteRenderer spriteRenderer = transform.GetComponent<SpriteRenderer>();
if (spriteRenderer == null)
{
spriteRenderer = transform.gameObject.AddComponent<SpriteRenderer>();
}
spriteRenderer.sprite = Resources.Load<Sprite>(entity.inputExampleSprite.spriteName);
}
}
}
6.创建 两个Feature
GameFeature与InputFeature
public class GameFeature : Feature
{
public GameFeature(Contexts contexts)
{
Add(new RenderSpriteSystem(contexts));
Add(new ChangePositionSystem(contexts));
}
}
public class InputFeature : Feature
{
public InputFeature(Contexts contexts)
{
Add(new MouseSystem(contexts));
Add(new CreateSystem(contexts));
}
}
7.与Unity进行关联
public class GameController : MonoBehaviour
{
private Contexts _contexts;
private Systems _systems;
// Start is called before the first frame update
void Start()
{
this._contexts = Contexts.sharedInstance;
this._systems = new Feature("System")
.Add(new GameFeature(this._contexts))
.Add(new InputFeature(this._contexts));
this._systems.Initialize();
}
// Update is called once per frame
void Update()
{
this._systems.Execute();
this._systems.Cleanup();
}
}
这样就实现了点击屏幕,实例化一个物体,并且修改位置与坐标显示。
问题:
1.使用普通代码的方式不是更简单吗?
这里追求的不是写的快,一是学习ECS的方式,二是把数据和逻辑进行分离。
2.Game和Input有什么区别?
本质上没区别,但是是两个不同上下文,也可以理解为不同的环境。