AR Core+Unity中Runtime地形与Water缩放异常问题求助
Hey there, let's dig into why your Terrain and Unity Water Asset are misbehaving when using Lean Touch scaling in your AR Core project, and walk through practical fixes to get them working right.
Why Terrain & Water Asset Break on Scaling
The core issue is that these aren't standard GameObjects—they have specialized internal logic that clashes with Lean Touch's default scaling behavior:
- Terrain's unique structure: Unity's Terrain relies on fixed heightmaps, LOD systems, and world-space coordinate calculations. Directly modifying its
Transform.scalebreaks these internal references, causing the terrain mesh to fail rendering (hence it disappearing). AR Core's spatial anchoring also doesn't play nice with Terrain's non-standard transform setup. - Water Asset's rendering dependencies: Official Unity Water (like URP/HDRP Water 2) ties its wave patterns, reflections, and tiling to world-space coordinates and specific component parameters. Scaling the Transform throws these parameters out of sync with the mesh, leading to visual glitches like stretched waves or broken reflections.
- Lean Touch's default logic: By default, Lean Touch modifies the target's
localScaledirectly—this works for basic meshes, but not for assets with custom rendering or data pipelines like Terrain and Water.
Fixes for Each Asset Type
Fixing Terrain Scaling
Forget scaling the Transform entirely—adjust the Terrain's native size parameters instead:
- Editor-time adjustment: Select your Terrain, head to the
Terrain Settingspanel, and tweakTerrain Width,Terrain Length, andTerrain Heightto set your desired size. - Runtime dynamic scaling: Use code to modify the Terrain's
TerrainData.sizeproperty, and hook this into Lean Touch's scaling events. Example code:using UnityEngine; using Lean.Touch; public class TerrainARScaler : MonoBehaviour { public Terrain targetTerrain; private Vector3 initialTerrainSize; void Start() { if (targetTerrain != null) { initialTerrainSize = targetTerrain.terrainData.size; } LeanTouch.OnScale += OnTerrainScale; } void OnDisable() { LeanTouch.OnScale -= OnTerrainScale; } void OnTerrainScale(LeanFinger finger1, LeanFinger finger2) { if (targetTerrain == null) return; float scaleDelta = LeanGesture.GetScale(finger1, finger2); Vector3 newSize = initialTerrainSize * scaleDelta; // Clamp values to prevent extreme sizes that break rendering newSize = Vector3.Max(newSize, new Vector3(10, 1, 10)); targetTerrain.terrainData.size = newSize; targetTerrain.Flush(); // Force terrain to update visuals } } - Anchor setup: Attach your Terrain as a child to an empty GameObject with your AR Core anchor component. This keeps the Terrain anchored to AR space without scaling the anchor itself.
Fixing Water Asset Scaling
Sync scaling with the Water component's specific parameters instead of just the Transform:
- For URP/HDRP Water 2:
- Avoid scaling the Water GameObject directly. Instead, adjust the
Wave ScaleandTilingproperties in the Water component to match your desired size. - Use code to link Lean Touch's scaling gesture to both the water plane's size and the Water component's parameters:
using UnityEngine; using Lean.Touch; using UnityEngine.Rendering.Universal; // For URP Water 2 public class WaterARScaler : MonoBehaviour { public Water waterComponent; private Vector3 initialPlaneScale; private float initialWaveScale; void Start() { if (waterComponent != null) { initialPlaneScale = transform.localScale; initialWaveScale = waterComponent.WaveScale; } LeanTouch.OnScale += OnWaterScale; } void OnDisable() { LeanTouch.OnScale -= OnWaterScale; } void OnWaterScale(LeanFinger finger1, LeanFinger finger2) { if (waterComponent == null) return; float scaleDelta = LeanGesture.GetScale(finger1, finger2); transform.localScale = initialPlaneScale * scaleDelta; waterComponent.WaveScale = initialWaveScale * scaleDelta; // Optional: Update reflection probe position if used if (waterComponent.ReflectionProbe != null) { waterComponent.ReflectionProbe.transform.position = transform.position; } } }
- Avoid scaling the Water GameObject directly. Instead, adjust the
- Simpler alternative: If the official Water Asset is too finicky, create a basic Plane with a transparent, vertex-animated wave shader. This acts like a standard mesh, so Lean Touch's default scaling will work without glitches.
Universal Lean Touch Setup
Replace Lean Touch's default LeanScale component with a custom script that handles different asset types:
using UnityEngine; using Lean.Touch; public class ARMultiScaler : MonoBehaviour { public GameObject targetObject; private Terrain targetTerrain; private Water targetWater; private Vector3 initialObjectScale; private Vector3 initialTerrainSize; private float initialWaveScale; void Start() { targetTerrain = targetObject.GetComponent<Terrain>(); targetWater = targetObject.GetComponent<Water>(); if (targetTerrain != null) { initialTerrainSize = targetTerrain.terrainData.size; } else if (targetWater != null) { initialObjectScale = targetObject.transform.localScale; initialWaveScale = targetWater.WaveScale; } else { initialObjectScale = targetObject.transform.localScale; } LeanTouch.OnScale += OnScale; } void OnDisable() { LeanTouch.OnScale -= OnScale; } void OnScale(LeanFinger finger1, LeanFinger finger2) { float scaleDelta = LeanGesture.GetScale(finger1, finger2); if (targetTerrain != null) { Vector3 newSize = initialTerrainSize * scaleDelta; newSize = Vector3.Max(newSize, new Vector3(5, 0.5f, 5)); targetTerrain.terrainData.size = newSize; targetTerrain.Flush(); } else if (targetWater != null) { targetObject.transform.localScale = initialObjectScale * scaleDelta; targetWater.WaveScale = initialWaveScale * scaleDelta; } else { targetObject.transform.localScale = initialObjectScale * scaleDelta; } } }
内容的提问来源于stack exchange,提问作者Bosanac95
相关产品推荐
相关产品推荐

