Hi @janine,
First and foremost, thank you for your quick response and for all the great work you folks are doing (including the numerous helpful responses I’ve read on this forum in the past)!
Interesting. I hadn’t seen that issue thread before, but it makes sense that it’s been encountered by others. Like advised in the Github thread I also ended up removing the green1x1 texture to avoid that issue, but then reencountered it again when working on the water wave shader.
Thanks for the tip on the includeInactive overload! I hadn’t considered that cached tiles were already instantiated as GameObject with meshes, but of course that makes sense! I tested it out and it partially fixed the issue (i.e all tiles were correctly updated), however it did lead to a sort of flashing effect where the code from the script I posted above and the logic around cleaning up textures would rapidly overwrite/fight each other resulting in the water areas occasionally flashing between the a material variant with and without the normal texture.
However, after fiddling a while with that solution I got an idea that ended up working better for me, and that I think is a bit more elegant: Using the OnTileGameObjectCreated event to dynamically create the required texture copies for each tile instance. Here is the code I wrote for doing this:
using UnityEngine;
using UnityEngine.UI;
using CesiumForUnity;
public class CesiumMaterialHandling : MonoBehaviour {
public Cesium3DTileset bingMapTileset;
public Texture2D waveNormalSourceX;
public Texture2D waveNormalSourceY;
public bool waveEffectEnabled;
void Awake() {
bingMapTileset.OnTileGameObjectCreated += OnTileGameObjectCreated;
}
private void OnTileGameObjectCreated(GameObject tile) {
var (waveNormalCopyX, waveNormalCopyY) = CopyWaveNormals();
MeshRenderer mesh = tile.GetComponentInChildren<MeshRenderer>(true);
mesh.material.SetTexture("_waveNormalOne", waveNormalCopyX);
mesh.material.SetTexture("_waveNormalTwo", waveNormalCopyY);
mesh.material.SetInt("_enableWaveEffect", waveEffectEnabled ? 1 : 0);
}
private (Texture2D, Texture2D) CopyWaveNormals() {
// Create a per-tile copy of the X and Y normal textures
Texture2D waveNormalCopyX = new Texture2D(waveNormalSourceX.width, waveNormalSourceX.height, waveNormalSourceX.format, false);
Texture2D waveNormalCopyY = new Texture2D(waveNormalSourceY.width, waveNormalSourceY.height, waveNormalSourceY.format, false);
Graphics.CopyTexture(waveNormalSourceX, waveNormalCopyX);
Graphics.CopyTexture(waveNormalSourceY, waveNormalCopyY);
return (waveNormalCopyX, waveNormalCopyY);
}
private void SetWaveEffectToMaterial(bool enable) {
// Update material and loop through the existing tiles' mesh instances and update them
bingMapTileset.opaqueMaterial.SetInt("_enableWaveEffect", enable ? 1 : 0);
foreach (var mesh in bingMapTileset.GetComponentsInChildren<MeshRenderer>(true)) {
mesh.material.SetInt("_enableWaveEffect", enable ? 1 : 0);
}
}
public void OnToggleWaveEffect(Toggle toggle) {
waveEffectEnabled = toggle.isOn;
SetWaveEffectToMaterial(toggle.isOn);
}
void OnDestroy() {
bingMapTileset.OnTileGameObjectCreated -= OnTileGameObjectCreated;
}
}
This solution has worked very well for me so far, and should in principle work for any issue encountered in the github issue thread. It’s a bit costly on the memory side, but measures such as e.g turning off mipmap generation on the normal textures seems to greatly offset this.
And thanks, happy to hear that! I look forward to work more with Cesium for Unity and expore the material side of things (e.g vertex displace all sea-land boarders, so please let me know if you have any insights on that!)