using UnityEngine; using UnityEngine.Experimental.Rendering.Universal; using System.Reflection; [ExecuteInEditMode] public class ShadowCasterFlip : MonoBehaviour { [SerializeField] [HideInInspector] private bool flipX = false; [SerializeField] [HideInInspector] private bool flipY = false; private SpriteRenderer spriteRenderer; private ShadowCaster2D shadowCaster; private static BindingFlags accessFlagsPrivate = BindingFlags.NonPublic | BindingFlags.Instance; private static FieldInfo meshField = typeof(ShadowCaster2D).GetField("m_Mesh", accessFlagsPrivate); private static FieldInfo shapePathField = typeof(ShadowCaster2D).GetField("m_ShapePath", accessFlagsPrivate); private static MethodInfo onEnableMethod = typeof(ShadowCaster2D).GetMethod("OnEnable", accessFlagsPrivate); private static bool isInspector => #if UNITY_EDITOR !UnityEditor.EditorApplication.isPlaying; #else false; #endif //Bounds bounds => GetComponent()?.bounds ?? GetComponent()?.bounds ?? new Bounds(transform.position, Vector3.one); private bool flipCaster(bool flipX, bool flipY) { if (!flipX && !flipY) return false; var shapePath = shapePathField.GetValue(shadowCaster) as Vector3[]; var newShapePath = new Vector3[shapePath.Length]; int newStartIndex = 0; float? lowestAvg = null; for (int i = 0; i < shapePath.Length; i++) { shapePath[i].x = shapePath[i].x * (flipX ? -1 : 1); shapePath[i].y = shapePath[i].y * (flipY ? -1 : 1); var newAvg = (shapePath[i].x + shapePath[i].y) / 2; if (lowestAvg == null || newAvg < lowestAvg) { newStartIndex = i; lowestAvg = newAvg; } } if (flipX != flipY) for (int i = 0, ni = newStartIndex; i < shapePath.Length; i++, ni--) { if (ni < 0) ni = shapePath.Length - 1; newShapePath[i] = shapePath[ni]; } else for (int i = 0, ni = newStartIndex; i < shapePath.Length; i++, ni++) { if (ni >= shapePath.Length) ni = 0; newShapePath[i] = shapePath[ni]; } shapePathField.SetValue(shadowCaster, newShapePath); shadowCaster.enabled = false; meshField.SetValue(shadowCaster, null); shadowCaster.enabled = true; return true; } #if UNITY_EDITOR void Start() { if (isInspector) { spriteRenderer = GetComponent(); shadowCaster = GetComponent(); } } #endif #if UNITY_EDITOR void Update() { if (isInspector && flipCaster(flipX != spriteRenderer.flipX, flipY != spriteRenderer.flipY)) { flipX = spriteRenderer.flipX; flipY = spriteRenderer.flipY; UnityEditor.EditorUtility.SetDirty(shadowCaster); UnityEditor.EditorUtility.SetDirty(this); } } #endif }