ECS框架学习-01

移动功能实现

  1. 创建位置组件(Component),速度组件。(注:这里采用的移动方法是数学计算,位移 = 速度*时间)
  2. 创建实体(Entity),添加组件
  3. 创建移动系统(system),通过GameMatcher查找具有指定组件的实体,对实体进行控制
public class MoveSystem : IExecuteSystem
{
    private readonly IGroup<GameEntity> _group;

    public MoveSystem(Contexts contexts)
    {
        _group = contexts.game.GetGroup(GameMatcher.AllOf(
            GameMatcher.PosComp,
            GameMatcher.VelComp
        ));
    }

    public void Execute()
    {
        var dt = Time.deltaTime;
        foreach (var entity in _group.GetEntities())
        {
            var pos = entity.posComp;
            var vel = entity.velComp;

            entity.ReplacePosComp(new Vector2(
                pos.Value.x + dt * vel.Value.x,
            	pos.Value.y + dt * vel.Value.y
            ));
        }
    }
}
  1. 创建继承自MonoBehaviour的GameManager,继承自Feature的GameSystems,通过GameManager控制GameSystems
public class GameManager : MonoBehaviour
{
    public static GameManager Instance;

    private Contexts _contexts;
    private GameSystems _gameSystems;
    private FixedUpdateGameSystems _fixedUpdateGameSystems;

    private void Awake()
    {
        if (Instance != null)
            Destroy(Instance.gameObject);

        Instance = this;

        _contexts = Contexts.sharedInstance;

        _gameSystems = new GameSystems(_contexts);
        _fixedUpdateGameSystems = new FixedUpdateGameSystems(_contexts);
    }

    private void Start()
    {
        _gameSystems.Initialize();	//g 初始化系统
    }

    private void FixedUpdate()
    {
        _fixedUpdateGameSystems.Execute();	//g 执行系统
        _fixedUpdateGameSystems.Cleanup();	//g 清理系统
    }

    private void Update()
    {
        _gameSystems.Execute();
        _gameSystems.Cleanup();
    }

    private void OnDestroy()
    {
        _gameSystems.TearDown();	//g 回收系统
    }
}
public class GameSystems : Feature
{
    public GameSystems(Contexts contexts)
    {

    }
}

public class FixedUpdateGameSystems : Feature
{
    public FixedUpdateGameSystems(Contexts contexts)
    {
        Add(new MoveSystem(contexts));  //g 移动系统
    }
}
  1. 添加移动系统至GameSystems

输入控制移动

  1. 创建输入组件,添加[input]标签;创建Tag组件做为标识
[Input]
[Unique]
public sealed class InputComp : IComponent
{
	public Vector2 Dir;
	public Vector2 MousePos;
	public bool FireButton; // 开火按键
	public bool FireButtonDown; // 开火按键按下
	public bool DashButton; // 冲刺按键
	public bool DashButtonDown; // 冲刺按键按下
	public bool SkillButton; // 技能按键
	public bool SkillButtonDown; // 技能按键按下
}
  1. 创建输入系统(IExecuteSystem)来设置各种功能按键,输入处理系统(ReactiveSystem)来实现效果
public class InputSystem : IExecuteSystem
{
	private readonly Contexts _contexts;

	public InputSystem(Contexts contexts)
	{
		_contexts = contexts;
	}

	public void Execute()
	{
		var playerInputEntity = _contexts.input.CreateEntity();
		playerInputEntity.AddInputComp(new Vector2(
				UnityEngine.Input.GetAxis("Horizontal"),
				UnityEngine.Input.GetAxis("Vertical")
			),
			UnityEngine.Input.mousePosition,
			UnityEngine.Input.GetMouseButton(0),
			UnityEngine.Input.GetMouseButtonDown(0),
			UnityEngine.Input.GetMouseButton(1),
			UnityEngine.Input.GetMouseButtonDown(1),
			UnityEngine.Input.GetKey(KeyCode.Space),
			UnityEngine.Input.GetKeyDown(KeyCode.Space));
	}
}
public class PlayerInputProcessSystem : ReactiveSystem<InputEntity>     //g 也是每帧都执行
{
    private readonly Contexts _contexts;

    public PlayerInputProcessSystem(Contexts contexts) : base(contexts.input)
    {
        _contexts = contexts;
    }

    protected override bool Filter(InputEntity entity)
    {
        return true;
    }

    protected override ICollector<InputEntity> GetTrigger(IContext<InputEntity> context)
    {
        return context.CreateCollector(InputMatcher.InputComp);     //g 当InputComp被添加时,才会触发
    }

    protected override void Execute(List<InputEntity> entities)
    {
        var playerEntity = _contexts.game.playerTagEntity;		//g 取得具有PlayerTag标识的Entity
        var inputComp = _contexts.input.inputComp;

        // 处理玩家移动
        playerEntity.ReplaceVelComp(	//g 通过输入改变速度向量
            new Vector2(
                inputComp.Dir.x * 10,
                inputComp.Dir.y * 10
            )
        );
    }
}
  1. 创建输入实体,添加输入组件
  2. 添加输入系统,输入处理系统至GameSystems

添加视图显示

  1. 创建Player(GameObject),制作预制体(Prefab),保存至Resources文件夹
  2. 创建View实现IView接口,将gameobject与entity绑定
  3. 创建实例化gameobject组件;创建View组件(充当entity与gameobject间的桥梁。通过gameobject.GetEntityLink()获得与该gameobject绑定的entity。通过View组件获得gameobject)
  4. 创建添加视图系统
  5. 添加实例化gameobject组件
  6. 实例化player,调用绑定方法
public class AddViewSystem : ReactiveSystem<GameEntity>
{
    private readonly Contexts _contexts;

    public AddViewSystem(Contexts contexts) : base(contexts.game)
    {
        _contexts = contexts;
    }

    protected override ICollector<GameEntity> GetTrigger(IContext<GameEntity> context)
    {
        return context.CreateCollector(GameMatcher.CreateGameObjCmdComp);
    }

    protected override bool Filter(GameEntity entity)
    {
        return true;
    }

    protected override void Execute(List<GameEntity> entities)
    {
        foreach (var entity in entities)
        {
            var obj = SpawnObj(entity);
            entity.AddViewComp(obj);
            entity.RemoveCreateGameObjCmdComp();
        }
    }

    private GameObject SpawnObj(GameEntity gameEntity)
    {
        var path = gameEntity.createGameObjCmdComp.Path;
        var prefab = Resources.Load<GameObject>(path);
        var obj = GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity);

        var view = obj.GetComponent<View>();
        view.Link(_contexts, gameEntity);
        return obj;
    }
}
  1. 添加View组件,同步gameobject的position,entity的posComp的value
entity.viewComp.View.transform.position = entity.posComp.Value;
  1. 添加视图系统至GameSystem

根据鼠标位置旋转

  1. 创建旋转组件,由于实验项目为2D,只需旋转z轴即可,因此组件中只包含一个浮点型角度
  2. 在处理输入系统中添加处理旋转逻辑
// 处理玩家旋转
var mousePos = inputComp.MousePos;
var worldPos = _mainCamera.ScreenToWorldPoint(mousePos);		//g 屏幕坐标转化为世界坐标
// var dir = new Vector2(worldPos.x, worldPos.y) - playerEntity.posComp.Value;
// var angle = dir.Vector2Angle2D();
// playerEntity.ReplaceRotComp(angle);		//g 由于素材为45°俯视角,因此此处改为翻转图片即可,如果是全俯视视角素材,则使用注释中的内容

if (playerEntity.posComp.Value.x > worldPos.x)
{
    playerEntity.viewComp.View.GetComponentInChildren<SpriteRenderer>().flipX = true;
}
else if (playerEntity.posComp.Value.x < worldPos.x)
{

    playerEntity.viewComp.View.GetComponentInChildren<SpriteRenderer>().flipX = false;
}
  1. 创建旋转系统,根据旋转组件中的角度来改变gameobject的旋转
var angle = gameEntity.rotComp.Angle;
gameEntity.viewComp.View.transform.rotation = Quaternion.Euler(0, 0, angle);
  1. 添加旋转系统至GameSystems
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值