感谢 Hess 建议优化 ecs 框架所有生命周期事件在处理多实体时,将批处理逻辑移到框架层实现,减小业务层代码量

This commit is contained in:
dgflash
2022-04-15 10:46:43 +08:00
parent e7b5719e68
commit e2861b69d7
7 changed files with 186 additions and 140 deletions

View File

@@ -1,3 +1,9 @@
<!--
* @Author: dgflash
* @Date: 2022-04-14 17:08:00
* @LastEditors: dgflash
* @LastEditTime: 2022-04-15 10:43:53
-->
# oops-framework
#### 介绍
oops-framework 基于 Cocos Creato 3.x 开发的一款游戏框架
@@ -81,3 +87,12 @@ oops-framework 基于 Cocos Creato 3.x 开发的一款游戏框架
打开项目请用Cocos Creator v3.4.2 以上版本
#### 学习交流QQ群798575969
#### 贡献榜
| 时间 | 开发者 | 贡献内容 |
| ---------- | -------- | ------------------------------------------------------------------------------------------- |
| 2022-04.15 | Hess | 建议优化 ecs 框架所有生命周期事件在处理多实体时,将批处理逻辑移到框架层实现,减小业务代码量 |
| 2021-10-13 | laret | 修复 Dialog 类型的 UI 不能连续触发 |
| 2021-10-20 | dogegg | 支持添加 cc.Component 到 ecs 实体对象中 |
| 2022-02-18 | 匿名好友 | 修复 TimerManager 时间管理对象,在游戏最小化切到最大化时,定时间器不触发完成事件的问题 |

View File

@@ -227,7 +227,7 @@
"_priority": 1073741824,
"_fov": 45,
"_fovAxis": 0,
"_orthoHeight": 391.032967032967,
"_orthoHeight": 394.00651465798046,
"_near": 1,
"_far": 2000,
"_color": {

View File

@@ -527,6 +527,7 @@ export module ecs {
}
this.mask.set(compTid);
//@ts-ignore
this[tmpCtor.compName] = ctor;
this.compTid2Ctor.set(compTid, tmpCtor);
ctor.ent = this;
@@ -589,12 +590,14 @@ export module ecs {
compName = ctor.compName;
if (this.mask.has(componentTypeId)) {
hasComp = true;
//@ts-ignore
let comp = this[ctor.compName] as IComp;
//@ts-ignore
comp.ent = null;
if (isRecycle) {
comp.reset();
if (comp.canRecycle) {
compPools.get(componentTypeId).push(comp);
compPools.get(componentTypeId)!.push(comp);
}
}
else {
@@ -604,6 +607,7 @@ export module ecs {
}
if (hasComp) {
//@ts-ignore
this[compName] = null;
this.mask.delete(componentTypeId);
this.compTid2Ctor.delete(componentTypeId);
@@ -703,6 +707,8 @@ export module ecs {
}
}
//#region Matcher
abstract class BaseOf {
protected mask = new Mask();
public indices: number[] = [];
@@ -918,6 +924,7 @@ export module ecs {
return newMatcher;
}
}
//#endregion
//#region System
/**
@@ -927,21 +934,28 @@ export module ecs {
* 当实体从当前System移除下次再次符合条件进入System也会执行上述流程。
*/
export interface IEntityEnterSystem<E extends Entity = Entity> {
entityEnter(entities: E[]): void;
entityEnter(entity: E): void;
}
/**
* 如果需要监听实体从当前System移除需要实现这个接口。
*/
export interface IEntityRemoveSystem<E extends Entity = Entity> {
entityRemove(entities: E[]): void;
entityRemove(entity: E): void;
}
/**
* 第一次执行update
*/
export interface ISystemFirstUpdate<E extends Entity = Entity> {
firstUpdate(entities: E[]): void;
firstUpdate(entity: E): void;
}
/**
* 执行update
*/
export interface ISystemUpdate<E extends Entity = Entity> {
update(entity: E): void;
}
export abstract class ComblockSystem<E extends Entity = Entity> {
@@ -998,17 +1012,32 @@ export module ecs {
return this.group.count > 0;
}
/**
* 先执行entityEnter最后执行firstUpdate
* @param dt
* @returns
*/
private updateOnce(dt: number) {
if (this.group.count === 0) {
return;
}
this.dt = dt;
// 处理刚进来的实体
if (this.enteredEntities!.size > 0) {
(this as unknown as IEntityEnterSystem).entityEnter(Array.from(this.enteredEntities!.values()) as E[]);
var entities = this.enteredEntities!.values();
for (let entity of entities) {
(this as unknown as IEntityEnterSystem).entityEnter(entity);
}
this.enteredEntities!.clear();
}
(this as unknown as ISystemFirstUpdate).firstUpdate(this.group.matchEntities);
// 只执行firstUpdate
for (let entity of this.group.matchEntities) {
(this as unknown as ISystemFirstUpdate).firstUpdate(entity);
}
this.execute = this.tmpExecute!;
this.execute(dt);
this.tmpExecute = null;
@@ -1020,37 +1049,51 @@ export module ecs {
* @returns
*/
private execute0(dt: number): void {
if (this.group.count === 0) {
return;
}
if (this.group.count === 0) return;
this.dt = dt;
this.update(this.group.matchEntities);
// 执行update
for (let entity of this.group.matchEntities) {
this.update(entity);
}
}
/**
* 先执行entityRemove再执行entityEnter最后执行update
* 先执行entityRemove再执行entityEnter最后执行update
* @param dt
* @returns
*/
private execute1(dt: number): void {
if (this.removedEntities!.size > 0) {
if (this.hasEntityRemove) {
(this as unknown as IEntityRemoveSystem).entityRemove(Array.from(this.removedEntities!.values()) as E[]);
var entities = this.removedEntities!.values();
for (let entity of entities) {
(this as unknown as IEntityRemoveSystem).entityRemove(entity);
}
}
this.removedEntities!.clear();
}
if (this.group.count === 0) {
return;
}
if (this.group.count === 0) return;
this.dt = dt;
// 处理刚进来的实体
if (this.enteredEntities!.size > 0) {
if (this.hasEntityEnter) {
(this as unknown as IEntityEnterSystem).entityEnter(Array.from(this.enteredEntities!.values()) as E[]);
var entities = this.enteredEntities!.values();
for (let entity of entities) {
(this as unknown as IEntityEnterSystem).entityEnter(entity);
}
}
this.enteredEntities!.clear();
}
this.update(this.group.matchEntities as E[]);
// 执行update
for (let entity of this.group.matchEntities) {
this.update(entity);
}
}
/**
@@ -1059,8 +1102,8 @@ export module ecs {
* 根据提供的组件过滤实体。
*/
abstract filter(): IMatcher;
// abstract update(entities: E[]): void;
update(entities: E[]) { }; // 避免不需要用update时写一些多余的代码
update(entity: E) { }; // 避免不需要用update时写一些多余的代码
}
/**

View File

@@ -2,7 +2,7 @@
* @Author: dgflash
* @Date: 2021-11-23 15:51:15
* @LastEditors: dgflash
* @LastEditTime: 2022-03-10 10:21:27
* @LastEditTime: 2022-04-15 09:47:36
*/
import { v3 } from "cc";
@@ -28,44 +28,42 @@ export class AccountNetDataSystem extends ecs.ComblockSystem implements ecs.IEnt
return ecs.allOf(AccountNetDataComp, AccountModelComp);
}
entityEnter(entities: Account[]): void {
for (let e of entities) {
var params: any = {
playerId: netConfig.dbid,
sessionKey: netConfig.sessionKey,
}
let onComplete = {
target: this,
callback: (data: any) => {
// 设置本地存储的用户标识(用于下次登录不输入帐号)
this.setLocalStorage(data.id);
// 创建玩家角色对象
this.createRole(e, data);
// 玩家登录成功事件
Message.dispatchEvent(GameEvent.LoginSuccess);
}
}
// 请求登录游戏获取角色数据
// netChannel.game.req("LoginAction", "loadPlayer", params, onComplete);
// 离线测试代码开始
var data = {
id: 1,
name: "Oops",
power: 10,
agile: 10,
physical: 10,
lv: 1,
jobId: 1
}
onComplete.callback(data);
// 离线测试代码结束
e.remove(AccountNetDataComp);
entityEnter(e: Account): void {
var params: any = {
playerId: netConfig.dbid,
sessionKey: netConfig.sessionKey,
}
let onComplete = {
target: this,
callback: (data: any) => {
// 设置本地存储的用户标识(用于下次登录不输入帐号)
this.setLocalStorage(data.id);
// 创建玩家角色对象
this.createRole(e, data);
// 玩家登录成功事件
Message.dispatchEvent(GameEvent.LoginSuccess);
}
}
// 请求登录游戏获取角色数据
// netChannel.game.req("LoginAction", "loadPlayer", params, onComplete);
// 离线测试代码开始
var data = {
id: 1,
name: "Oops",
power: 10,
agile: 10,
physical: 10,
lv: 1,
jobId: 1
}
onComplete.callback(data);
// 离线测试代码结束
e.remove(AccountNetDataComp);
}
/** 创建角色对象(自定义逻辑) */

View File

@@ -2,7 +2,7 @@
* @Author: dgflash
* @Date: 2021-08-11 16:41:12
* @LastEditors: dgflash
* @LastEditTime: 2022-01-27 11:33:31
* @LastEditTime: 2022-04-15 10:01:35
*/
import { Node, Vec3 } from "cc";
import { Timer } from "../../../../core/common/manager/TimerManager";
@@ -63,73 +63,67 @@ export class MoveToSystem extends ecs.ComblockSystem<ecs.Entity> implements ecs.
return ecs.allOf(MoveToComp);
}
entityEnter(entities: ecs.Entity[]): void {
for (let e of entities) {
e.add(VariableMoveToComponent);
}
entityEnter(e: ecs.Entity): void {
e.add(VariableMoveToComponent);
}
entityRemove(entities: ecs.Entity[]): void {
for (let e of entities) {
e.remove(VariableMoveToComponent);
}
entityRemove(e: ecs.Entity): void {
e.remove(VariableMoveToComponent);
}
update(entities: ecs.Entity[]) {
for (let e of entities) {
let move = e.get(MoveToComp);
let mtv = e.get(VariableMoveToComponent);
let end: Vec3;
update(e: ecs.Entity) {
let move = e.get(MoveToComp);
let mtv = e.get(VariableMoveToComponent);
let end: Vec3;
console.assert(move.speed > 0, "移动速度必须要大于零");
console.assert(move.speed > 0, "移动速度必须要大于零");
if (move.target instanceof Node) {
end = move.ns == Node.NodeSpace.WORLD ? move.target.worldPosition : move.target.position;
}
else {
end = move.target as Vec3;
if (move.target instanceof Node) {
end = move.ns == Node.NodeSpace.WORLD ? move.target.worldPosition : move.target.position;
}
else {
end = move.target as Vec3;
}
// 目标移动后,重计算移动方向与移动到目标点的速度
if (mtv.end == null || !mtv.end.strictEquals(end)) {
let target = end.clone();
if (move.offsetVector) {
target = target.add(move.offsetVector); // 这里的问题
}
// 目标移动后,重计算移动方向与移动到目标点的速
if (mtv.end == null || !mtv.end.strictEquals(end)) {
let target = end.clone();
if (move.offsetVector) {
target = target.add(move.offsetVector); // 这里的问题
}
// 移动方向与移动
let start = move.ns == Node.NodeSpace.WORLD ? move.node.worldPosition : move.node.position;
move.velocity = Vec3Util.sub(target, start).normalize();
// 移动方向与移动数度
let start = move.ns == Node.NodeSpace.WORLD ? move.node.worldPosition : move.node.position;
move.velocity = Vec3Util.sub(target, start).normalize();
// 移动时间与目标偏位置计算
let distance = Vec3.distance(start, target) - move.offset;
// 移动时间与目标偏位置计算
let distance = Vec3.distance(start, target) - move.offset;
move.onChange?.call(this);
if (distance - move.offset <= 0) {
this.exit(e);
}
else {
mtv.timer.step = distance / move.speed;
mtv.end = end.clone();
mtv.target = move.velocity.clone().multiplyScalar(distance).add(start);
}
}
if (move.speed > 0) {
let trans = Vec3Util.mul(move.velocity, move.speed * this.dt);
move.node.translate(trans, Node.NodeSpace.LOCAL);
}
// 移动完成事件
if (mtv.timer.update(this.dt)) {
if (move.ns == Node.NodeSpace.WORLD)
move.node.worldPosition = mtv.target;
else
move.node.position = mtv.target;
move.onChange?.call(this);
if (distance - move.offset <= 0) {
this.exit(e);
}
else {
mtv.timer.step = distance / move.speed;
mtv.end = end.clone();
mtv.target = move.velocity.clone().multiplyScalar(distance).add(start);
}
}
if (move.speed > 0) {
let trans = Vec3Util.mul(move.velocity, move.speed * this.dt);
move.node.translate(trans, Node.NodeSpace.LOCAL);
}
// 移动完成事件
if (mtv.timer.update(this.dt)) {
if (move.ns == Node.NodeSpace.WORLD)
move.node.worldPosition = mtv.target;
else
move.node.position = mtv.target;
this.exit(e);
}
}

View File

@@ -2,7 +2,7 @@
* @Author: dgflash
* @Date: 2022-01-25 17:49:26
* @LastEditors: dgflash
* @LastEditTime: 2022-03-10 13:47:35
* @LastEditTime: 2022-04-15 09:37:39
*/
import { Message } from "../../../core/common/event/MessageManager";
@@ -38,15 +38,13 @@ export class RoleChangeJobSystem extends ecs.ComblockSystem implements ecs.IEnti
return ecs.allOf(RoleChangeJobComp, RoleModelJobComp);
}
entityEnter(entities: Role[]): void {
for (let e of entities) {
// 数值更新
e.RoleModelJob.id = e.RoleChangeJob.jobId;
entityEnter(e: Role): void {
// 数值更新
e.RoleModelJob.id = e.RoleChangeJob.jobId;
// 转职事件,通知视图层逻辑刷新界面效果,实现两层逻辑分离
Message.dispatchEvent(RoleEvent.ChangeJob);
// 转职事件,通知视图层逻辑刷新界面效果,实现两层逻辑分离
Message.dispatchEvent(RoleEvent.ChangeJob);
e.remove(RoleChangeJobComp);
}
e.remove(RoleChangeJobComp);
}
}

View File

@@ -21,27 +21,25 @@ export class RoleUpgradeSystem extends ecs.ComblockSystem implements ecs.IEntity
return ecs.allOf(RoleUpgradeComp, RoleModelLevelComp);
}
entityEnter(entities: Role[]): void {
for (let e of entities) {
let rm = e.RoleModel;
let rlm = e.RoleModelLevel;
let ru = e.RoleUpgrade;
entityEnter(e: Role): void {
let rm = e.RoleModel;
let rlm = e.RoleModelLevel;
let ru = e.RoleUpgrade;
if (ru.lv == 0)
rlm.vm.lv++; // 提升一级
else
rlm.vm.lv = ru.lv; // 设置等级
if (ru.lv == 0)
rlm.vm.lv++; // 提升一级
else
rlm.vm.lv = ru.lv; // 设置等级
// 当前等级配置
rlm.rtluCurrent.init(rlm.vm.lv);
// 等级附加属性
rm.attributes.get(RoleAttributeType.hp).level = rlm.rtluCurrent.hp;
// 当前等级配置
rlm.rtluCurrent.init(rlm.vm.lv);
// 等级附加属性
rm.attributes.get(RoleAttributeType.hp).level = rlm.rtluCurrent.hp;
// 下个等级配置
rlm.rtluNext.init(rlm.vm.lv + 1);
rlm.vm.expNext = rlm.rtluNext.needexp;
// 下个等级配置
rlm.rtluNext.init(rlm.vm.lv + 1);
rlm.vm.expNext = rlm.rtluNext.needexp;
e.remove(RoleUpgradeComp);
}
e.remove(RoleUpgradeComp);
}
}