게임 엔진/Unity

[Particle System] 유니티 2017 -> 2018 업그레이드 시 변경 사항

niamdank 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