LogoPlaneCreator.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. using UnityEngine;
  2. using UnityEngine.UI;
  3. using TMPro;
  4. using System.Collections.Generic;
  5. public class LogoPlaneCreator : MonoBehaviour
  6. {
  7. [Header("目标对象设置")]
  8. [SerializeField] private GameObject targetObject; // 要添加Plane的目标对象
  9. [SerializeField] private string targetObjectName = "Object001"; // 如果targetObject为空,则通过名称查找
  10. [Header("Plane设置")]
  11. [SerializeField] private Vector3 planePosition = Vector3.zero; // 相对于目标对象的位置
  12. [SerializeField] private Vector3 planeRotation = Vector3.zero; // 旋转角度
  13. [SerializeField] private Vector3 planeScale = Vector3.one; // 缩放
  14. [SerializeField] private Material planeMaterial; // Plane的材质
  15. [Header("Logo文字设置")]
  16. [SerializeField] private string logoText = "LOGO"; // Logo文字
  17. [SerializeField] private Font logoFont; // 字体
  18. [SerializeField] private int fontSize = 48; // 字体大小
  19. [SerializeField] private Color textColor = Color.white; // 文字颜色
  20. [SerializeField] private TextAlignmentOptions textAlignment = TextAlignmentOptions.Center; // 文字对齐
  21. [SerializeField] private Vector3 textOffset = Vector3.zero; // 文字位置偏移
  22. [Header("高级设置")]
  23. [SerializeField] private bool useTextMeshPro = true; // 是否使用TextMeshPro
  24. [SerializeField] private bool createAsChild = true; // 是否作为子对象创建
  25. [SerializeField] private bool addCollider = false; // 是否添加碰撞体
  26. [SerializeField] private bool addRigidbody = false; // 是否添加刚体
  27. [Header("文字质量设置")]
  28. [SerializeField] private bool useHighQuality = true; // 使用高质量渲染
  29. [SerializeField] private float textScale = 2.0f; // 文字缩放倍数(提高分辨率)
  30. [SerializeField] private bool enableAntiAliasing = true; // 启用抗锯齿
  31. [SerializeField] private int canvasWidth = 1024; // Canvas宽度
  32. [SerializeField] private int canvasHeight = 512; // Canvas高度
  33. [SerializeField] private bool usePixelPerfect = true; // 像素完美模式
  34. [SerializeField] private FilterMode textureFilterMode = FilterMode.Bilinear; // 纹理过滤模式
  35. private GameObject createdPlane;
  36. private GameObject createdText;
  37. private Canvas createdCanvas;
  38. [ContextMenu("创建Logo Plane")]
  39. public void CreateLogoPlane()
  40. {
  41. // 查找目标对象
  42. GameObject target = targetObject;
  43. if (target == null)
  44. {
  45. target = GameObject.Find(targetObjectName);
  46. if (target == null)
  47. {
  48. Debug.LogError($"未找到名为 {targetObjectName} 的对象");
  49. return;
  50. }
  51. }
  52. // 创建Plane
  53. CreatePlane(target);
  54. // 创建文字Logo
  55. CreateTextLogo();
  56. Debug.Log($"已在 {target.name} 上成功创建Logo Plane");
  57. }
  58. private void CreatePlane(GameObject parent)
  59. {
  60. // 创建Plane GameObject
  61. createdPlane = GameObject.CreatePrimitive(PrimitiveType.Plane);
  62. createdPlane.name = "LogoPlane";
  63. // 设置Transform
  64. Transform planeTransform = createdPlane.transform;
  65. if (createAsChild)
  66. {
  67. planeTransform.SetParent(parent.transform);
  68. planeTransform.localPosition = planePosition;
  69. planeTransform.localRotation = Quaternion.Euler(planeRotation);
  70. planeTransform.localScale = planeScale;
  71. }
  72. else
  73. {
  74. planeTransform.position = parent.transform.position + planePosition;
  75. planeTransform.rotation = parent.transform.rotation * Quaternion.Euler(planeRotation);
  76. planeTransform.localScale = planeScale;
  77. }
  78. // 设置材质
  79. if (planeMaterial != null)
  80. {
  81. MeshRenderer renderer = createdPlane.GetComponent<MeshRenderer>();
  82. renderer.material = planeMaterial;
  83. }
  84. // 添加碰撞体(可选)
  85. if (!addCollider)
  86. {
  87. Collider collider = createdPlane.GetComponent<Collider>();
  88. if (collider != null)
  89. DestroyImmediate(collider);
  90. }
  91. // 添加刚体(可选)
  92. if (addRigidbody)
  93. {
  94. createdPlane.AddComponent<Rigidbody>();
  95. }
  96. }
  97. private void CreateTextLogo()
  98. {
  99. if (string.IsNullOrEmpty(logoText))
  100. {
  101. Debug.LogWarning("Logo文字为空,跳过文字创建");
  102. return;
  103. }
  104. if (useTextMeshPro)
  105. {
  106. CreateTextMeshPro();
  107. }
  108. else
  109. {
  110. CreateLegacyText();
  111. }
  112. }
  113. private void CreateTextMeshPro()
  114. {
  115. // 创建TextMeshPro对象
  116. createdText = new GameObject("LogoText_TMP");
  117. createdText.transform.SetParent(createdPlane.transform);
  118. createdText.transform.localPosition = textOffset;
  119. createdText.transform.localRotation = Quaternion.identity;
  120. // 添加TextMeshPro组件
  121. TextMeshPro tmp = createdText.AddComponent<TextMeshPro>();
  122. tmp.text = logoText;
  123. tmp.fontSize = fontSize * (useHighQuality ? textScale : 1.0f);
  124. tmp.color = textColor;
  125. tmp.alignment = textAlignment;
  126. // 高质量设置
  127. if (useHighQuality)
  128. {
  129. // 设置高质量渲染
  130. tmp.enableAutoSizing = false;
  131. tmp.fontStyle = FontStyles.Normal;
  132. tmp.enableWordWrapping = false;
  133. tmp.richText = false;
  134. // 设置材质质量
  135. if (tmp.material != null)
  136. {
  137. tmp.material.SetFloat("_UnderlayDilate", 0.0f);
  138. tmp.material.SetFloat("_UnderlaySoftness", 0.0f);
  139. tmp.material.SetFloat("_WeightNormal", 0.5f);
  140. tmp.material.SetFloat("_WeightBold", 0.75f);
  141. }
  142. }
  143. // 设置字体
  144. if (logoFont != null)
  145. {
  146. // 注意:TextMeshPro使用TMP_FontAsset,不是普通Font
  147. // 这里需要手动设置TMP_FontAsset
  148. Debug.Log("请手动设置TextMeshPro的字体资源");
  149. }
  150. // 调整位置,让文字面向摄像机
  151. createdText.transform.LookAt(Camera.main.transform);
  152. createdText.transform.Rotate(0, 180, 0);
  153. // 应用缩放
  154. if (useHighQuality && textScale != 1.0f)
  155. {
  156. createdText.transform.localScale = Vector3.one / textScale;
  157. }
  158. }
  159. private void CreateLegacyText()
  160. {
  161. // 创建Canvas
  162. GameObject canvasObj = new GameObject("LogoCanvas");
  163. canvasObj.transform.SetParent(createdPlane.transform);
  164. canvasObj.transform.localPosition = textOffset;
  165. canvasObj.transform.localRotation = Quaternion.identity;
  166. Canvas canvas = canvasObj.AddComponent<Canvas>();
  167. canvas.renderMode = RenderMode.WorldSpace;
  168. canvas.worldCamera = Camera.main;
  169. createdCanvas = canvas;
  170. // 高质量Canvas设置
  171. if (useHighQuality)
  172. {
  173. // 设置Canvas尺寸
  174. RectTransform canvasRect = canvasObj.GetComponent<RectTransform>();
  175. canvasRect.sizeDelta = new Vector2(canvasWidth, canvasHeight);
  176. // 添加CanvasScaler
  177. CanvasScaler scaler = canvasObj.AddComponent<CanvasScaler>();
  178. scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
  179. scaler.referenceResolution = new Vector2(canvasWidth, canvasHeight);
  180. scaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
  181. scaler.matchWidthOrHeight = 0.5f;
  182. // 添加GraphicRaycaster(如果需要交互)
  183. canvasObj.AddComponent<GraphicRaycaster>();
  184. }
  185. else
  186. {
  187. // 标准设置
  188. CanvasScaler scaler = canvasObj.AddComponent<CanvasScaler>();
  189. scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
  190. scaler.referenceResolution = new Vector2(1920, 1080);
  191. }
  192. // 创建Text对象
  193. createdText = new GameObject("LogoText");
  194. createdText.transform.SetParent(canvasObj.transform);
  195. createdText.transform.localPosition = Vector3.zero;
  196. createdText.transform.localRotation = Quaternion.identity;
  197. createdText.transform.localScale = Vector3.one;
  198. // 添加Text组件
  199. Text text = createdText.AddComponent<Text>();
  200. text.text = logoText;
  201. text.font = logoFont;
  202. text.fontSize = (int)(fontSize * (useHighQuality ? textScale : 1.0f));
  203. text.color = textColor;
  204. text.alignment = TextAnchor.MiddleCenter;
  205. // 高质量文字设置
  206. if (useHighQuality)
  207. {
  208. text.horizontalOverflow = HorizontalWrapMode.Overflow;
  209. text.verticalOverflow = VerticalWrapMode.Overflow;
  210. text.resizeTextForBestFit = false;
  211. text.supportRichText = false;
  212. // 设置字体样式
  213. if (logoFont != null)
  214. {
  215. text.font = logoFont;
  216. text.fontStyle = FontStyle.Normal;
  217. }
  218. }
  219. // 设置RectTransform
  220. RectTransform rectTransform = createdText.GetComponent<RectTransform>();
  221. if (useHighQuality)
  222. {
  223. rectTransform.sizeDelta = new Vector2(canvasWidth * 0.8f, canvasHeight * 0.8f);
  224. }
  225. else
  226. {
  227. rectTransform.sizeDelta = new Vector2(400, 100);
  228. }
  229. rectTransform.anchoredPosition = Vector2.zero;
  230. // 应用缩放
  231. if (useHighQuality && textScale != 1.0f)
  232. {
  233. createdText.transform.localScale = Vector3.one / textScale;
  234. }
  235. // 创建高质量材质(可选)
  236. if (useHighQuality && enableAntiAliasing)
  237. {
  238. CreateHighQualityMaterial(text);
  239. }
  240. }
  241. private void CreateHighQualityMaterial(Text text)
  242. {
  243. // 创建高质量材质
  244. Material highQualityMaterial = new Material(Shader.Find("UI/Default"));
  245. // 设置材质属性
  246. highQualityMaterial.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.SrcAlpha);
  247. highQualityMaterial.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
  248. highQualityMaterial.SetFloat("_ZWrite", 0);
  249. highQualityMaterial.DisableKeyword("_ALPHATEST_ON");
  250. highQualityMaterial.EnableKeyword("_ALPHABLEND_ON");
  251. highQualityMaterial.DisableKeyword("_ALPHAPREMULTIPLY_ON");
  252. highQualityMaterial.renderQueue = 3000;
  253. // 应用材质
  254. text.material = highQualityMaterial;
  255. }
  256. [ContextMenu("删除Logo Plane")]
  257. public void DeleteLogoPlane()
  258. {
  259. if (createdPlane != null)
  260. {
  261. DestroyImmediate(createdPlane);
  262. createdPlane = null;
  263. createdText = null;
  264. createdCanvas = null;
  265. Debug.Log("已删除Logo Plane");
  266. }
  267. }
  268. [ContextMenu("更新Logo文字")]
  269. public void UpdateLogoText()
  270. {
  271. if (createdText != null)
  272. {
  273. if (useTextMeshPro)
  274. {
  275. TextMeshPro tmp = createdText.GetComponent<TextMeshPro>();
  276. if (tmp != null)
  277. {
  278. tmp.text = logoText;
  279. tmp.fontSize = fontSize * (useHighQuality ? textScale : 1.0f);
  280. tmp.color = textColor;
  281. }
  282. }
  283. else
  284. {
  285. Text text = createdText.GetComponent<Text>();
  286. if (text != null)
  287. {
  288. text.text = logoText;
  289. text.fontSize = (int)(fontSize * (useHighQuality ? textScale : 1.0f));
  290. text.color = textColor;
  291. }
  292. }
  293. Debug.Log("已更新Logo文字");
  294. }
  295. }
  296. [ContextMenu("查找目标对象")]
  297. public void FindTargetObject()
  298. {
  299. GameObject found = GameObject.Find(targetObjectName);
  300. if (found != null)
  301. {
  302. targetObject = found;
  303. Debug.Log($"已找到目标对象: {found.name}");
  304. }
  305. else
  306. {
  307. Debug.LogWarning($"未找到名为 {targetObjectName} 的对象");
  308. }
  309. }
  310. [ContextMenu("优化文字质量")]
  311. public void OptimizeTextQuality()
  312. {
  313. if (createdText != null)
  314. {
  315. if (useTextMeshPro)
  316. {
  317. TextMeshPro tmp = createdText.GetComponent<TextMeshPro>();
  318. if (tmp != null)
  319. {
  320. // 重新应用高质量设置
  321. tmp.fontSize = fontSize * textScale;
  322. if (tmp.material != null)
  323. {
  324. tmp.material.SetFloat("_UnderlayDilate", 0.0f);
  325. tmp.material.SetFloat("_UnderlaySoftness", 0.0f);
  326. }
  327. }
  328. }
  329. else
  330. {
  331. Text text = createdText.GetComponent<Text>();
  332. if (text != null)
  333. {
  334. text.fontSize = (int)(fontSize * textScale);
  335. text.horizontalOverflow = HorizontalWrapMode.Overflow;
  336. text.verticalOverflow = VerticalWrapMode.Overflow;
  337. }
  338. }
  339. Debug.Log("已优化文字质量");
  340. }
  341. }
  342. // 在Inspector中实时预览
  343. private void OnValidate()
  344. {
  345. if (Application.isPlaying && createdText != null)
  346. {
  347. UpdateLogoText();
  348. }
  349. }
  350. }