移动功能实现
- 创建位置组件(Component),速度组件。(注:这里采用的移动方法是数学计算,位移 = 速度*时间)
- 创建实体(Entity),添加组件
- 创建移动系统(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
));
}
}
}
- 创建继承自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();
}
private void FixedUpdate()
{
_fixedUpdateGameSystems.Execute();
_fixedUpdateGameSystems.Cleanup();
}
private void Update()
{
_gameSystems.Execute();
_gameSystems.Cleanup();
}
private void OnDestroy()
{
_gameSystems.TearDown();
}
}
public class GameSystems : Feature
{
public GameSystems(Contexts contexts)
{
}
}
public class FixedUpdateGameSystems : Feature
{
public FixedUpdateGameSystems(Contexts contexts)
{
Add(new MoveSystem(contexts));
}
}
- 添加移动系统至GameSystems
输入控制移动
- 创建输入组件,添加[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;
}
- 创建输入系统(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>
{
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);
}
protected override void Execute(List<InputEntity> entities)
{
var playerEntity = _contexts.game.playerTagEntity;
var inputComp = _contexts.input.inputComp;
playerEntity.ReplaceVelComp(
new Vector2(
inputComp.Dir.x * 10,
inputComp.Dir.y * 10
)
);
}
}
- 创建输入实体,添加输入组件
- 添加输入系统,输入处理系统至GameSystems
添加视图显示
- 创建Player(GameObject),制作预制体(Prefab),保存至Resources文件夹
- 创建View实现IView接口,将gameobject与entity绑定
- 创建实例化gameobject组件;创建View组件(充当entity与gameobject间的桥梁。通过gameobject.GetEntityLink()获得与该gameobject绑定的entity。通过View组件获得gameobject)
- 创建添加视图系统
- 添加实例化gameobject组件
- 实例化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;
}
}
- 添加View组件,同步gameobject的position,entity的posComp的value
entity.viewComp.View.transform.position = entity.posComp.Value;
- 添加视图系统至GameSystem
根据鼠标位置旋转
- 创建旋转组件,由于实验项目为2D,只需旋转z轴即可,因此组件中只包含一个浮点型角度
- 在处理输入系统中添加处理旋转逻辑
var mousePos = inputComp.MousePos;
var worldPos = _mainCamera.ScreenToWorldPoint(mousePos);
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;
}
- 创建旋转系统,根据旋转组件中的角度来改变gameobject的旋转
var angle = gameEntity.rotComp.Angle;
gameEntity.viewComp.View.transform.rotation = Quaternion.Euler(0, 0, angle);
- 添加旋转系统至GameSystems