|
@@ -0,0 +1,993 @@
|
|
|
|
|
+using UnityEngine;
|
|
|
|
|
+using TMPro;
|
|
|
|
|
+using System.Collections.Generic;
|
|
|
|
|
+using System.Collections;
|
|
|
|
|
+
|
|
|
|
|
+public class WorldSpaceLocationNames : MonoBehaviour
|
|
|
|
|
+{
|
|
|
|
|
+ [Header("Display Settings")]
|
|
|
|
|
+ public bool showSettlementNames = true;
|
|
|
|
|
+ public bool showForestNames = true;
|
|
|
|
|
+ public bool showLakeNames = true;
|
|
|
|
|
+ public bool showPlainNames = true;
|
|
|
|
|
+ public bool showMountainNames = true;
|
|
|
|
|
+ public bool showRiverNames = true;
|
|
|
|
|
+
|
|
|
|
|
+ [Header("Visual Settings")]
|
|
|
|
|
+ public Color settlementNameColor = Color.white;
|
|
|
|
|
+ public Color forestNameColor = Color.green;
|
|
|
|
|
+ public Color lakeNameColor = Color.cyan;
|
|
|
|
|
+ public Color plainNameColor = Color.yellow;
|
|
|
|
|
+ public Color mountainNameColor = Color.gray;
|
|
|
|
|
+ public Color riverNameColor = Color.blue;
|
|
|
|
|
+
|
|
|
|
|
+ [Header("3D Text Settings")]
|
|
|
|
|
+ public GameObject textPrefab; // TextMeshPro 3D prefab
|
|
|
|
|
+ public float textSize = 72f; // Large size for visibility (was 10f)
|
|
|
|
|
+ public float heightOffset = 0.5f; // Small offset above terrain (0.5 = just above ground)
|
|
|
|
|
+ public bool faceCamera = false; // Disabled by default to allow manual rotation control
|
|
|
|
|
+ public Vector3 fixedRotation = new Vector3(90, 0, 0); // Fixed rotation for text (X=90 for flat text)
|
|
|
|
|
+ public float maxViewDistance = 0f; // Disabled by default (was 100f) - distance culling causes visibility issues
|
|
|
|
|
+
|
|
|
|
|
+ [Header("Rendering Order")]
|
|
|
|
|
+ public string sortingLayerName = "Default"; // Sorting layer for text rendering
|
|
|
|
|
+ public int sortingOrder = 2; // Order in layer (higher = renders on top). Roads are 1, so use 2+
|
|
|
|
|
+ public bool useBuiltInTextMesh = false; // Fallback to Unity's TextMesh if TextMeshPro fails
|
|
|
|
|
+
|
|
|
|
|
+ [Header("Debug")]
|
|
|
|
|
+ public bool debugMode = true;
|
|
|
|
|
+
|
|
|
|
|
+ private List<GameObject> nameObjects = new List<GameObject>();
|
|
|
|
|
+ private GeographicFeatureManager featureManager;
|
|
|
|
|
+ private MapData mapData;
|
|
|
|
|
+ private MapMaker2 mapMaker;
|
|
|
|
|
+ private Camera mainCamera;
|
|
|
|
|
+ private Transform nameContainer;
|
|
|
|
|
+
|
|
|
|
|
+ private void Start()
|
|
|
|
|
+ {
|
|
|
|
|
+ StartCoroutine(InitializeDelayed());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private IEnumerator InitializeDelayed()
|
|
|
|
|
+ {
|
|
|
|
|
+ // Wait for map generation to complete
|
|
|
|
|
+ yield return new WaitForSeconds(1f);
|
|
|
|
|
+
|
|
|
|
|
+ InitializeReferences();
|
|
|
|
|
+ CreateNameContainer();
|
|
|
|
|
+
|
|
|
|
|
+ if (textPrefab == null)
|
|
|
|
|
+ {
|
|
|
|
|
+ CreateDefaultTextPrefab();
|
|
|
|
|
+
|
|
|
|
|
+ // If TextMeshPro setup failed, try built-in TextMesh as fallback
|
|
|
|
|
+ if (textPrefab == null)
|
|
|
|
|
+ {
|
|
|
|
|
+ useBuiltInTextMesh = true;
|
|
|
|
|
+ CreateFallbackTextPrefab();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ yield return new WaitForSeconds(0.5f);
|
|
|
|
|
+ RefreshLocationNames();
|
|
|
|
|
+
|
|
|
|
|
+ // Automatically apply visibility fixes at startup
|
|
|
|
|
+ yield return new WaitForSeconds(0.1f); // Small delay to ensure objects are created
|
|
|
|
|
+ ApplyVisibilityFixesAtStartup();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void InitializeReferences()
|
|
|
|
|
+ {
|
|
|
|
|
+ featureManager = FindFirstObjectByType<GeographicFeatureManager>();
|
|
|
|
|
+
|
|
|
|
|
+ // If GeographicFeatureManager isn't found, try to find it by name
|
|
|
|
|
+ if (featureManager == null)
|
|
|
|
|
+ {
|
|
|
|
|
+ GameObject gfmObject = GameObject.Find("GeographicFeatureManager");
|
|
|
|
|
+ if (gfmObject != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ featureManager = gfmObject.GetComponent<GeographicFeatureManager>();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ mapMaker = FindFirstObjectByType<MapMaker2>();
|
|
|
|
|
+ mainCamera = Camera.main ?? FindFirstObjectByType<Camera>();
|
|
|
|
|
+
|
|
|
|
|
+ if (mapMaker != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ mapData = mapMaker.GetMapData();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (debugMode)
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.Log($"WorldSpaceLocationNames: Initialized");
|
|
|
|
|
+ Debug.Log($" - FeatureManager: {(featureManager != null ? $"Found ({featureManager.GeographicFeatures.Count} features)" : "NULL")}");
|
|
|
|
|
+ Debug.Log($" - MapData: {(mapData != null ? $"Found ({mapData.Width}x{mapData.Height})" : "NULL")}");
|
|
|
|
|
+ Debug.Log($" - Camera: {(mainCamera != null ? "Found" : "NULL")}");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void CreateNameContainer()
|
|
|
|
|
+ {
|
|
|
|
|
+ GameObject containerObj = new GameObject("LocationNameContainer");
|
|
|
|
|
+ containerObj.transform.parent = transform;
|
|
|
|
|
+ containerObj.transform.localPosition = Vector3.zero;
|
|
|
|
|
+ containerObj.transform.localRotation = Quaternion.identity;
|
|
|
|
|
+ containerObj.transform.localScale = Vector3.one;
|
|
|
|
|
+ nameContainer = containerObj.transform;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void CreateDefaultTextPrefab()
|
|
|
|
|
+ {
|
|
|
|
|
+ // Create a simple TextMeshPro 3D prefab if none is assigned
|
|
|
|
|
+ GameObject prefab = new GameObject("DefaultLocationNameText");
|
|
|
|
|
+
|
|
|
|
|
+ TextMeshPro tmp = prefab.AddComponent<TextMeshPro>();
|
|
|
|
|
+ tmp.text = "Sample Text";
|
|
|
|
|
+ tmp.fontSize = textSize; // Use the large font size (72f)
|
|
|
|
|
+ tmp.color = Color.white;
|
|
|
|
|
+ tmp.alignment = TextAlignmentOptions.Center;
|
|
|
|
|
+ tmp.autoSizeTextContainer = false; // Disable auto-sizing based on user findings
|
|
|
|
|
+
|
|
|
|
|
+ // Make sure the text has proper bounds - use larger size based on user findings
|
|
|
|
|
+ tmp.rectTransform.sizeDelta = new Vector2(40, 20);
|
|
|
|
|
+
|
|
|
|
|
+ // Try to assign a font asset - this is crucial for visibility
|
|
|
|
|
+ TMP_FontAsset fontAsset = null;
|
|
|
|
|
+
|
|
|
|
|
+ // First try to get the default font from TMP Settings
|
|
|
|
|
+ if (TMP_Settings.defaultFontAsset != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ fontAsset = TMP_Settings.defaultFontAsset;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ // Try to load the default TMP font from Resources
|
|
|
|
|
+ fontAsset = Resources.Load<TMP_FontAsset>("LiberationSans SDF");
|
|
|
|
|
+ if (fontAsset == null)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Try alternative resource paths
|
|
|
|
|
+ fontAsset = Resources.Load<TMP_FontAsset>("Fonts & Materials/LiberationSans SDF");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (fontAsset != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ tmp.font = fontAsset;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ // If no TMP font is found, we'll rely on the default behavior
|
|
|
|
|
+ Debug.LogWarning("WorldSpaceLocationNames: No TMP_FontAsset found, using default font");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Set up the material properly
|
|
|
|
|
+ MeshRenderer renderer = prefab.GetComponent<MeshRenderer>();
|
|
|
|
|
+ if (renderer != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Ensure renderer is enabled
|
|
|
|
|
+ renderer.enabled = true;
|
|
|
|
|
+ renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
|
|
|
|
|
+ renderer.receiveShadows = false;
|
|
|
|
|
+
|
|
|
|
|
+ // Try to use the font's material if available
|
|
|
|
|
+ if (tmp.font != null && tmp.font.material != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ renderer.material = tmp.font.material;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ // Create a basic material for TextMeshPro with fallbacks
|
|
|
|
|
+ Material tmpMaterial = null;
|
|
|
|
|
+
|
|
|
|
|
+ if (Shader.Find("TextMeshPro/Distance Field") != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ tmpMaterial = new Material(Shader.Find("TextMeshPro/Distance Field"));
|
|
|
|
|
+ tmpMaterial.color = Color.white;
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (Shader.Find("TextMeshPro/Mobile/Distance Field") != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ tmpMaterial = new Material(Shader.Find("TextMeshPro/Mobile/Distance Field"));
|
|
|
|
|
+ tmpMaterial.color = Color.white;
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (Shader.Find("GUI/Text Shader") != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ tmpMaterial = new Material(Shader.Find("GUI/Text Shader"));
|
|
|
|
|
+ tmpMaterial.color = Color.white;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ // Last resort - simple unlit color
|
|
|
|
|
+ tmpMaterial = new Material(Shader.Find("Unlit/Color"));
|
|
|
|
|
+ tmpMaterial.color = Color.white;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (tmpMaterial != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ renderer.material = tmpMaterial;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ textPrefab = prefab;
|
|
|
|
|
+
|
|
|
|
|
+ if (debugMode)
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.Log($"WorldSpaceLocationNames: Created default TextMeshPro prefab");
|
|
|
|
|
+ Debug.Log($" - Font: {(tmp.font != null ? tmp.font.name : "NULL")}");
|
|
|
|
|
+ Debug.Log($" - Material: {(renderer.material != null ? renderer.material.name : "NULL")}");
|
|
|
|
|
+ Debug.Log($" - Shader: {(renderer.material != null && renderer.material.shader != null ? renderer.material.shader.name : "NULL")}");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void CreateFallbackTextPrefab()
|
|
|
|
|
+ {
|
|
|
|
|
+ // Create a simple Unity TextMesh 3D prefab as fallback
|
|
|
|
|
+ GameObject prefab = new GameObject("FallbackLocationNameText");
|
|
|
|
|
+
|
|
|
|
|
+ TextMesh textMesh = prefab.AddComponent<TextMesh>();
|
|
|
|
|
+ textMesh.text = "Sample Text";
|
|
|
|
|
+ textMesh.fontSize = (int)textSize;
|
|
|
|
|
+ textMesh.color = Color.white;
|
|
|
|
|
+ textMesh.anchor = TextAnchor.MiddleCenter;
|
|
|
|
|
+ textMesh.alignment = TextAlignment.Center;
|
|
|
|
|
+
|
|
|
|
|
+ // Set up the mesh renderer with a simple material
|
|
|
|
|
+ MeshRenderer renderer = prefab.GetComponent<MeshRenderer>();
|
|
|
|
|
+ if (renderer != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Use Unity's default font material
|
|
|
|
|
+ Material fontMaterial = Resources.GetBuiltinResource<Material>("Default-Material");
|
|
|
|
|
+ if (fontMaterial != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ renderer.material = fontMaterial;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ // Create a simple unlit material
|
|
|
|
|
+ Material simpleMaterial = new Material(Shader.Find("Unlit/Color"));
|
|
|
|
|
+ simpleMaterial.color = Color.white;
|
|
|
|
|
+ renderer.material = simpleMaterial;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ textPrefab = prefab;
|
|
|
|
|
+
|
|
|
|
|
+ if (debugMode) Debug.Log("WorldSpaceLocationNames: Created fallback Unity TextMesh prefab");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public void RefreshLocationNames()
|
|
|
|
|
+ {
|
|
|
|
|
+ ClearAllNames();
|
|
|
|
|
+
|
|
|
|
|
+ if (mapData == null || textPrefab == null)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (debugMode) Debug.LogWarning($"WorldSpaceLocationNames: Cannot refresh - mapData: {(mapData != null ? "OK" : "NULL")}, textPrefab: {(textPrefab != null ? "OK" : "NULL")}");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (debugMode) Debug.Log("WorldSpaceLocationNames: Refreshing location names...");
|
|
|
|
|
+
|
|
|
|
|
+ // Display settlement names
|
|
|
|
|
+ if (showSettlementNames)
|
|
|
|
|
+ {
|
|
|
|
|
+ DisplaySettlementNames();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Display geographic feature names
|
|
|
|
|
+ if (featureManager != null && featureManager.GeographicFeatures != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ foreach (var feature in featureManager.GeographicFeatures)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (ShouldDisplayFeature(feature))
|
|
|
|
|
+ {
|
|
|
|
|
+ CreateFeatureName(feature);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (debugMode)
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.Log($"WorldSpaceLocationNames: Created {nameObjects.Count} name objects");
|
|
|
|
|
+
|
|
|
|
|
+ // Debug camera information
|
|
|
|
|
+ if (mainCamera != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.Log($" - Camera position: {mainCamera.transform.position}");
|
|
|
|
|
+ Debug.Log($" - Camera rotation: {mainCamera.transform.rotation.eulerAngles}");
|
|
|
|
|
+ Debug.Log($" - Camera far clip: {mainCamera.farClipPlane}");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Debug first few name objects
|
|
|
|
|
+ for (int i = 0; i < Mathf.Min(3, nameObjects.Count); i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (nameObjects[i] != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.Log($" - Name object {i}: '{nameObjects[i].name}' at {nameObjects[i].transform.position}");
|
|
|
|
|
+
|
|
|
|
|
+ // Check if it has TextMeshPro
|
|
|
|
|
+ TextMeshPro tmp = nameObjects[i].GetComponent<TextMeshPro>();
|
|
|
|
|
+ if (tmp != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.Log($" - TMP text: '{tmp.text}', size: {tmp.fontSize}, bounds: {tmp.bounds}");
|
|
|
|
|
+ Debug.Log($" - TMP renderer enabled: {tmp.renderer.enabled}");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Check distance to camera
|
|
|
|
|
+ if (mainCamera != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ float distance = Vector3.Distance(mainCamera.transform.position, nameObjects[i].transform.position);
|
|
|
|
|
+ Debug.Log($" - Distance to camera: {distance:F2}");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void DisplaySettlementNames()
|
|
|
|
|
+ {
|
|
|
|
|
+ var settlements = mapData.GetAllSettlements();
|
|
|
|
|
+ if (debugMode) Debug.Log($"WorldSpaceLocationNames: Creating {settlements.Count} settlement names");
|
|
|
|
|
+
|
|
|
|
|
+ foreach (var settlement in settlements)
|
|
|
|
|
+ {
|
|
|
|
|
+ CreateSettlementName(settlement);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private bool ShouldDisplayFeature(GeographicFeature feature)
|
|
|
|
|
+ {
|
|
|
|
|
+ switch (feature.type)
|
|
|
|
|
+ {
|
|
|
|
|
+ case GeographicFeatureType.Forest:
|
|
|
|
|
+ return showForestNames;
|
|
|
|
|
+ case GeographicFeatureType.Lake:
|
|
|
|
|
+ return showLakeNames;
|
|
|
|
|
+ case GeographicFeatureType.Plain:
|
|
|
|
|
+ return showPlainNames;
|
|
|
|
|
+ case GeographicFeatureType.Mountain:
|
|
|
|
|
+ return showMountainNames;
|
|
|
|
|
+ case GeographicFeatureType.River:
|
|
|
|
|
+ return showRiverNames;
|
|
|
|
|
+ default:
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void CreateSettlementName(Settlement settlement)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Position text directly at the settlement location with a small height offset
|
|
|
|
|
+ Vector3 worldPosition = new Vector3(settlement.position.x, heightOffset, settlement.position.y);
|
|
|
|
|
+ Color color = settlementNameColor;
|
|
|
|
|
+ float fontSize = settlement.Type == SettlementType.Town ? textSize * 1.2f : textSize;
|
|
|
|
|
+
|
|
|
|
|
+ GameObject nameObj = CreateNameObject(settlement.name, worldPosition, color, fontSize);
|
|
|
|
|
+
|
|
|
|
|
+ if (debugMode)
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.Log($"WorldSpaceLocationNames: Created settlement name '{settlement.name}' at {worldPosition}");
|
|
|
|
|
+ Debug.Log($" - Settlement position: {settlement.position}");
|
|
|
|
|
+ Debug.Log($" - GameObject position: {nameObj.transform.position}");
|
|
|
|
|
+ Debug.Log($" - Container position: {nameContainer.position}");
|
|
|
|
|
+ Debug.Log($" - Text height: {heightOffset} (directly on terrain)");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void CreateFeatureName(GeographicFeature feature)
|
|
|
|
|
+ {
|
|
|
|
|
+ Vector2Int featureCenter = feature.GetCenterPosition();
|
|
|
|
|
+
|
|
|
|
|
+ // Position text directly at the feature center with a small height offset
|
|
|
|
|
+ Vector3 worldPosition = new Vector3(featureCenter.x, heightOffset, featureCenter.y);
|
|
|
|
|
+ Color color = GetFeatureColor(feature.type);
|
|
|
|
|
+ float fontSize = GetFeatureFontSize(feature.type);
|
|
|
|
|
+
|
|
|
|
|
+ GameObject nameObj = CreateNameObject(feature.name, worldPosition, color, fontSize);
|
|
|
|
|
+
|
|
|
|
|
+ // Add opacity for undiscovered features
|
|
|
|
|
+ if (!feature.isDiscovered)
|
|
|
|
|
+ {
|
|
|
|
|
+ TextMeshPro tmp = nameObj.GetComponent<TextMeshPro>();
|
|
|
|
|
+ if (tmp != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ Color c = tmp.color;
|
|
|
|
|
+ c.a = 0.6f;
|
|
|
|
|
+ tmp.color = c;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (debugMode)
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.Log($"WorldSpaceLocationNames: Created feature name '{feature.name}' at {worldPosition}");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private GameObject CreateNameObject(string text, Vector3 position, Color color, float fontSize)
|
|
|
|
|
+ {
|
|
|
|
|
+ GameObject nameObj = Instantiate(textPrefab, nameContainer);
|
|
|
|
|
+ nameObj.name = $"LocationName_{text}";
|
|
|
|
|
+
|
|
|
|
|
+ // Set position after instantiation to ensure it's not reset
|
|
|
|
|
+ nameObj.transform.position = position;
|
|
|
|
|
+ nameObj.transform.rotation = Quaternion.identity;
|
|
|
|
|
+
|
|
|
|
|
+ // Make sure the object is on a visible layer
|
|
|
|
|
+ nameObj.layer = 0; // Default layer
|
|
|
|
|
+
|
|
|
|
|
+ // Try TextMeshPro first
|
|
|
|
|
+ TextMeshPro tmp = nameObj.GetComponent<TextMeshPro>();
|
|
|
|
|
+ if (tmp != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ tmp.text = text;
|
|
|
|
|
+ tmp.color = color;
|
|
|
|
|
+ tmp.fontSize = Mathf.Max(fontSize, 72f); // Force minimum 72pt size for visibility
|
|
|
|
|
+ tmp.alignment = TextAlignmentOptions.Center;
|
|
|
|
|
+
|
|
|
|
|
+ // Based on user findings: disable auto-sizing and set manual size
|
|
|
|
|
+ tmp.autoSizeTextContainer = false; // Disable auto-sizing
|
|
|
|
|
+ tmp.rectTransform.sizeDelta = new Vector2(200, 50); // Much larger text area
|
|
|
|
|
+
|
|
|
|
|
+ // Force the text to update and generate mesh
|
|
|
|
|
+ tmp.ForceMeshUpdate();
|
|
|
|
|
+
|
|
|
|
|
+ // Ensure proper material setup and renderer activation
|
|
|
|
|
+ if (tmp.renderer != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ tmp.renderer.enabled = true; // Explicitly enable renderer
|
|
|
|
|
+ tmp.renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
|
|
|
|
|
+ tmp.renderer.receiveShadows = false;
|
|
|
|
|
+
|
|
|
|
|
+ // Set sorting layer to render above roads and map tiles
|
|
|
|
|
+ tmp.renderer.sortingLayerName = sortingLayerName;
|
|
|
|
|
+ tmp.renderer.sortingOrder = sortingOrder;
|
|
|
|
|
+
|
|
|
|
|
+ // Force material assignment if missing
|
|
|
|
|
+ if (tmp.renderer.material == null || tmp.renderer.material.shader == null)
|
|
|
|
|
+ {
|
|
|
|
|
+ Material tmpMaterial = null;
|
|
|
|
|
+
|
|
|
|
|
+ // Try to find a working TextMeshPro shader
|
|
|
|
|
+ if (Shader.Find("TextMeshPro/Distance Field") != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ tmpMaterial = new Material(Shader.Find("TextMeshPro/Distance Field"));
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (Shader.Find("TextMeshPro/Mobile/Distance Field") != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ tmpMaterial = new Material(Shader.Find("TextMeshPro/Mobile/Distance Field"));
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (Shader.Find("GUI/Text Shader") != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ tmpMaterial = new Material(Shader.Find("GUI/Text Shader"));
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ // Last resort - unlit color
|
|
|
|
|
+ tmpMaterial = new Material(Shader.Find("Unlit/Color"));
|
|
|
|
|
+ tmpMaterial.color = color;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (tmpMaterial != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ tmp.renderer.material = tmpMaterial;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Force another mesh update after material assignment
|
|
|
|
|
+ tmp.ForceMeshUpdate();
|
|
|
|
|
+
|
|
|
|
|
+ if (debugMode)
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.Log($"WorldSpaceLocationNames: TextMeshPro setup - Text: '{text}', Font Size: {tmp.fontSize}, Color: {color}");
|
|
|
|
|
+ Debug.Log($" - Position: {nameObj.transform.position}");
|
|
|
|
|
+ Debug.Log($" - Renderer enabled: {tmp.renderer.enabled}");
|
|
|
|
|
+ Debug.Log($" - Material: {(tmp.renderer.material != null ? tmp.renderer.material.name : "NULL")}");
|
|
|
|
|
+ Debug.Log($" - Shader: {(tmp.renderer.material != null && tmp.renderer.material.shader != null ? tmp.renderer.material.shader.name : "NULL")}");
|
|
|
|
|
+ Debug.Log($" - Bounds: {tmp.bounds}");
|
|
|
|
|
+ Debug.Log($" - Auto-size enabled: {tmp.autoSizeTextContainer}");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ // Fallback to Unity TextMesh
|
|
|
|
|
+ TextMesh textMesh = nameObj.GetComponent<TextMesh>();
|
|
|
|
|
+ if (textMesh != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ textMesh.text = text;
|
|
|
|
|
+ textMesh.color = color;
|
|
|
|
|
+ textMesh.fontSize = (int)Mathf.Max(fontSize, 72f); // Force minimum 72pt size for visibility
|
|
|
|
|
+ textMesh.anchor = TextAnchor.MiddleCenter;
|
|
|
|
|
+ textMesh.alignment = TextAlignment.Center;
|
|
|
|
|
+
|
|
|
|
|
+ // Ensure renderer is enabled
|
|
|
|
|
+ MeshRenderer meshRenderer = nameObj.GetComponent<MeshRenderer>();
|
|
|
|
|
+ if (meshRenderer != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ meshRenderer.enabled = true; // Explicitly enable renderer
|
|
|
|
|
+ meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
|
|
|
|
|
+ meshRenderer.receiveShadows = false;
|
|
|
|
|
+
|
|
|
|
|
+ // Set sorting layer to render above roads and map tiles
|
|
|
|
|
+ meshRenderer.sortingLayerName = sortingLayerName;
|
|
|
|
|
+ meshRenderer.sortingOrder = sortingOrder;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (debugMode)
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.Log($"WorldSpaceLocationNames: Unity TextMesh setup - Text: '{text}', Font Size: {textMesh.fontSize}, Color: {color}");
|
|
|
|
|
+ Debug.Log($" - Position: {nameObj.transform.position}");
|
|
|
|
|
+ Debug.Log($" - Renderer enabled: {(meshRenderer != null ? meshRenderer.enabled : false)}");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Use a more visible scale
|
|
|
|
|
+ nameObj.transform.localScale = Vector3.one;
|
|
|
|
|
+
|
|
|
|
|
+ // Set rotation based on settings
|
|
|
|
|
+ if (faceCamera)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Add camera-facing behavior if enabled
|
|
|
|
|
+ LookAtCamera lookAt = nameObj.GetComponent<LookAtCamera>();
|
|
|
|
|
+ if (lookAt == null)
|
|
|
|
|
+ {
|
|
|
|
|
+ lookAt = nameObj.AddComponent<LookAtCamera>();
|
|
|
|
|
+ }
|
|
|
|
|
+ lookAt.targetCamera = mainCamera;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ // Use fixed rotation for better control
|
|
|
|
|
+ nameObj.transform.rotation = Quaternion.Euler(fixedRotation);
|
|
|
|
|
+
|
|
|
|
|
+ if (debugMode)
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.Log($" - Applied fixed rotation: {fixedRotation}");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Distance-based visibility disabled by default (causes visibility issues)
|
|
|
|
|
+ // Only add if maxViewDistance is explicitly set > 0
|
|
|
|
|
+ if (maxViewDistance > 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ DistanceBasedVisibility visibility = nameObj.GetComponent<DistanceBasedVisibility>();
|
|
|
|
|
+ if (visibility == null)
|
|
|
|
|
+ {
|
|
|
|
|
+ visibility = nameObj.AddComponent<DistanceBasedVisibility>();
|
|
|
|
|
+ }
|
|
|
|
|
+ visibility.maxDistance = maxViewDistance;
|
|
|
|
|
+ visibility.targetCamera = mainCamera;
|
|
|
|
|
+
|
|
|
|
|
+ if (debugMode)
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.Log($" - Added distance visibility with max distance: {maxViewDistance}");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (debugMode)
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.Log($" - Distance-based visibility disabled (maxViewDistance = {maxViewDistance})");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ nameObjects.Add(nameObj);
|
|
|
|
|
+ return nameObj;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Color GetFeatureColor(GeographicFeatureType type)
|
|
|
|
|
+ {
|
|
|
|
|
+ switch (type)
|
|
|
|
|
+ {
|
|
|
|
|
+ case GeographicFeatureType.Forest:
|
|
|
|
|
+ return forestNameColor;
|
|
|
|
|
+ case GeographicFeatureType.Lake:
|
|
|
|
|
+ return lakeNameColor;
|
|
|
|
|
+ case GeographicFeatureType.Plain:
|
|
|
|
|
+ return plainNameColor;
|
|
|
|
|
+ case GeographicFeatureType.Mountain:
|
|
|
|
|
+ return mountainNameColor;
|
|
|
|
|
+ case GeographicFeatureType.River:
|
|
|
|
|
+ return riverNameColor;
|
|
|
|
|
+ default:
|
|
|
|
|
+ return Color.white;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private float GetFeatureFontSize(GeographicFeatureType type)
|
|
|
|
|
+ {
|
|
|
|
|
+ float baseSize = textSize;
|
|
|
|
|
+ switch (type)
|
|
|
|
|
+ {
|
|
|
|
|
+ case GeographicFeatureType.Mountain:
|
|
|
|
|
+ return baseSize * 1.1f;
|
|
|
|
|
+ case GeographicFeatureType.Forest:
|
|
|
|
|
+ case GeographicFeatureType.Lake:
|
|
|
|
|
+ return baseSize;
|
|
|
|
|
+ case GeographicFeatureType.Plain:
|
|
|
|
|
+ case GeographicFeatureType.River:
|
|
|
|
|
+ return baseSize * 0.9f;
|
|
|
|
|
+ default:
|
|
|
|
|
+ return baseSize;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void ClearAllNames()
|
|
|
|
|
+ {
|
|
|
|
|
+ if (debugMode && nameObjects.Count > 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.Log($"WorldSpaceLocationNames: Clearing {nameObjects.Count} existing name objects");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ foreach (var nameObj in nameObjects)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (nameObj != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ DestroyImmediate(nameObj);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ nameObjects.Clear();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Public methods for toggling different name types
|
|
|
|
|
+ public void ToggleSettlementNames(bool show)
|
|
|
|
|
+ {
|
|
|
|
|
+ showSettlementNames = show;
|
|
|
|
|
+ RefreshLocationNames();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public void ToggleForestNames(bool show)
|
|
|
|
|
+ {
|
|
|
|
|
+ showForestNames = show;
|
|
|
|
|
+ RefreshLocationNames();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public void ToggleLakeNames(bool show)
|
|
|
|
|
+ {
|
|
|
|
|
+ showLakeNames = show;
|
|
|
|
|
+ RefreshLocationNames();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public void TogglePlainNames(bool show)
|
|
|
|
|
+ {
|
|
|
|
|
+ showPlainNames = show;
|
|
|
|
|
+ RefreshLocationNames();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public void ToggleMountainNames(bool show)
|
|
|
|
|
+ {
|
|
|
|
|
+ showMountainNames = show;
|
|
|
|
|
+ RefreshLocationNames();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public void ToggleRiverNames(bool show)
|
|
|
|
|
+ {
|
|
|
|
|
+ showRiverNames = show;
|
|
|
|
|
+ RefreshLocationNames();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ [ContextMenu("Refresh Names")]
|
|
|
|
|
+ public void RefreshNamesManual()
|
|
|
|
|
+ {
|
|
|
|
|
+ RefreshLocationNames();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void OnDestroy()
|
|
|
|
|
+ {
|
|
|
|
|
+ ClearAllNames();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Test method to create a simple text object at camera position for debugging
|
|
|
|
|
+ [ContextMenu("Create Test Text")]
|
|
|
|
|
+ public void CreateTestText()
|
|
|
|
|
+ {
|
|
|
|
|
+ if (mainCamera == null)
|
|
|
|
|
+ {
|
|
|
|
|
+ mainCamera = Camera.main ?? FindFirstObjectByType<Camera>();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (textPrefab == null)
|
|
|
|
|
+ {
|
|
|
|
|
+ CreateDefaultTextPrefab();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (nameContainer == null)
|
|
|
|
|
+ {
|
|
|
|
|
+ CreateNameContainer();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (mainCamera != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Create test text in front of camera at terrain level
|
|
|
|
|
+ Vector3 testPosition = mainCamera.transform.position + mainCamera.transform.forward * 10f;
|
|
|
|
|
+ testPosition.y = heightOffset; // Same height as location names (on terrain)
|
|
|
|
|
+
|
|
|
|
|
+ GameObject testObj = CreateNameObject("TEST TEXT", testPosition, Color.yellow, textSize);
|
|
|
|
|
+
|
|
|
|
|
+ Debug.Log($"Created test text at {testPosition}");
|
|
|
|
|
+ Debug.Log($"Camera is at {mainCamera.transform.position}");
|
|
|
|
|
+ Debug.Log($"Distance: {Vector3.Distance(mainCamera.transform.position, testPosition):F2}");
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.LogError("No camera found for test text creation");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Refresh all location names from context menu
|
|
|
|
|
+ [ContextMenu("Refresh Location Names")]
|
|
|
|
|
+ public void ForceRefreshLocationNames()
|
|
|
|
|
+ {
|
|
|
|
|
+ RefreshLocationNames();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Remove all LookAtCamera components to allow manual rotation control
|
|
|
|
|
+ [ContextMenu("Remove Camera Facing")]
|
|
|
|
|
+ public void RemoveCameraFacing()
|
|
|
|
|
+ {
|
|
|
|
|
+ foreach (var nameObj in nameObjects)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (nameObj != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ LookAtCamera lookAt = nameObj.GetComponent<LookAtCamera>();
|
|
|
|
|
+ if (lookAt != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ DestroyImmediate(lookAt);
|
|
|
|
|
+ // Apply fixed rotation
|
|
|
|
|
+ nameObj.transform.rotation = Quaternion.Euler(fixedRotation);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Also disable face camera for future objects
|
|
|
|
|
+ faceCamera = false;
|
|
|
|
|
+
|
|
|
|
|
+ Debug.Log($"Removed LookAtCamera components from {nameObjects.Count} objects and applied fixed rotation: {fixedRotation}");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Apply all the manual fixes you discovered automatically
|
|
|
|
|
+ [ContextMenu("Fix Text Visibility")]
|
|
|
|
|
+ public void FixTextVisibility()
|
|
|
|
|
+ {
|
|
|
|
|
+ int fixedCount = 0;
|
|
|
|
|
+
|
|
|
|
|
+ foreach (var nameObj in nameObjects)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (nameObj != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Remove distance-based visibility component
|
|
|
|
|
+ DistanceBasedVisibility distanceVis = nameObj.GetComponent<DistanceBasedVisibility>();
|
|
|
|
|
+ if (distanceVis != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ DestroyImmediate(distanceVis);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Remove LookAtCamera component
|
|
|
|
|
+ LookAtCamera lookAt = nameObj.GetComponent<LookAtCamera>();
|
|
|
|
|
+ if (lookAt != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ DestroyImmediate(lookAt);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Apply fixed rotation
|
|
|
|
|
+ nameObj.transform.rotation = Quaternion.Euler(fixedRotation);
|
|
|
|
|
+
|
|
|
|
|
+ // Fix TextMeshPro settings
|
|
|
|
|
+ TextMeshPro tmp = nameObj.GetComponent<TextMeshPro>();
|
|
|
|
|
+ if (tmp != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Ensure renderer is enabled
|
|
|
|
|
+ if (tmp.renderer != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ tmp.renderer.enabled = true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Set proper font size and disable auto-sizing
|
|
|
|
|
+ tmp.fontSize = textSize; // Use the large size (72f)
|
|
|
|
|
+ tmp.autoSizeTextContainer = false;
|
|
|
|
|
+ tmp.rectTransform.sizeDelta = new Vector2(200, 50);
|
|
|
|
|
+
|
|
|
|
|
+ // Force mesh update
|
|
|
|
|
+ tmp.ForceMeshUpdate();
|
|
|
|
|
+
|
|
|
|
|
+ fixedCount++;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Fix Unity TextMesh if used instead
|
|
|
|
|
+ TextMesh textMesh = nameObj.GetComponent<TextMesh>();
|
|
|
|
|
+ if (textMesh != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ MeshRenderer meshRenderer = nameObj.GetComponent<MeshRenderer>();
|
|
|
|
|
+ if (meshRenderer != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ meshRenderer.enabled = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ textMesh.fontSize = (int)textSize;
|
|
|
|
|
+ fixedCount++;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Disable face camera and distance culling for future objects
|
|
|
|
|
+ faceCamera = false;
|
|
|
|
|
+ maxViewDistance = 0f;
|
|
|
|
|
+
|
|
|
|
|
+ Debug.Log($"Fixed visibility settings for {fixedCount} text objects");
|
|
|
|
|
+ Debug.Log($"- Removed distance-based visibility components");
|
|
|
|
|
+ Debug.Log($"- Removed LookAtCamera components");
|
|
|
|
|
+ Debug.Log($"- Enabled mesh renderers");
|
|
|
|
|
+ Debug.Log($"- Set font size to {textSize}");
|
|
|
|
|
+ Debug.Log($"- Applied fixed rotation: {fixedRotation}");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Automatically apply visibility fixes at startup (no manual interaction needed)
|
|
|
|
|
+ private void ApplyVisibilityFixesAtStartup()
|
|
|
|
|
+ {
|
|
|
|
|
+ if (debugMode)
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.Log("WorldSpaceLocationNames: Applying automatic visibility fixes at startup...");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ int fixedCount = 0;
|
|
|
|
|
+
|
|
|
|
|
+ foreach (var nameObj in nameObjects)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (nameObj != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Remove distance-based visibility component
|
|
|
|
|
+ DistanceBasedVisibility distanceVis = nameObj.GetComponent<DistanceBasedVisibility>();
|
|
|
|
|
+ if (distanceVis != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ DestroyImmediate(distanceVis);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Remove LookAtCamera component
|
|
|
|
|
+ LookAtCamera lookAt = nameObj.GetComponent<LookAtCamera>();
|
|
|
|
|
+ if (lookAt != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ DestroyImmediate(lookAt);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Apply fixed rotation
|
|
|
|
|
+ nameObj.transform.rotation = Quaternion.Euler(fixedRotation);
|
|
|
|
|
+
|
|
|
|
|
+ // Fix TextMeshPro settings
|
|
|
|
|
+ TextMeshPro tmp = nameObj.GetComponent<TextMeshPro>();
|
|
|
|
|
+ if (tmp != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Ensure renderer is enabled
|
|
|
|
|
+ if (tmp.renderer != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ tmp.renderer.enabled = true;
|
|
|
|
|
+
|
|
|
|
|
+ // Set sorting layer to render above roads
|
|
|
|
|
+ tmp.renderer.sortingLayerName = sortingLayerName;
|
|
|
|
|
+ tmp.renderer.sortingOrder = sortingOrder;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // FORCE the font size to be large - this was the main issue
|
|
|
|
|
+ tmp.fontSize = Mathf.Max(textSize, 72f); // Ensure minimum 72pt size
|
|
|
|
|
+ tmp.autoSizeTextContainer = false;
|
|
|
|
|
+ tmp.rectTransform.sizeDelta = new Vector2(200, 50);
|
|
|
|
|
+
|
|
|
|
|
+ // Force mesh update
|
|
|
|
|
+ tmp.ForceMeshUpdate();
|
|
|
|
|
+
|
|
|
|
|
+ if (debugMode)
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.Log($" - Fixed text '{tmp.text}': fontSize={tmp.fontSize}, renderer enabled={tmp.renderer.enabled}");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ fixedCount++;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Fix Unity TextMesh if used instead
|
|
|
|
|
+ TextMesh textMesh = nameObj.GetComponent<TextMesh>();
|
|
|
|
|
+ if (textMesh != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ MeshRenderer meshRenderer = nameObj.GetComponent<MeshRenderer>();
|
|
|
|
|
+ if (meshRenderer != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ meshRenderer.enabled = true;
|
|
|
|
|
+
|
|
|
|
|
+ // Set sorting layer to render above roads
|
|
|
|
|
+ meshRenderer.sortingLayerName = sortingLayerName;
|
|
|
|
|
+ meshRenderer.sortingOrder = sortingOrder;
|
|
|
|
|
+ }
|
|
|
|
|
+ textMesh.fontSize = (int)Mathf.Max(textSize, 72f);
|
|
|
|
|
+ fixedCount++;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Ensure settings are correct for future objects
|
|
|
|
|
+ faceCamera = false;
|
|
|
|
|
+ maxViewDistance = 0f;
|
|
|
|
|
+
|
|
|
|
|
+ if (debugMode)
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.Log($"WorldSpaceLocationNames: Automatically fixed {fixedCount} text objects at startup");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Fix sorting order for existing text to render above roads
|
|
|
|
|
+ [ContextMenu("Fix Text Sorting Order")]
|
|
|
|
|
+ public void FixTextSortingOrder()
|
|
|
|
|
+ {
|
|
|
|
|
+ int fixedCount = 0;
|
|
|
|
|
+
|
|
|
|
|
+ foreach (var nameObj in nameObjects)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (nameObj != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Fix TextMeshPro sorting
|
|
|
|
|
+ TextMeshPro tmp = nameObj.GetComponent<TextMeshPro>();
|
|
|
|
|
+ if (tmp != null && tmp.renderer != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ tmp.renderer.sortingLayerName = sortingLayerName;
|
|
|
|
|
+ tmp.renderer.sortingOrder = sortingOrder;
|
|
|
|
|
+ fixedCount++;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Fix Unity TextMesh sorting
|
|
|
|
|
+ TextMesh textMesh = nameObj.GetComponent<TextMesh>();
|
|
|
|
|
+ if (textMesh != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ MeshRenderer meshRenderer = nameObj.GetComponent<MeshRenderer>();
|
|
|
|
|
+ if (meshRenderer != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ meshRenderer.sortingLayerName = sortingLayerName;
|
|
|
|
|
+ meshRenderer.sortingOrder = sortingOrder;
|
|
|
|
|
+ fixedCount++;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Debug.Log($"Fixed sorting order for {fixedCount} text objects");
|
|
|
|
|
+ Debug.Log($"- Sorting Layer: {sortingLayerName}");
|
|
|
|
|
+ Debug.Log($"- Sorting Order: {sortingOrder} (roads are 1, so text should be 2+)");
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Helper component to make text face the camera
|
|
|
|
|
+public class LookAtCamera : MonoBehaviour
|
|
|
|
|
+{
|
|
|
|
|
+ public Camera targetCamera;
|
|
|
|
|
+
|
|
|
|
|
+ private void Update()
|
|
|
|
|
+ {
|
|
|
|
|
+ if (targetCamera != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Make the text face the camera without flipping
|
|
|
|
|
+ Vector3 directionToCamera = targetCamera.transform.position - transform.position;
|
|
|
|
|
+ directionToCamera.y = 0; // Keep text upright by ignoring Y rotation
|
|
|
|
|
+
|
|
|
|
|
+ if (directionToCamera != Vector3.zero)
|
|
|
|
|
+ {
|
|
|
|
|
+ transform.rotation = Quaternion.LookRotation(-directionToCamera, Vector3.up);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Helper component for distance-based visibility
|
|
|
|
|
+public class DistanceBasedVisibility : MonoBehaviour
|
|
|
|
|
+{
|
|
|
|
|
+ public Camera targetCamera;
|
|
|
|
|
+ public float maxDistance = 50f;
|
|
|
|
|
+
|
|
|
|
|
+ private Renderer textRenderer;
|
|
|
|
|
+
|
|
|
|
|
+ private void Start()
|
|
|
|
|
+ {
|
|
|
|
|
+ textRenderer = GetComponent<Renderer>();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void Update()
|
|
|
|
|
+ {
|
|
|
|
|
+ if (targetCamera != null && textRenderer != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ float distance = Vector3.Distance(transform.position, targetCamera.transform.position);
|
|
|
|
|
+ textRenderer.enabled = distance <= maxDistance;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|