게임 엔진/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;
}
- 전체 코드