主题
SCE Scene Environment
Use this skill when the task changes or reads SCE scene builtin nodes, terrain runtime state, weather, lighting, fog, FogOfWar, cloud shadow, or LightGroup presets.
Human-facing doc: docs/systems/SceSceneEnvironmentSystem.md.
Fit Check
| Goal | Use |
|---|---|
| Runtime terrain material/weights, weather, fog, lighting, FogOfWar, cloud shadow, LightGroup XML fade in an SCE map | This skill |
Independent local SceneGraph mini-game or model/material preview | client-scenegraph-game |
| Material/shader/pass visibility issue | gamegraph-materials |
| Gameplay visibility, observer range, unit reveal rules, server-authoritative vision | SceneVisionSystem / relevant Unit gameplay skill |
| Permanent map atmosphere, fog, sunlight, reflection or post-processing | Use atmosphere-mcp and read docs/guides/AtmosphereLightGroup.md; query/preview/apply/save the active atmosphere |
Editor Atmosphere Files (Permanent Authoring)
In the SCE Editor, the map's 氛围 / atmosphere is the scene's LightGroup environment. It is not a separate opaque binary format: files under the project map's atmosphere/ directory use the .lightgroup suffix but contain XML text (<node>, Zone, Light, and their <attribute> values). For example:
text
<project-map>/atmosphere/default.lightgroup
<project-map>/atmosphere/<name>.lightgroupWhen a user asks the AI to permanently change the map atmosphere, prefer the full Editor MCP: terrain_get_atmosphere -> terrain_preview_atmosphere_edit -> terrain_apply_atmosphere_edit -> explicit scene save. Read atmosphere-mcp. It discovers the active .lightgroup, accepts partial typed Zone/Light patches and sun Euler angles, and creates one Undo/Redo transaction. name.json lists display names and is not the lighting payload. Do not rename .lightgroup files to .xml.
Recommended AI authoring loop:
- Query the current scene and
atmosphere.lightgroup_path; match the requested preset before editing. Other presets can be selected through the editor atmosphere panel. - Preview only the requested editable attributes, then apply with the same patch and current preview token/hash. Read back actual values and inspect the rendered scene.
- Explicitly save:
terrain_save_scenefor discrete tile scenes; normal editor save for other backends. Reload and verify both values and appearance. - If MCP is unavailable and the scene is offline, parse the chosen XML and preserve unrelated attributes, resource paths, generated IDs and origin. Avoid disk XML edits behind an open scene. Temporary gameplay transitions use the runtime API below.
This authoring path is different from the client runtime controller below:
- Editing
<project-map>/atmosphere/*.lightgrouppersists a map asset and affects future editor/game loads. SceneLightingController.LoadPreset(...),StartPresetFade(...), andApply*Settings(...)affect only the current client session and never write those files.- Terrain geometry/material/weight edits are separate from atmosphere/LightGroup edits; do not modify terrain assets when the request is only about scene mood, fog, sunlight, or ambient lighting.
Common XML edit targets are Zone attributes such as Ambient Color, Fog Color, depth/height fog switches, distances, density, environment texture paths/intensities, Bloom, and vignette; and main Light attributes such as node Rotation, Color, Brightness Multiplier, temperature, shadows, and weather/volumetric values. XML colors are generally normalized 0–1 RGBA, while the editor UI displays 0–255. Rotation is serialized as a quaternion, so use the editor for direction changes. If Depth Fog AutoCompute is enabled, manual start/end edits may have no visible effect; if Use Temperature is enabled, changing only Color may not produce the expected result.
After an authoring edit, reopen/reload the map or run a client debug session to verify the selected atmosphere. For a temporary in-game change, use the runtime API instead and keep the change under #if CLIENT. See docs/guides/AtmosphereLightGroup.md for the full field map and XML examples.
Boundaries
- Put all usage under
#if CLIENT. - These APIs are runtime-only and client-only. They do not sync to the server, other clients, or saved map resources.
- Access through
Scene, not plainSceneGraph. OrdinarySceneGraphinstances do not guarantee SCE fixed node names. - Wait for the configured SCE
Sceneto load.Game.LocalScene.IsEngineFallback == truemeans map-dependent SCE nodes are not available. - Always handle
nullfromTryGetWeatherController()andTryGetLightingController(). - If the user needs persistence or multiplayer consistency, store a project-level weather/lighting state and have each client apply it locally.
Entry Pattern
csharp
#if CLIENT
using GameGraph.NodeSystem;
var scene = Game.LocalScene;
if (scene.IsEngineFallback)
{
return;
}
var weather = scene.TryGetWeatherController();
var lighting = scene.TryGetLightingController();
#endifFor nodes only:
csharp
#if CLIENT
var terrainNode = Game.LocalScene.TryGetTerrainNode();
var terrain = Game.LocalScene.TryGetTerrainController();
var weatherNode = Game.LocalScene.TryGetWeatherNode();
var lightingNode = Game.LocalScene.TryGetLightingNode();
var lightGroup = Game.LocalScene.GetBuiltinNode(SceneBuiltinNodeKind.LightGroup);
#endifTerrain Patterns
Use SceneTerrainController for the current SCE terrain node, terrain materials, tile texture weights, texture labels, Landscape patch blend, Landscape weight map pixels, and runtime painting.
For discrete tile texture-weight edits, configure GameDataScene.EnableRuntimeTerrainTextureEditing = true before scene loading and require ClientRuntimeFeature.RuntimeTerrainTextureEditing (client capability 5). The default is false: ordinary loading releases weights and mesh rebuild data. Enabling this costs client memory for the scene/cache lifetime; changing the field after loading cannot recover discarded data. Configure JSON-owned scenes in their source JSON, then regenerate normally. Never patch generated data. Material texture replacement and Landscape weight maps are separate from this opt-in. Batch tile writes with refresh: false, then refresh once; verify readback and screenshots.
csharp
#if CLIENT
using EngineInterface.Urho3DInterface.Graphics;
using GameGraph.NodeSystem;
using ResourceTexture = GameCore.ResourceType.Texture;
var terrain = Game.LocalScene.TryGetTerrainController();
terrain?.SetMaterialTexture(
materialIndex: 0,
unit: TextureUnit.Diffuse,
texturePath: (ResourceTexture)"res/terrain/grass.png");
#endifcsharp
#if CLIENT
using GameGraph.MaterialSystem;
using GameGraph.NodeSystem;
var terrain = Game.LocalScene.TryGetTerrainController();
if (terrain?.GetTextureWeights(position) is { } weights)
{
terrain.SetTextureWeights(position, weights with
{
Weight1 = 1.0f,
Weight2 = 0.0f
});
}
#endifTerrain material and weight edits are runtime terrain state. They are not the same as saving terrain assets in the editor, and they do not become server-authoritative gameplay data by themselves.
Runnable Tile Texture Sample
In editors with the scene-inspector toggle, users can enable “允许运行时修改地表纹理” in the scene editor's right-hand scene properties. It writes the same GameDataScene.EnableRuntimeTerrainTextureEditing field and is shown for discrete tile scenes. Save the project and reload the runtime scene; toggling it does not restore data discarded by an already-running scene.
Use map_templates/code_sample/src/RuntimeTerrainTextureSample/ for a complete example: a dedicated scene opt-in, solid replacement, blend ratios, a three-surface gradient, soft brush, spread animation, and snapshot restore. Register/select its game mode using the sample README. The map assets ship in scene/runtime_terrain_texture_sample/.
- Capture the entire
TerrainTextureWeightsfor every edited point before painting. Restore all indices, base weights andExtendedWeights, not just two floats. Stop animation before restoring. - Resolve texture slots and groups from the loaded map resources. The sample deliberately validates field group 1 / style 0 / slots 2, 3, 7; this fixture mapping is not a general whitelist or a rule for other maps.
- Keep base texture indices/weights and extended group weights consistent.
ExtendedWeights.XYZfollows group item order;Widentifies the group. Follow the sample'sEncodeGrouprather than modifying onlyWeight1/Weight2and assuming every render path uses them. - Current SDK normalization clamps all extended vector components to
[0,1]. Group 1 is the sample's supported case; verify API support and exact group-id readback before adapting it to larger group IDs. - Derive animated brush frames from the captured baseline, not the previous frame. Preserve incompatible styles/groups instead of inventing a universal cross-style interpolation. Batch writes, refresh once, and release snapshots/UI when the session ends.
- Check readback plus rendered output. Use structured status for repeated operations and a small number of settled foreground screenshots; user visual confirmation can supply the visual evidence. Repeated full-resolution captures are not necessary.
Weather Patterns
Use SceneWeatherController for TerrainData weather, Zone fog, light weather values, cloud shadow, and client FogOfWar.
csharp
#if CLIENT
using System.Drawing;
using GameGraph.NodeSystem;
var weather = Game.LocalScene.TryGetWeatherController();
if (weather is null || !weather.HasTerrainData)
{
return;
}
weather.TerrainDataEnabled = true;
weather.WeatherEffectEnabled = true;
weather.TerrainFogColor = Color.FromArgb(255, 80, 100, 120);
weather.ApplyLightWeatherValues(Color.FromArgb(255, 120, 150, 190), 0.75f);
weather.SetLightWeatherParamBlend(1.0f);
#endifFog settings are snapshots:
csharp
#if CLIENT
var weather = Game.LocalScene.TryGetWeatherController();
if (weather?.GetFogSettings() is { } fog)
{
weather.ApplyFogSettings(fog with
{
DepthFogEnable = true,
DepthFogDensity = 0.08f
});
}
#endifFogOfWar is local visual state, not gameplay vision sync:
csharp
#if CLIENT
using System.Drawing;
using GameGraph.NodeSystem;
var weather = Game.LocalScene.TryGetWeatherController();
if (weather?.OpenFogOfWar(true) == true)
{
weather.ApplyFogOfWarSettings(new SceneFogOfWarSettings(
Blend: 0.65f,
OpenSpeed: 4.0f,
Brightness: 0.85f,
FogColor: Color.FromArgb(255, 40, 48, 60),
RangeColor: Color.FromArgb(255, 100, 120, 140)));
weather.SetFogOfWarWeight(8, 12, 0.0f);
weather.RefreshFogOfWar(force: true);
}
#endifLighting Patterns
Use SceneLightingController for main light, point lights, Zone fog/environment parameters, and LightGroup XML presets.
csharp
#if CLIENT
using GameGraph.NodeSystem;
var lighting = Game.LocalScene.TryGetLightingController();
if (lighting?.GetMainLightSettings() is { } mainLight)
{
lighting.ApplyMainLightSettings(mainLight with
{
Brightness = 1.25f,
ShadowIntensity = 0.7f
});
}
#endifEnvironment settings are snapshots:
csharp
#if CLIENT
var lighting = Game.LocalScene.TryGetLightingController();
if (lighting?.GetEnvironmentSettings() is { } environment)
{
lighting.ApplyEnvironmentSettings(environment with
{
BloomWeight = 0.4f,
VignetteEnabled = true,
VignetteIntensity = 0.25f
});
}
#endifLightGroup preset fade:
csharp
#if CLIENT
using GameGraph.NodeSystem;
var lighting = Game.LocalScene.TryGetLightingController();
// Engine preset example. A project map asset normally lives under atmosphere/.
lighting?.StartPresetFade("LightGroup/Daytime.xml", fadeInTime: 1.5f);
#endifUse LoadPreset(...) for immediate XML load and StartPresetFade(...) for smooth runtime transition. The path is a runtime resource path; bundled engine examples use LightGroup/*.xml, while a project-owned atmosphere asset may be addressed with its project resource path (for example atmosphere/dusk.lightgroup, if that asset is available to the runtime). Neither call writes map resources.
Validation
Build both sides so shared code and guards remain valid:
powershell
dotnet build src\GameEntry.csproj -c Client-Debug
dotnet build src\GameEntry.csproj -c Server-DebugFor visible changes:
- Start editor debug or client-only debug for the target project.
- Wait until the target SCE scene is loaded.
- Apply the runtime weather/lighting code.
- Capture a screenshot or use Runtime MCP diagnostics when available.
- Check logs for
nullcontroller handling rather than assuming builtin nodes exist.
Related
docs/systems/SceSceneEnvironmentSystem.mddocs/guides/AtmosphereLightGroup.mddocs/systems/SceneSystem.mddocs/systems/SceneVisionSystem.mddocs/systems/GameGraphOverview.mddocs/systems/MaterialSystem.mddocs/ai/skills/client-scenegraph-game/SKILL.mddocs/ai/skills/gamegraph-materials/SKILL.mddocs/ai/skills/client-only-debug/SKILL.mddocs/ai/skills/sce-preview-verify/SKILL.md