Created
November 29, 2022 10:56
-
-
Save devindazzle/37f55d96ab38275d1b174014e88ea58d to your computer and use it in GitHub Desktop.
This component will mirror a sprite renderer and create a sprite wrapping effect at the edges of the screen similar to the game Asteroids. To use the component, add it to the same game object as the sprite renderer you want to mirror and it just works. Optionally, you can set the warp property to true and the game object will warp to the opposit…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
[RequireComponent(typeof(SpriteRenderer))] | |
public class SpriteWrapper : MonoBehaviour { | |
[Header("Sprite Wrapper")] | |
[Tooltip("Should sprite be wrapped when reaching the edge of the screen?"), SerializeField] | |
private bool wrap; | |
#region Privates | |
private SpriteRenderer m_Renderer; | |
private SpriteRenderer[] m_Wrappers; | |
private Bounds m_ScreenBounds; | |
#endregion | |
#region MonoBehaviour | |
private void Awake() { | |
// Store a reference to frequently accessed components on same game object | |
m_Renderer = GetComponent<SpriteRenderer>(); | |
DebugUtility.HandleErrorIfNullGetComponent<SpriteRenderer, SpriteWrapper>(m_Renderer, this, gameObject); | |
} | |
private void Start() { | |
CalculateScreenBounds(); | |
CreateSpriteWrappers(); | |
PositionSpriteWrappers(); | |
} | |
private void LateUpdate() { | |
// Update the sprite for each of the wrappers to match the renderer | |
for (int i = 0; i < 4; i++) { | |
m_Wrappers[i].sprite = m_Renderer.sprite; | |
m_Wrappers[i].flipX = m_Renderer.flipX; | |
m_Wrappers[i].flipY = m_Renderer.flipY; | |
} | |
// Wrap sprite around screen | |
if (wrap) { | |
Wrap(); | |
} | |
} | |
#endregion | |
#region Methods | |
/// <summary> | |
/// Calculates the screen bounds | |
/// </summary> | |
private void CalculateScreenBounds() { | |
// Get the bottom left and top right corners of the screen | |
// in world points | |
Vector2 bottomLeft = Camera.main.ViewportToWorldPoint(new Vector3(0, 0, 0)); | |
Vector2 topRight = Camera.main.ViewportToWorldPoint(new Vector3(1, 1, 0)); | |
// Create bounds | |
m_ScreenBounds = new Bounds( | |
Camera.main.transform.position, | |
new Vector2(topRight.x - bottomLeft.x, topRight.y - bottomLeft.y) | |
); | |
} | |
/// <summary> | |
/// Create sprite wrapper objects for each of the four directions | |
/// </summary> | |
private void CreateSpriteWrappers() { | |
m_Wrappers = new SpriteRenderer[4]; | |
for (int i = 0; i < 4; i++) { | |
// Instantiate a copy of the sprite renderer on this game object | |
m_Wrappers[i] = Instantiate(m_Renderer, Vector3.zero, Quaternion.identity); | |
m_Wrappers[i].name = transform.name + " Wrapper Sprite " + i; | |
// Remove all components except the sprite renderer from the copy | |
Component[] components = m_Wrappers[i].GetComponents<Component>(); | |
foreach (Component component in components) { | |
// Do not destroy the sprite renderer nor the transform | |
if (component is SpriteRenderer) continue; | |
if (component is Transform) continue; | |
// Destroy any other component | |
DestroyImmediate(component); | |
} | |
} | |
} | |
/// <summary> | |
/// Positions the sprite wrapper objects correctly to mimic a wrap effect | |
/// on the screen | |
/// </summary> | |
private void PositionSpriteWrappers() { | |
// Top | |
m_Wrappers[0].transform.SetParent(transform); | |
m_Wrappers[0].transform.position = transform.position + new Vector3(0, m_ScreenBounds.size.y, 0); | |
// Right | |
m_Wrappers[1].transform.SetParent(transform); | |
m_Wrappers[1].transform.position = transform.position + new Vector3(m_ScreenBounds.size.x, 0, 0); | |
// Bottom | |
m_Wrappers[2].transform.SetParent(transform); | |
m_Wrappers[2].transform.position = transform.position + new Vector3(0, -m_ScreenBounds.size.y, 0); | |
// Left | |
m_Wrappers[3].transform.SetParent(transform); | |
m_Wrappers[3].transform.position = transform.position + new Vector3(-m_ScreenBounds.size.x, 0, 0); | |
} | |
/// <summary> | |
/// Re-positions / wraps the transform | |
/// </summary> | |
private void Wrap() { | |
for (int i = 0; i < 4; i++) { | |
Vector3 p = m_Wrappers[i].transform.position; | |
if (p.x > m_ScreenBounds.min.x && p.x < m_ScreenBounds.max.x && p.y > m_ScreenBounds.min.y && p.y < m_ScreenBounds.max.y) { | |
transform.parent.position = p; | |
break; | |
} | |
} | |
} | |
#endregion | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment