Hello friends,
I am attempting to create a small editor tool that will help me later on with environment setup. The tool will perform the following:
-
Iterate through the children of the clicked entity in the scene.
-
If the entity has a render component on it, the script adds a Rigidbody static and a Collision mesh.
-
Fetch the render asset from the asset folder name found in the render component.
-
Set the render asset to the mesh collider.
This will ensure that every entity has a mesh collider on it. It especially helpful for large scenes with a lot of assets.
The problem:
The system is working well when it comes to adding the components and fetching the render assets.
As you can see the render asset is set to the collision, the same asset as the one in render.
However, I keep getting this error when I run the game.
viewport-error-console.js:159 TypeError: Cannot read properties of undefined (reading 'length')
at CollisionMeshSystemImpl.createPhysicalShape (system.js:402:51)
at CollisionMeshSystemImpl.doRecreatePhysicalShape (system.js:470:31)
at Asset.<anonymous> (system.js:449:22)
at Asset.ready (asset.js:480:22)
at CollisionMeshSystemImpl.loadAsset (system.js:447:19)
at CollisionMeshSystemImpl.recreatePhysicalShapes (system.js:429:22)
at CollisionMeshSystemImpl.afterInitialize (system.js:57:14)
at CollisionComponentSystem.initializeComponentData (system.js:669:14)
at CollisionComponentSystem.addComponent (system.js:55:14)
at SceneParser._openComponentData (scene.js:107:24)
When i comment out this line of code that is setting the render asset to the collision entity.set('components.collision.asset', renderAssetId);
the game launches normally.
When I set the render asset manually in the editor and not from the script, the game launches normally as well.
Here is the link to the project: here
Here is my code:
(function () {
async function listChildrenAndAddComponents(entityId, indentation = '') {
const entity = editor.entities.get(entityId);
if (!entity) {
console.warn("Entity not found.");
return;
}
console.log(`${indentation}Processing entity: ${entity.get('name')}`);
if (entity.has('components.render')) {
const renderAssetId = entity.get('components.render.asset');
const renderAsset = editor.assets.get(renderAssetId);
console.log(`Render Asset ID: ${renderAssetId}`);
if (!entity.has('components.collision')) {
entity.addComponent('collision', { type: 'mesh' });
}
if (!entity.has('components.rigidbody')) {
entity.addComponent('rigidbody', { type: 'static' });
}
if (renderAsset) {
console.log("Render Asset Name:", renderAsset.get('name'));
console.log("Render Asset Type:", renderAsset.get('type'));
if (renderAssetId) {
// Set the collision asset to the render asset
entity.set('components.collision.asset', renderAssetId);
} else {
console.log('Asset ID or Asset is not available');
}
} else {
console.log("Render asset not found.");
}
}
const children = entity.get('children');
if (children && children.length > 0) {
for (const childId of children) {
await listChildrenAndAddComponents(childId, indentation + ' ');
}
}
}
function createButton() {
const btn = new pcui.Button({ text: 'List Children and Add Components' });
btn.style.position = 'absolute';
btn.style.bottom = '10px';
btn.style.right = '10px';
editor.call('layout.viewport').append(btn);
btn.on('click', async () => {
const selectedEntities = editor.call('selector:items');
if (selectedEntities.length === 0) {
editor.call('status:text', 'No entity selected.');
return;
}
for (const entity of selectedEntities) {
await listChildrenAndAddComponents(entity.get('resource_id'));
}
});
}
createButton();
})();
Thank you for your help!