Skip to content

Instantly share code, notes, and snippets.

@devindazzle
Created November 29, 2022 10:56
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save devindazzle/37f55d96ab38275d1b174014e88ea58d to your computer and use it in GitHub Desktop.
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…
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