Image에 ParticalleSystem 및 Image 표시

13423 단어 UnityC#
UGUI에 Partical 효과를 표시하고 싶습니다!나는 이것이 항상 있는 요구라고 생각한다.예전에는 상당히 번거로운 방법으로 이루어졌다고 생각했는데 오랜만에 찾아보니 간단할 것 같아서 총괄해 봤어요.(전제는 Canvas의 RenderMode를 ScreenSpace-Camera로 만들어야 한다는 것이다. ScreenSpace-Overlay의 경우 RenderTexture를 사용하는 것은 번거롭다.)
※ 환경은 유니티 2017.C#6.0을 3.1p4에 사용합니다.

Canvas 및 Particalle System의 Sorting Layer 및 Order in Layer 를 적절하게 설정


서문에서 설명한 대로 Canvas의 RenderMode는 ScreenSpace-Camera여야 합니다.또한 이 모드는 Canvas의 Camera를 방영해야 하기 때문에 Canvas의 Render Camera에 UI용 Camera를 설정합니다.
Canvas 및 Particle System의 표시 순서는 SortingLayer 및 Order in Layer에 의해 결정됩니다.예를 들어 다음과 같이 설정하면 Canvas에ParticalleSystem이 표시됩니다
  • Canvas(SortingLayer=Default, Order in Layer=0)
  • ParticleSystem(SortingLayer=Default, Order in Layer=1)

  • SortingLayer는 우선순위가 높지만 미리 Layer를 정의해야 하기 때문에 자유도가 낮다.숫자 값을 사용하여 Order in Layer를 지정할 수 있으므로 디스플레이 우선순위를 유연하게 결정할 수 있습니다.

    Canvas의 아이 위에 Canvas를 놓고ParticalleSystem에 Image를 표시합니다


    ParticalleSystem 위에 Image 등 UI를 표시하려면 Order in Layer가 큰 Canvas를 준비합니다.Canvas의 아이에 Canvas를 설치한 경우 Override Sorting을 On으로 설정하여 Sorting Layer와 Order in Layer를 덮어쓸 수 있습니다.

    캔버스의 아이에 캔버스를 설치하면 하이에라치에서 순서와 표시 순서가 일치하지 않는 것이 단점이다.난발은 혼란을 초래할 수 있으니 적당히 해야 한다.

    자동 관리 Order in Layer


    개발 규모가 커지면 캔버스의 오더 인 라이어를 변경할 가능성도 있다.이거 변경할 때 Partical이랑 아기 Canvas 설정을 변경하는 걸 까먹었어요.이런 사태를 야기하다.
    그래서 우리는 최고급 캔버스의 설정을 바꾸면 영향을 받는 Particle System과 어린이 캔버스의 설정을 자동으로 바꿀 수 있는Sorting Order Updater를 만들었다.Canvas에서 Canvas Order Updater를, Particalle System에서 Partical Order Updater를 설정합니다.
    SortingOrderUpdater.cs
    using UnityEngine;
    
    public abstract class SortingOrderUpdater : MonoBehaviour
    {
        [SerializeField]
        SortingOrderUpdater[] childSortingOrderUpdaters;
    
        [SerializeField]
        int relativeOrder = 0;
    
        public void SetOrder(int order, int layerId)
        {
            int newOrder = order + relativeOrder;
    
            SetOrderInDerivedClass(newOrder, layerId);
    
            foreach (var updater in childSortingOrderUpdaters)
                updater.SetOrder(newOrder, layerId);
        }
    
        protected abstract void SetOrderInDerivedClass(int order, int layerId);
    
    #if UNITY_EDITOR
        public void Reset()
        {
            this.childSortingOrderUpdaters = ResetUtility.GetDirectChildComponents<SortingOrderUpdater>(this);
            foreach (var updater in childSortingOrderUpdaters)
                updater.Reset();
        }
    #endif
    }
    
    CanvasOrderUpdater.cs
    using UnityEngine;
    
    [RequireComponent(typeof(Canvas))]
    public class CanvasOrderUpdater : SortingOrderUpdater
    {
        [SerializeField]
        Canvas canvas;
    
        protected override void SetOrderInDerivedClass(int order, int layerId)
        {
            canvas.sortingOrder = order;
            canvas.sortingLayerID = layerId;
        }
    }
    
    ParticleOrderUpdater.cs
    using UnityEngine;
    
    [RequireComponent(typeof(ParticleSystem))]
    public class ParticleOrderUpdater : SortingOrderUpdater
    {
        [SerializeField]
        ParticleSystemRenderer particleSystemRenderer;
    
        protected override void SetOrderInDerivedClass(int order, int layerId)
        {
            particleSystemRenderer.sortingOrder = order;
            particleSystemRenderer.sortingLayerID = layerId;
        }
    }
    
    ResetUtility.cs
    using System.Collections.Generic;
    using System.Linq;
    using UnityEngine;
    
    #if UNITY_EDITOR
    public class ResetUtility
    {
        public static T[] GetDirectChildComponents<T>(Component component) where T : Component
        {
            return GetDirectChildComponents<T>(component.transform).ToArray();
        }
    
        static IEnumerable<T> GetDirectChildComponents<T>(Transform transform) where T : Component
        {
            for (int i = 0; i < transform.childCount; i++)
            {
                Transform child = transform.GetChild(i);
                T component = child.GetComponent<T>();
                if (component != null)
                {
                    yield return component;
                }
                else
                {
                    foreach (T t in GetDirectChildComponents<T>(child))
                        yield return t;
                }
            }
        }
    }
    #endif
    
    설치가 완료되면 Reset이 맨 위에 있는 CanvasOrder Updater가 표시됩니다.그러면 영향을 받는 SortingOrder Updater가 등록됩니다.
    이 코드는 하나의 예다.이 코드는 위쪽 Canvas의 Order in Layer를 동적으로 변경하는 것을 전제로 합니다.실제로는 운용에 따라 개조한 거죠.
    이 예에서 맨 위에 있는 SetOrder를 호출하면 영향을 받은 Canvas와Particlessitem의 값이 업데이트됩니다.Order in Layer의 차이는 Inspector에서 relative Order라는 값을 설정합니다.Particle에서 +1 및 위에 표시된 Canvas에 +2가 설정되어 있습니다.

    Ex.Partical 크기


    Particle의 크기는 locaScale에 의해 결정되는 것 같습니다.부모의 scale이 아무리 변해도 Partical의 크기가 연동되지 않는다는 것이다.이렇게 되면 Top Canvas 설정에 따라 예상치 못한 내용이 표시될 수 있다(크기가 달라질 수 있다).
  • Canvas의 PlaneDistance
  • CanvasSccaller의 설정
  • 이 일대가 바뀌면 탑 캔버스의 scale이 바뀌고 Partical의 표시상 크기가 달라진다.특히 CanvasSccaller에 의한 scale 변화로 터미널마다 값이 달라질 수 있어 번거롭다.Partical의 local Scale 구조를 화면 크기에 따라 자동으로 조정해야 합니다.

    좋은 웹페이지 즐겨찾기