ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Particle System] 유니티 2017 -> 2018 업그레이드 시 변경 사항
    게임 엔진/Unity 2021. 7. 5. 21:22

    유니티 업그레이드 시 파티클 시스템 변경사항

    파티클 시스템 버그로 인해 2017에서 생성된 파티클 이펙트는 2018에서 정상적으로 보이지 않을 수 있다. 유니티에서 공개한 버그는 다음과 같다.

    • 메시(Mesh)
      • Offset 공식 변경(기존: size * size * pivot, 변경: size * pivot)
    • 빌보드(Billboard)
      • 비균등 스케일일 때 스케일의  y축과 z축이 반전됨
      • 비균등 스케일일 때 회전 후 스케일링 적용됨
    • 윈드존(Wind Zone)
      • 윈드 존이 파티클에 영향 주는 방향 변경(기존: 나무와 반대 방향, 변경: 나무와 동일한 방향)

     

    유니티 파티클 변경 사항 처리 참고 코드

    유니티 업그레이드를 위해 사용한 코드이며 모든 버그를 수정하지는 못했으나 대부분의 버그는 수정하여 정상적으로 출력되도록 했다.

     

    - 메시 처리 코드

    ParticleSystemRenderer psr = psrArr[i];
    ParticleSystem ps = psr.GetComponent<ParticleSystem>();
    Transform psrTransform = psr.transform;
    
    if (psr.renderMode == ParticleSystemRenderMode.Mesh && psr.mesh != null)
    {
      Vector3 scale = psrTransform.localScale;
      ParticleSystem.MainModule main = ps.main;
    
      if (IsNonUniformScale(scale))
      {
          ParticleSystem.MinMaxCurve startRotationX = main.startRotationX;
          ParticleSystem.MinMaxCurve startRotationY = main.startRotationY;
          ParticleSystem.MinMaxCurve startRotationZ = main.startRotationZ;
    
          float xMin = startRotationX.constant;
          float yMin = startRotationY.constant;
          float zMin = startRotationZ.constant;
    
          float xMax, yMax, zMax;
          xMax = yMax = zMax = 0;
    
          if (main.startRotation.mode == ParticleSystemCurveMode.TwoConstants)
          {
              xMin = Mathf.Min(startRotationX.constantMin, startRotationX.constantMax);
              yMin = Mathf.Min(startRotationY.constantMin, startRotationY.constantMax);
              zMin = Mathf.Min(startRotationZ.constantMin, startRotationZ.constantMax);
    
              xMax = Mathf.Max(startRotationX.constantMin, startRotationX.constantMax);
              yMax = Mathf.Max(startRotationY.constantMin, startRotationY.constantMax);
              zMax = Mathf.Max(startRotationZ.constantMin, startRotationZ.constantMax);
          }
    
          Quaternion scaleRotation = Quaternion.AngleAxis(Mathf.Rad2Deg * zMin, Vector3.forward);
    
          if (main.startRotation3D)
          {
              scaleRotation *= Quaternion.AngleAxis(Mathf.Rad2Deg * xMin, Vector3.right)
              * Quaternion.AngleAxis(Mathf.Rad2Deg * yMin, Vector3.up);
          }
    
          psrTransform.rotation *= scaleRotation;
    
          if (main.startRotation.mode == ParticleSystemCurveMode.TwoConstants)
          {
              startRotationX.constantMin = startRotationY.constantMin 
              	= startRotationZ.constantMin = 0;
    
              startRotationX.constantMax = xMax - xMin;
              startRotationY.constantMax = yMax - yMin;
              startRotationZ.constantMax = zMax - zMin;
          }
          else
          {
              startRotationX.constant = startRotationY.constant = startRotationZ.constant = 0;
          }
    
          main.startRotationX = startRotationX;
          main.startRotationY = startRotationY;
          main.startRotationZ = startRotationZ;
    
          changed = true;
      }
    
      if (!Mathf.Approximately(psr.pivot.x, 0) || !Mathf.Approximately(psr.pivot.y, 0)
      	|| !Mathf.Approximately(psr.pivot.z, 0))
      {
          Vector3 meshSize = psr.mesh.bounds.size;
    
          Vector3 newPivot = new Vector3(psr.pivot.x, -psr.pivot.z, -psr.pivot.y);
          if (!Mathf.Approximately(meshSize.x, 0))
          {
              newPivot.x /= meshSize.x;
          }
          if (!Mathf.Approximately(meshSize.y, 0))
          {
              newPivot.y /= meshSize.y;
          }
          if (!Mathf.Approximately(meshSize.z, 0))
          {
              newPivot.z /= meshSize.z;
          }
    
          ParticleSystem.MinMaxCurve startSizeX = main.startSizeX;
          ParticleSystem.MinMaxCurve startSizeY = main.startSizeY;
          ParticleSystem.MinMaxCurve startSizeZ = main.startSizeZ;
    
          float xMin = startSizeX.constant;
          float yMin = startSizeY.constant;
          float zMin = startSizeZ.constant;
    
          if (main.startRotation.mode == ParticleSystemCurveMode.TwoConstants)
          {
              xMin = Mathf.Min(startSizeX.constantMin, startSizeX.constantMax);
              yMin = Mathf.Min(startSizeY.constantMin, startSizeY.constantMax);
              zMin = Mathf.Min(startSizeZ.constantMin, startSizeZ.constantMax);
          }
    
          if (main.startSize3D)
          {
              if (!Mathf.Approximately(xMin, 0))
              {
                  newPivot.x *= xMin;
              }
              if (!Mathf.Approximately(yMin, 0))
              {
                  newPivot.y *= yMin;
              }
              if (!Mathf.Approximately(zMin, 0))
              {
                  newPivot.z *= zMin;
              }
          }
          else
          {
              if (!Mathf.Approximately(xMin, 0))
              {
                  newPivot.x *= xMin;
                  newPivot.y *= xMin;
                  newPivot.z *= xMin;
              }
          }
    
          psr.pivot = newPivot;
    
          changed = true;
      }
    }

     

    - 빌보드 처리 코드

    else if (psr.renderMode == ParticleSystemRenderMode.Billboard)
    {
        Vector3 scale = psrTransform.localScale;
        Transform parent = psrTransform.parent;
        ParticleSystem.MainModule main = ps.main;
    
        if (main.scalingMode != ParticleSystemScalingMode.Local)
        {
            if (parent != null)
            {
                while (psrTransform.childCount > 0)
                {
                    psrTransform.GetChild(0).parent = parent;
                }
            }
    
            while (parent != null)
            {
                Vector3 parentScale = parent.localScale;
    
                if (!Mathf.Approximately(parentScale.x, 0))
                    scale.x *= parentScale.x;
                if (!Mathf.Approximately(parentScale.y, 0))
                    scale.y *= parentScale.y;
                if (!Mathf.Approximately(parentScale.z, 0))
                    scale.z *= parentScale.z;
    
                ParticleSystemRenderer ppsr = parent.GetComponent<ParticleSystemRenderer>();
                if (ppsr != null && ppsr.enabled &&
                		ppsr.renderMode == ParticleSystemRenderMode.Billboard)
                {
                    break;
                }
    
                parent = parent.parent;
            }
        }
    
        if (!Mathf.Approximately(scale.y, scale.z)
            || !Mathf.Approximately(psrTransform.localScale.y, psrTransform.localScale.z))
        {
            psrTransform.localScale = new Vector3(scale.x, scale.z, scale.y);
    
            main.scalingMode = ParticleSystemScalingMode.Local;
        }
    
        changed = true;
    }

     

    - 전체 코드

    UpgradeEffects.cs
    0.01MB

     

     

    댓글

Designed by Tistory.