我正在构建一个编辑器,当你按下播放时它会将一堆对象转换为Prefab
(这会向我的引擎解释如何构建一个对象)。当我停止它们时,我想再次重建Prefab
,它应该恢复到原始状态(在按下游戏之前)。我遇到的问题是,当stop
被按下时,项目不会回到原来的状态。当他们停下来时,他们似乎处于他们所处的状态。
以下是我用来来回转换Prefabs的课程:
class Prefab {
public name: string;
public components: PrefabComponent[] = [];
public static create(gameObject: GameObject): Prefab {
let prefab = new Prefab;
prefab.name = gameObject.name;
gameObject.components.forEach(comp => {
let prefabComp = new PrefabComponent;
prefabComp.name = comp.name;
for (let c in comp) {
let prefabProp = new PrefabProperty;
prefabProp.name = c;
if (typeof comp[c] == 'object') {
prefabProp.value = Object.create(comp[c]);
} else {
prefabProp.value = comp[c];
}
prefabComp.properties.push(prefabProp);
}
prefab.components.push(prefabComp);
});
return prefab;
}
public static toObject(prefab: Prefab): GameObject {
let gameObject = new GameObject(prefab.name);
prefab.components.forEach(comp => {
let newComp;
if (comp.name.toLowerCase() != 'transform') {
newComp = gameObject.addComponent(comp.name);
}
if (!newComp) {
newComp = gameObject.getComponent(comp.name);
}
comp.properties.forEach(prop => {
if (prop.value instanceof Sprite) {
newComp[prop.name] = Sprite.create(prop.value.path);
} else if (typeof prop.value == 'object') {
newComp[prop.name] = Object.create(prop.value);
} else {
newComp[prop.name] = prop.value;
}
});
});
return gameObject;
}
}
class PrefabComponent {
public name: string;
public properties: PrefabProperty[] = [];
}
class PrefabProperty {
public name: string;
public value: any;
}
以下是我开始和停止游戏的方式:
play.addEventListener('click', (event) => {
event.preventDefault();
// Game has started
// Stop was pressed
if (game instanceof SpyNginMain) {
game.stopGame();
game = null;
play.classList.remove('active');
pause.classList.remove('active');
// Reset the editor
EditorObjectManager.clear();
prefabs.forEach(prefab => {
EditorObjectManager.addItem(Prefab.toObject(prefab));
});
updateScene();
}
// Game has not started
// Play was pressed
else {
game = new SpyNginMain();
prefabs = [];
EditorObjectManager.items.forEach(item => {
prefabs.push(Prefab.create(item));
});
game.init(scene, prefabs);
game.startGame();
play.classList.add('active');
}
});
问题似乎是当我尝试使用PrefabProperty
类转换Object时。我认为它不是创建一个实例,而是创建一个对原始的引用,但我不确定...
答案 0 :(得分:1)
由于以下代码,您的create
方法肯定会保留对原始对象的引用:
if (typeof comp[c] == 'object') {
prefabProp.value = Object.create(comp[c]);
} else {
prefabProp.value = comp[c];
}
Object.create
调用创建一个以原始对象为原型的新对象,因此如果随后在原始对象中添加/修改/删除属性,则更改也将出现在新创建的对象中。 / p>
我认为你在这里要做的是克隆原始对象?克隆有许多现有的实现(例如lodash的cloneDeep)。
我会用一次clone(comp[c])
调用替换上面引用的所有五行,因为您的typeof
检查在其他方面也不可靠(例如typeof null == 'object'
为真,{{1}是的,等等。)
答案 1 :(得分:0)
这可能只是一个打字稿的东西,但看到这个没有括号看起来不正确:
let prefabComp = new PrefabComponent;
我认为应该是:
let prefabComp = new PrefabComponent();
此处此行:newComp[prop.name] = prop.value;
如果prop.value是一个对象,那么该组件将从旧组件中引用。
查看对象是否相同的好方法是===
。
const a = {'a': 'hello'};
console.log(a === a); // true
const b = {'a': 'hello'};
console.log(a === b); // false