公共字段在Inspector中重叠显示(自定义Struct Class 数组 列表)

解决UnityInspector中自定义字段重叠问题
文章介绍了Unity中自定义结构体或类在Inspector显示时属性重叠的问题,并提供了解决方案:使用[NonReorderable]标签防止数组或列表重排,以改善数据可视化效果。

自定义公共字段在Inspector相互重叠

一、什么问题

当用到自定义的结构体或类的时候,在Unity面板中展开该属性,会出现属性之间相互重叠的问题。如下图所示。
在这里插入图片描述

二、如何解决

方法:对数据(数组 // 列表)定义之前添加[NonReorderable]字段。
含义:在inspector中,禁止对数组或列表重排。
【官方文档】

//定义公共类
 [Serializable]  //在面板中可视公共类Obj
    public class Obj
    {
   
   
        public Transform Object
将以下代码改成不通过在commandBuffer绘制来使outlines里的物体可以实现描边效果: using UnityEngine; using System.Collections.Generic; using UnityEngine.Rendering; namespace cakeslice { [DisallowMultipleComponent] [RequireComponent(typeof(Camera))] [ExecuteInEditMode] public class OutlineEffect : MonoBehaviour { private static OutlineEffect m_instance; public static OutlineEffect Instance { get { if (Equals(m_instance, null)) { return m_instance = FindObjectOfType(typeof(OutlineEffect)) as OutlineEffect; } return m_instance; } } private OutlineEffect() { } private readonly LinkedSet<Outline> outlines = new LinkedSet<Outline>(); [Range(0.0f, 6.0f)] public float lineThickness = 1.25f; [Range(0, 10)] public float lineIntensity = .5f; [Range(0, 1)] public float fillAmount = 0.2f; public Color lineColor0 = Color.red; public Color lineColor1 = Color.green; public Color lineColor2 = Color.blue; public bool additiveRendering = false; public bool backfaceCulling = true; [Header("These settings can affect performance!")] public bool cornerOutlines = false; public bool addLinesBetweenColors = false; [Header("Advanced settings")] public bool scaleWithScreenSize = true; [Range(0.1f, .9f)] public float alphaCutoff = .5f; public bool flipY = false; public Camera sourceCamera; [HideInInspector] public Camera outlineCamera; Material outline1Material; Material outline2Material; Material outline3Material; Material outlineEraseMaterial; Shader outlineShader; Shader outlineBufferShader; [HideInInspector] public Material outlineShaderMaterial; [HideInInspector] public RenderTexture renderTexture; [HideInInspector] public RenderTexture extraRenderTexture; CommandBuffer commandBuffer; Material GetMaterialFromID(int ID) { if (ID == 0) return outline1Material; else if (ID == 1) return outline2Material; else return outline3Material; } List<Material> materialBuffer = new List<Material>(); Material CreateMaterial(Color emissionColor) { Material m = new Material(outlineBufferShader); m.SetColor("_Color", emissionColor); m.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); m.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); m.SetInt("_ZWrite", 1); m.DisableKeyword("_ALPHATEST_ON"); m.EnableKeyword("_ALPHABLEND_ON"); m.DisableKeyword("_ALPHAPREMULTIPLY_ON"); m.renderQueue = 3000; m.enableInstancing = true; return m; } private void Awake() { m_instance = this; } void Start() { CreateMaterialsIfNeeded(); UpdateMaterialsPublicProperties(); if (sourceCamera == null) { sourceCamera = GetComponent<Camera>(); if (sourceCamera == null) sourceCamera = Camera.main; } if (outlineCamera == null) { GameObject cameraGameObject = new GameObject("Outline Camera"); cameraGameObject.transform.parent = sourceCamera.transform; outlineCamera = cameraGameObject.AddComponent<Camera>(); outlineCamera.enabled = false; } renderTexture = new RenderTexture(sourceCamera.pixelWidth, sourceCamera.pixelHeight, 16, RenderTextureFormat.Default); extraRenderTexture = new RenderTexture(sourceCamera.pixelWidth, sourceCamera.pixelHeight, 16, RenderTextureFormat.Default); UpdateOutlineCameraFromSource(); commandBuffer = new CommandBuffer(); outlineCamera.AddCommandBuffer(CameraEvent.BeforeImageEffects, commandBuffer); } public void OnPreRender() { if (commandBuffer == null) return; CreateMaterialsIfNeeded(); if (renderTexture == null || renderTexture.width != sourceCamera.pixelWidth || renderTexture.height != sourceCamera.pixelHeight) { renderTexture = new RenderTexture(sourceCamera.pixelWidth, sourceCamera.pixelHeight, 16, RenderTextureFormat.Default); extraRenderTexture = new RenderTexture(sourceCamera.pixelWidth, sourceCamera.pixelHeight, 16, RenderTextureFormat.Default); outlineCamera.targetTexture = renderTexture; } UpdateMaterialsPublicProperties(); UpdateOutlineCameraFromSource(); outlineCamera.targetTexture = renderTexture; commandBuffer.SetRenderTarget(renderTexture); commandBuffer.Clear(); commandBuffer.ClearRenderTarget(true, true, Color.clear); if (outlines != null) { var sortedOutlines = new List<Outline>(outlines); sortedOutlines.Sort((a, b) => { if (a == null || b == null) return 0; float distA = Vector3.SqrMagnitude(sourceCamera.transform.position - a.transform.position); float distB = Vector3.SqrMagnitude(sourceCamera.transform.position - b.transform.position); return distA.CompareTo(distB); }); foreach (Outline outline in sortedOutlines) { if (outline == null) continue; LayerMask l = sourceCamera.cullingMask; if ((l & (1 << outline.gameObject.layer)) == 0) continue; Renderer renderer = outline.Renderer; if (renderer == null) continue; for (int v = 0; v < renderer.sharedMaterials.Length; v++) { Material m = null; if (renderer.sharedMaterials[v]?.mainTexture != null) { foreach (Material g in materialBuffer) { if (g.mainTexture == renderer.sharedMaterials[v].mainTexture) { if (outline.eraseRenderer && g.color == outlineEraseMaterial.color) m = g; else if (g.color == GetMaterialFromID(outline.color).color) m = g; } } if (m == null) { if (outline.eraseRenderer) m = new Material(outlineEraseMaterial); else m = new Material(GetMaterialFromID(outline.color)); m.mainTexture = renderer.sharedMaterials[v].mainTexture; materialBuffer.Add(m); } } else { if (outline.eraseRenderer) m = outlineEraseMaterial; else m = GetMaterialFromID(outline.color); } if (backfaceCulling) m.SetInt("_Culling", (int)UnityEngine.Rendering.CullMode.Back); else m.SetInt("_Culling", (int)UnityEngine.Rendering.CullMode.Off); commandBuffer.DrawRenderer(renderer, m, 0, 0); if (renderer is MeshRenderer meshRenderer) { MeshFilter meshFilter = outline.GetComponent<MeshFilter>(); if (meshFilter != null && meshFilter.sharedMesh != null) { for (int i = 1; i < meshFilter.sharedMesh.subMeshCount; i++) commandBuffer.DrawRenderer(renderer, m, i, 0); } } else if (renderer is SkinnedMeshRenderer skinnedMeshRenderer) { if (skinnedMeshRenderer.sharedMesh != null) { for (int i = 1; i < skinnedMeshRenderer.sharedMesh.subMeshCount; i++) commandBuffer.DrawRenderer(renderer, m, i, 0); } } } } } outlineCamera.Render(); } private void OnEnable() { Outline[] o = FindObjectsOfType<Outline>(); foreach (Outline oL in o) { oL.enabled = false; oL.enabled = true; } } void OnDestroy() { if (renderTexture != null) renderTexture.Release(); if (extraRenderTexture != null) extraRenderTexture.Release(); DestroyMaterials(); } void OnRenderImage(RenderTexture source, RenderTexture destination) { outlineShaderMaterial.SetTexture("_OutlineSource", renderTexture); if (addLinesBetweenColors) { Graphics.Blit(source, extraRenderTexture, outlineShaderMaterial, 0); outlineShaderMaterial.SetTexture("_OutlineSource", extraRenderTexture); } Graphics.Blit(source, destination, outlineShaderMaterial, 1); } private void CreateMaterialsIfNeeded() { if (outlineShader == null) outlineShader = Resources.Load<Shader>("OutlineShader"); if (outlineBufferShader == null) { outlineBufferShader = Resources.Load<Shader>("OutlineBufferShader"); } if (outlineShaderMaterial == null) { outlineShaderMaterial = new Material(outlineShader); outlineShaderMaterial.hideFlags = HideFlags.HideAndDontSave; UpdateMaterialsPublicProperties(); } if (outlineEraseMaterial == null) outlineEraseMaterial = CreateMaterial(new Color(0, 0, 0, 0)); if (outline1Material == null) outline1Material = CreateMaterial(new Color(1, 0, 0, 0)); if (outline2Material == null) outline2Material = CreateMaterial(new Color(0, 1, 0, 0)); if (outline3Material == null) outline3Material = CreateMaterial(new Color(0, 0, 1, 0)); } private void DestroyMaterials() { foreach (Material m in materialBuffer) DestroyImmediate(m); materialBuffer.Clear(); DestroyImmediate(outlineShaderMaterial); DestroyImmediate(outlineEraseMaterial); DestroyImmediate(outline1Material); DestroyImmediate(outline2Material); DestroyImmediate(outline3Material); outlineShader = null; outlineBufferShader = null; outlineShaderMaterial = null; outlineEraseMaterial = null; outline1Material = null; outline2Material = null; outline3Material = null; } public void UpdateMaterialsPublicProperties() { if (outlineShaderMaterial) { float scalingFactor = 1; if (scaleWithScreenSize) { // If Screen.height gets bigger, outlines gets thicker scalingFactor = Screen.height / 360.0f; } // If scaling is too small (height less than 360 pixels), make sure you still render the outlines, but render them with 1 thickness if (scaleWithScreenSize && scalingFactor < 1) { if (UnityEngine.XR.XRSettings.isDeviceActive && sourceCamera.stereoTargetEye != StereoTargetEyeMask.None) { outlineShaderMaterial.SetFloat("_LineThicknessX", (1 / 1000.0f) * (1.0f / UnityEngine.XR.XRSettings.eyeTextureWidth) * 1000.0f); outlineShaderMaterial.SetFloat("_LineThicknessY", (1 / 1000.0f) * (1.0f / UnityEngine.XR.XRSettings.eyeTextureHeight) * 1000.0f); } else { outlineShaderMaterial.SetFloat("_LineThicknessX", (1 / 1000.0f) * (1.0f / Screen.width) * 1000.0f); outlineShaderMaterial.SetFloat("_LineThicknessY", (1 / 1000.0f) * (1.0f / Screen.height) * 1000.0f); } } else { if (UnityEngine.XR.XRSettings.isDeviceActive && sourceCamera.stereoTargetEye != StereoTargetEyeMask.None) { outlineShaderMaterial.SetFloat("_LineThicknessX", scalingFactor * (lineThickness / 1000.0f) * (1.0f / UnityEngine.XR.XRSettings.eyeTextureWidth) * 1000.0f); outlineShaderMaterial.SetFloat("_LineThicknessY", scalingFactor * (lineThickness / 1000.0f) * (1.0f / UnityEngine.XR.XRSettings.eyeTextureHeight) * 1000.0f); } else { outlineShaderMaterial.SetFloat("_LineThicknessX", scalingFactor * (lineThickness / 1000.0f) * (1.0f / Screen.width) * 1000.0f); outlineShaderMaterial.SetFloat("_LineThicknessY", scalingFactor * (lineThickness / 1000.0f) * (1.0f / Screen.height) * 1000.0f); } } outlineShaderMaterial.SetFloat("_LineIntensity", lineIntensity); outlineShaderMaterial.SetFloat("_FillAmount", fillAmount); outlineShaderMaterial.SetColor("_LineColor1", lineColor0 * lineColor0); outlineShaderMaterial.SetColor("_LineColor2", lineColor1 * lineColor1); outlineShaderMaterial.SetColor("_LineColor3", lineColor2 * lineColor2); if (flipY) outlineShaderMaterial.SetInt("_FlipY", 1); else outlineShaderMaterial.SetInt("_FlipY", 0); if (!additiveRendering) outlineShaderMaterial.SetInt("_Dark", 1); else outlineShaderMaterial.SetInt("_Dark", 0); if (cornerOutlines) outlineShaderMaterial.SetInt("_CornerOutlines", 1); else outlineShaderMaterial.SetInt("_CornerOutlines", 0); Shader.SetGlobalFloat("_OutlineAlphaCutoff", alphaCutoff); } } void UpdateOutlineCameraFromSource() { outlineCamera.CopyFrom(sourceCamera); outlineCamera.renderingPath = RenderingPath.Forward; outlineCamera.backgroundColor = new Color(0.0f, 0.0f, 0.0f, 0.0f); outlineCamera.clearFlags = CameraClearFlags.SolidColor; outlineCamera.rect = new Rect(0, 0, 1, 1); outlineCamera.cullingMask = 0; outlineCamera.targetTexture = renderTexture; outlineCamera.enabled = false; #if UNITY_5_6_OR_NEWER outlineCamera.allowHDR = false; #else outlineCamera.hdr = false; #endif } public void AddOutline(Outline outline) { if (!outlines.Contains(outline)) outlines.Add(outline); } public void RemoveOutline(Outline outline) { if (outlines.Contains(outline)) outlines.Remove(outline); } } }
最新发布
09-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值