I’m trying to implement color changing functionality for a GLB model in PlayCanvas React. The goal is to change the model’s color when clicking on color swatches in a menu, specifically implementing a “tint without textures” approach.
What I’ve done so far:
Created a custom hook useModelColor and a component ColorableModel
// useModelColor.ts
import { useCallback } from 'react';
import { Color } from 'playcanvas';
export const useModelColor = () => {
const changeModelColor = useCallback((meshInstances: any[], color: number[]) => {
if (!meshInstances?.length) {
console.warn('No meshInstances available');
return;
}
meshInstances.forEach(mesh => {
if (mesh?.material) {
const newColor = new Color(color[0], color[1], color[2]);
mesh.material.diffuse = newColor;
mesh.material.update();
}
});
}, []);
return { changeModelColor };
};
// ColorableModel.tsx
import { Entity } from '@playcanvas/react';
import { Render } from '@playcanvas/react/components';
import { useModel } from '@playcanvas/react/hooks';
import { useRef, useEffect } from 'react';
import { useModelColor } from '../hooks/useModelColor';
interface ColorableModelProps {
src: string;
selectedColor?: number[];
}
export const ColorableModel = ({ src, selectedColor }: ColorableModelProps) => {
const { asset } = useModel(src);
const { changeModelColor } = useModelColor();
const entityRef = useRef<any>(null);
useEffect(() => {
if (!entityRef.current || !selectedColor) return;
const tryAccessMeshInstances = () => {
const render = entityRef.current?.components?.render;
if (render?.meshInstances?.length) {
console.log('MeshInstances found:', render.meshInstances);
changeModelColor(render.meshInstances, selectedColor);
} else {
console.log('No meshInstances yet, retrying...');
setTimeout(tryAccessMeshInstances, 100);
}
};
tryAccessMeshInstances();
}, [selectedColor, changeModelColor]);
if (!asset) return null;
return (
<Entity ref={entityRef}>
<Render asset={asset} />
</Entity>
);
};
The Problem:
The model loads successfully, but I can’t access meshInstances to change the color. I’ve tried several approaches:
-
Initially tried accessing meshInstances directly through asset.resource
-
Then attempted to access through Entity’s render component
-
Implemented a retry mechanism with setTimeout
-
Added useRef to get access to the Entity
-
Added detailed logging for debugging
Despite these attempts, meshInstances remains inaccessible even after multiple retry attempts. The model renders correctly, but I can’t modify its color.
Questions:
-
What is the correct way to access and modify meshInstances in PlayCanvas React?
-
Is there a proper event or callback I should wait for before attempting to modify the model’s material?
-
Are there any alternative approaches to changing a GLB model’s color in PlayCanvas React?
-
Could you please share any examples of implementing similar color-changing functionality?
I would be incredibly grateful for any guidance, examples, or best practices you could share. Thank you in advance for your time and assistance!