#22 Reworked background dynamic generation
Added better background tiling, dynamically generated with height in mind, automatically destroyed when out of sight
| | |
| | | - {fileID: 690370498} |
| | | m_Father: {fileID: 1633192636} |
| | | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} |
| | | m_AnchorMin: {x: 0, y: 0} |
| | | m_AnchorMax: {x: 0, y: 0} |
| | | m_AnchoredPosition: {x: 0, y: 0} |
| | | m_SizeDelta: {x: 0, y: 0} |
| | | m_AnchorMin: {x: 0, y: 1} |
| | | m_AnchorMax: {x: 0, y: 1} |
| | | m_AnchoredPosition: {x: 799.99994, y: -475.2434} |
| | | m_SizeDelta: {x: 999.9999, y: 650.4868} |
| | | m_Pivot: {x: 0.5, y: 0.5} |
| | | --- !u!114 &257770452 |
| | | MonoBehaviour: |
| | |
| | | - {fileID: 162135952} |
| | | m_Father: {fileID: 257770451} |
| | | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} |
| | | m_AnchorMin: {x: 0, y: 0} |
| | | m_AnchorMax: {x: 0, y: 0} |
| | | m_AnchoredPosition: {x: 0, y: 0} |
| | | m_SizeDelta: {x: 0, y: 0} |
| | | m_AnchorMin: {x: 0, y: 1} |
| | | m_AnchorMax: {x: 0, y: 1} |
| | | m_AnchoredPosition: {x: 336.83328, y: -325.2434} |
| | | m_SizeDelta: {x: 593.66656, y: 570.4868} |
| | | m_Pivot: {x: 0.5, y: 0.5} |
| | | --- !u!114 &368852411 |
| | | MonoBehaviour: |
| | |
| | | m_Father: {fileID: 2009171746} |
| | | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} |
| | | m_AnchorMin: {x: 0, y: 0} |
| | | m_AnchorMax: {x: 0, y: 0} |
| | | m_AnchorMax: {x: 1, y: 1} |
| | | m_AnchoredPosition: {x: 0.000030517578, y: -0.49996948} |
| | | m_SizeDelta: {x: 20, y: 0.80810547} |
| | | m_Pivot: {x: 0.5, y: 0.5} |
| | |
| | | m_Children: [] |
| | | m_Father: {fileID: 257770451} |
| | | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} |
| | | m_AnchorMin: {x: 0, y: 0} |
| | | m_AnchorMax: {x: 0, y: 0} |
| | | m_AnchoredPosition: {x: 0, y: 0} |
| | | m_SizeDelta: {x: 0, y: 0} |
| | | m_AnchorMin: {x: 0, y: 1} |
| | | m_AnchorMax: {x: 0, y: 1} |
| | | m_AnchoredPosition: {x: 801.83325, y: -325.2434} |
| | | m_SizeDelta: {x: 316.3333, y: 570.4868} |
| | | m_Pivot: {x: 0.5, y: 0.5} |
| | | --- !u!114 &690370499 |
| | | MonoBehaviour: |
| | |
| | | m_Icon: {fileID: 0} |
| | | m_NavMeshLayer: 0 |
| | | m_StaticEditorFlags: 0 |
| | | m_IsActive: 1 |
| | | m_IsActive: 0 |
| | | --- !u!4 &734382261 |
| | | Transform: |
| | | m_ObjectHideFlags: 0 |
| | |
| | | m_EditorClassIdentifier: |
| | | offsetX: 2 |
| | | offsetY: 2 |
| | | heightSprites: [] |
| | | hasRightBuddy: 0 |
| | | hasLeftBuddy: 0 |
| | | hasTopBuddy: 1 |
| | |
| | | m_Icon: {fileID: 0} |
| | | m_NavMeshLayer: 0 |
| | | m_StaticEditorFlags: 0 |
| | | m_IsActive: 1 |
| | | m_IsActive: 0 |
| | | --- !u!4 &1049982787 |
| | | Transform: |
| | | m_ObjectHideFlags: 0 |
| | |
| | | m_EditorClassIdentifier: |
| | | offsetX: 2 |
| | | offsetY: 2 |
| | | heightSprites: [] |
| | | hasRightBuddy: 0 |
| | | hasLeftBuddy: 0 |
| | | hasTopBuddy: 0 |
| | |
| | | m_AnchorMin: {x: 0, y: 0} |
| | | m_AnchorMax: {x: 1, y: 1} |
| | | m_AnchoredPosition: {x: 0, y: 0} |
| | | m_SizeDelta: {x: 0, y: 0} |
| | | m_SizeDelta: {x: 0, y: -490.48682} |
| | | m_Pivot: {x: 0, y: 1} |
| | | --- !u!114 &1165757303 |
| | | MonoBehaviour: |
| | |
| | | - component: {fileID: 1223747240} |
| | | - component: {fileID: 1223747239} |
| | | - component: {fileID: 1223747241} |
| | | m_Layer: 0 |
| | | m_Name: Sky |
| | | - component: {fileID: 1223747242} |
| | | m_Layer: 11 |
| | | m_Name: BackgroundAll |
| | | m_TagString: Untagged |
| | | m_Icon: {fileID: 0} |
| | | m_NavMeshLayer: 0 |
| | |
| | | m_GameObject: {fileID: 1223747237} |
| | | serializedVersion: 2 |
| | | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} |
| | | m_LocalPosition: {x: 0, y: 68, z: -2} |
| | | m_LocalScale: {x: 10, y: 10, z: 1} |
| | | m_LocalPosition: {x: 0, y: 6, z: -2} |
| | | m_LocalScale: {x: 1, y: 1, z: 1} |
| | | m_ConstrainProportionsScale: 0 |
| | | m_Children: [] |
| | | m_Father: {fileID: 796676099} |
| | |
| | | m_Script: {fileID: 11500000, guid: bff9938391d7202429e3508a7efde6eb, type: 3} |
| | | m_Name: |
| | | m_EditorClassIdentifier: |
| | | offsetX: 2 |
| | | offsetY: 2 |
| | | offsetX: 0 |
| | | offsetY: 0 |
| | | heightSprites: |
| | | - minHeight: 6 |
| | | maxHeight: 200 |
| | | sprite: {fileID: 21300000, guid: 7d5be99b0261348468ab492c35422f1b, type: 3} |
| | | - minHeight: -200 |
| | | maxHeight: -8 |
| | | sprite: {fileID: 21300000, guid: 58a6eeb45a0e2674ab35114433129f28, type: 3} |
| | | hasRightBuddy: 0 |
| | | hasLeftBuddy: 0 |
| | | hasTopBuddy: 0 |
| | | hasBottomBuddy: 1 |
| | | hasBottomBuddy: 0 |
| | | reverseScale: 1 |
| | | --- !u!61 &1223747242 |
| | | BoxCollider2D: |
| | | m_ObjectHideFlags: 0 |
| | | m_CorrespondingSourceObject: {fileID: 0} |
| | | m_PrefabInstance: {fileID: 0} |
| | | m_PrefabAsset: {fileID: 0} |
| | | m_GameObject: {fileID: 1223747237} |
| | | m_Enabled: 1 |
| | | m_Density: 1 |
| | | m_Material: {fileID: 0} |
| | | m_IncludeLayers: |
| | | serializedVersion: 2 |
| | | m_Bits: 0 |
| | | m_ExcludeLayers: |
| | | serializedVersion: 2 |
| | | m_Bits: 0 |
| | | m_LayerOverridePriority: 0 |
| | | m_ForceSendLayers: |
| | | serializedVersion: 2 |
| | | m_Bits: 4294967295 |
| | | m_ForceReceiveLayers: |
| | | serializedVersion: 2 |
| | | m_Bits: 4294967295 |
| | | m_ContactCaptureLayers: |
| | | serializedVersion: 2 |
| | | m_Bits: 4294967295 |
| | | m_CallbackLayers: |
| | | serializedVersion: 2 |
| | | m_Bits: 4294967295 |
| | | m_IsTrigger: 1 |
| | | m_UsedByEffector: 0 |
| | | m_UsedByComposite: 0 |
| | | m_Offset: {x: 0, y: 0} |
| | | m_SpriteTilingProperty: |
| | | border: {x: 0, y: 0, z: 0, w: 0} |
| | | pivot: {x: 0.5, y: 0.5} |
| | | oldSize: {x: 25, y: 14.0625} |
| | | newSize: {x: 84.12234, y: 61.8624} |
| | | adaptiveTilingThreshold: 0.349 |
| | | drawMode: 0 |
| | | adaptiveTiling: 0 |
| | | m_AutoTiling: 0 |
| | | serializedVersion: 2 |
| | | m_Size: {x: 25, y: 14.0625} |
| | | m_EdgeRadius: 0 |
| | | --- !u!1 &1235149190 |
| | | GameObject: |
| | | m_ObjectHideFlags: 0 |
| | |
| | | m_Icon: {fileID: 0} |
| | | m_NavMeshLayer: 0 |
| | | m_StaticEditorFlags: 0 |
| | | m_IsActive: 1 |
| | | m_IsActive: 0 |
| | | --- !u!224 &1633192636 |
| | | RectTransform: |
| | | m_ObjectHideFlags: 0 |
| | |
| | | m_Icon: {fileID: 0} |
| | | m_NavMeshLayer: 0 |
| | | m_StaticEditorFlags: 0 |
| | | m_IsActive: 1 |
| | | m_IsActive: 0 |
| | | --- !u!4 &2045670860 |
| | | Transform: |
| | | m_ObjectHideFlags: 0 |
| | |
| | | m_GameObject: {fileID: 2045670859} |
| | | serializedVersion: 2 |
| | | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} |
| | | m_LocalPosition: {x: 0, y: -72, z: -1} |
| | | m_LocalScale: {x: 10, y: 10, z: 1} |
| | | m_LocalPosition: {x: 0, y: -7, z: -1} |
| | | m_LocalScale: {x: 1, y: 1, z: 1} |
| | | m_ConstrainProportionsScale: 0 |
| | | m_Children: [] |
| | | m_Father: {fileID: 796676099} |
| | |
| | | m_EditorClassIdentifier: |
| | | offsetX: 2 |
| | | offsetY: 2 |
| | | heightSprites: [] |
| | | hasRightBuddy: 0 |
| | | hasLeftBuddy: 0 |
| | | hasTopBuddy: 1 |
| | | hasTopBuddy: 0 |
| | | hasBottomBuddy: 0 |
| | | reverseScale: 1 |
| | | --- !u!1 &2064964499 |
| | |
| | | objectReference: {fileID: 0} |
| | | - target: {fileID: 6633370595712293001, guid: e3c75e717a72154478a8806cd96eb126, type: 3} |
| | | propertyPath: m_AnchoredPosition.x |
| | | value: 288.33334 |
| | | value: 288.33328 |
| | | objectReference: {fileID: 0} |
| | | - target: {fileID: 6633370595712293001, guid: e3c75e717a72154478a8806cd96eb126, type: 3} |
| | | propertyPath: m_AnchoredPosition.y |
| | |
| | | |
| | | private void Awake() |
| | | { |
| | | if(Debug.isDebugBuild) |
| | | { |
| | | moveSpeed = 25f; |
| | | } |
| | | rb = GetComponent<Rigidbody2D>(); |
| | | animator = GetComponent<Animator>(); |
| | | animator_rotor = rotorGO.GetComponent<Animator>(); |
| | |
| | | [RequireComponent(typeof(SpriteRenderer))] |
| | | public class Tiling : MonoBehaviour |
| | | { |
| | | [System.Serializable] |
| | | public class HeightSpritePair |
| | | { |
| | | public float minHeight; |
| | | public float maxHeight; |
| | | public Sprite sprite; |
| | | } |
| | | |
| | | public int offsetX = 2; |
| | | public int offsetY = 2; |
| | | public HeightSpritePair[] heightSprites; |
| | | |
| | | public bool hasRightBuddy = false; |
| | | public bool hasLeftBuddy = false; |
| | |
| | | private float spriteHeight = 0f; |
| | | private Camera cam; |
| | | private Transform myTransform; |
| | | private SpriteRenderer spriteRenderer; |
| | | |
| | | private void Awake() |
| | | { |
| | | cam = Camera.main; |
| | | myTransform = transform; |
| | | spriteRenderer = GetComponent<SpriteRenderer>(); |
| | | } |
| | | // Start is called before the first frame update |
| | | |
| | | void Start() |
| | | { |
| | | SpriteRenderer spriteRenderer = GetComponent<SpriteRenderer>(); |
| | | UpdateSpriteForHeight(); |
| | | spriteWidth = spriteRenderer.sprite.bounds.size.x; |
| | | spriteHeight = spriteRenderer.sprite.bounds.size.y; |
| | | |
| | | //GenerateBackground(); |
| | | } |
| | | |
| | | // Update is called once per frame |
| | | void Update() |
| | | { |
| | | if (CheckOffscreenAndDestroy()) return; // Return early if destroyed |
| | | CheckHorizontalTiling(); |
| | | CheckVerticalTiling(); |
| | | } |
| | | |
| | | private void UpdateSpriteForHeight() |
| | | { |
| | | if (heightSprites == null || heightSprites.Length == 0) return; |
| | | |
| | | float worldY = transform.position.y; |
| | | Sprite oldSprite = spriteRenderer.sprite; |
| | | |
| | | foreach (HeightSpritePair pair in heightSprites) |
| | | { |
| | | if (pair.sprite == null) continue; // Skip invalid sprites |
| | | |
| | | if ((pair.minHeight == 0 && pair.maxHeight == 0) || |
| | | (worldY >= pair.minHeight && worldY <= pair.maxHeight)) |
| | | { |
| | | if (oldSprite != pair.sprite) |
| | | { |
| | | spriteRenderer.sprite = pair.sprite; |
| | | // Update sprite dimensions if sprite changed |
| | | spriteWidth = spriteRenderer.sprite.bounds.size.x; |
| | | spriteHeight = spriteRenderer.sprite.bounds.size.y; |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void CheckHorizontalTiling() |
| | | { |
| | | if (!hasLeftBuddy || !hasRightBuddy) |
| | | { |
| | | float camHorizontalExtend = cam.orthographicSize * Screen.width / Screen.height; |
| | | |
| | | float edgeVisiblePositionRight = (transform.position.x + spriteWidth / 2) - camHorizontalExtend; |
| | | float edgeVisiblePositionLeft = (transform.position.x - spriteWidth / 2) + camHorizontalExtend; |
| | | |
| | | if (cam.transform.position.x >= edgeVisiblePositionRight - offsetX && !hasRightBuddy) |
| | | { |
| | | MakeNewRightOrLeftBuddy(1); |
| | | MakeNewBuddy(1, 0); |
| | | hasRightBuddy = true; |
| | | } |
| | | else if (cam.transform.position.x <= edgeVisiblePositionLeft + offsetX && !hasLeftBuddy) |
| | | { |
| | | MakeNewRightOrLeftBuddy(-1); |
| | | MakeNewBuddy(-1, 0); |
| | | hasLeftBuddy = true; |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void MakeNewRightOrLeftBuddy(int rightOrLeft) |
| | | private void CheckVerticalTiling() |
| | | { |
| | | Vector3 newPosition = new Vector3(myTransform.position.x + spriteWidth * rightOrLeft, myTransform.position.y, myTransform.position.z); |
| | | if (!hasTopBuddy || !hasBottomBuddy) |
| | | { |
| | | float camVerticalExtend = cam.orthographicSize; |
| | | float edgeVisiblePositionTop = (transform.position.y + spriteHeight / 2) - camVerticalExtend; |
| | | float edgeVisiblePositionBottom = (transform.position.y - spriteHeight / 2) + camVerticalExtend; |
| | | |
| | | if (cam.transform.position.y >= edgeVisiblePositionTop - offsetY && !hasTopBuddy) |
| | | { |
| | | MakeNewBuddy(0, 1); |
| | | hasTopBuddy = true; |
| | | } |
| | | else if (cam.transform.position.y <= edgeVisiblePositionBottom + offsetY && !hasBottomBuddy) |
| | | { |
| | | MakeNewBuddy(0, -1); |
| | | hasBottomBuddy = true; |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void MakeNewBuddy(int rightOrLeft, int topOrBottom) |
| | | { |
| | | Vector3 newPosition = new Vector3( |
| | | myTransform.position.x + spriteWidth * rightOrLeft, |
| | | myTransform.position.y + spriteHeight * topOrBottom, |
| | | myTransform.position.z |
| | | ); |
| | | |
| | | Transform newBuddy = Instantiate(myTransform, newPosition, myTransform.rotation); |
| | | Tiling buddyTiling = newBuddy.GetComponent<Tiling>(); |
| | | |
| | | if (reverseScale) |
| | | { |
| | | newBuddy.localScale = new Vector3(newBuddy.localScale.x * -1, newBuddy.localScale.y, newBuddy.localScale.z); |
| | | newBuddy.localScale = new Vector3( |
| | | rightOrLeft != 0 ? newBuddy.localScale.x * -1 : newBuddy.localScale.x, |
| | | topOrBottom != 0 ? newBuddy.localScale.y * -1 : newBuddy.localScale.y, |
| | | newBuddy.localScale.z |
| | | ); |
| | | } |
| | | |
| | | newBuddy.parent = myTransform.parent; |
| | | newBuddy.name = myTransform.name; |
| | | |
| | | if (rightOrLeft > 0) |
| | | if (rightOrLeft > 0) buddyTiling.hasLeftBuddy = true; |
| | | else if (rightOrLeft < 0) buddyTiling.hasRightBuddy = true; |
| | | if (topOrBottom > 0) buddyTiling.hasBottomBuddy = true; |
| | | else if (topOrBottom < 0) buddyTiling.hasTopBuddy = true; |
| | | |
| | | buddyTiling.UpdateSpriteForHeight(); |
| | | } |
| | | |
| | | private bool CheckOffscreenAndDestroy() |
| | | { |
| | | Vector3 viewportPosition = cam.WorldToViewportPoint(transform.position); |
| | | float buffer = 1.5f; |
| | | |
| | | if (viewportPosition.x < -buffer || viewportPosition.x > 1 + buffer || |
| | | viewportPosition.y < -buffer || viewportPosition.y > 1 + buffer) |
| | | { |
| | | newBuddy.GetComponent<Tiling>().hasLeftBuddy = true; |
| | | NotifyNeighbors(); |
| | | Destroy(gameObject); |
| | | return true; |
| | | } |
| | | else if (rightOrLeft < 0) |
| | | return false; |
| | | } |
| | | private void NotifyNeighbors() |
| | | { |
| | | // Use a slightly smaller size than the sprite to ensure we only hit immediate neighbors |
| | | Vector2 checkSize = new Vector2(spriteWidth * 0.9f, spriteHeight * 0.9f); |
| | | Vector2 position = transform.position; |
| | | ContactFilter2D filter = new ContactFilter2D().NoFilter(); |
| | | Collider2D[] results = new Collider2D[1]; |
| | | |
| | | // Check each direction using OverlapBox |
| | | // Right neighbor |
| | | if (Physics2D.OverlapBox(position + new Vector2(spriteWidth, 0), |
| | | checkSize, 0f, |
| | | filter, results) > 0) |
| | | { |
| | | newBuddy.GetComponent<Tiling>().hasRightBuddy = true; |
| | | Tiling rightTile = results[0].GetComponent<Tiling>(); |
| | | if (rightTile != null) rightTile.hasLeftBuddy = false; |
| | | } |
| | | |
| | | // Left neighbor |
| | | if (Physics2D.OverlapBox(position + new Vector2(-spriteWidth, 0), |
| | | checkSize, 0f, |
| | | filter, results) > 0) |
| | | { |
| | | Tiling leftTile = results[0].GetComponent<Tiling>(); |
| | | if (leftTile != null) leftTile.hasRightBuddy = false; |
| | | } |
| | | |
| | | // Top neighbor |
| | | if (Physics2D.OverlapBox(position + new Vector2(0, spriteHeight), |
| | | checkSize, 0f, |
| | | filter, results) > 0) |
| | | { |
| | | Tiling topTile = results[0].GetComponent<Tiling>(); |
| | | if (topTile != null) topTile.hasBottomBuddy = false; |
| | | } |
| | | |
| | | // Bottom neighbor |
| | | if (Physics2D.OverlapBox(position + new Vector2(0, -spriteHeight), |
| | | checkSize, 0f, |
| | | filter, results) > 0) |
| | | { |
| | | Tiling bottomTile = results[0].GetComponent<Tiling>(); |
| | | if (bottomTile != null) bottomTile.hasTopBuddy = false; |
| | | } |
| | | } |
| | | //private void OnDrawGizmos() |
| | | //{ |
| | | // if (!Application.isPlaying) return; |
| | | |
| | | // Vector2 checkSize = new Vector2(spriteWidth * 0.9f, spriteHeight * 0.9f); |
| | | // Gizmos.color = Color.yellow; |
| | | |
| | | // // Draw detection boxes for each direction |
| | | // Gizmos.DrawWireCube((Vector2)transform.position + new Vector2(spriteWidth, 0), checkSize); |
| | | // Gizmos.DrawWireCube((Vector2)transform.position + new Vector2(-spriteWidth, 0), checkSize); |
| | | // Gizmos.DrawWireCube((Vector2)transform.position + new Vector2(0, spriteHeight), checkSize); |
| | | // Gizmos.DrawWireCube((Vector2)transform.position + new Vector2(0, -spriteHeight), checkSize); |
| | | //} |
| | | } |
| | |
| | | - PlayerHitbox |
| | | - GroundDetection |
| | | - Pickup |
| | | - |
| | | - Background |
| | | - |
| | | - |
| | | - |