- Home /
prefab instantiated by script containing ShadowCaster2D bugs out
Hey,
i wrote a script that creates shadow casters for a tilemap-grid. The generation is triggered by a button press from the inspector. Since i was unable to figure out how to manipulate the "shape" of a given ShadowCaster2D from script, i made a prefab that has a 1 by 1 ShadowCaster2D attached, instantiate that from my script and set the scale and position. It works fine, the screenshot shows the result of such a generation. However, when i try to manipulate the shape by hand afterwards, i am unable to generate new nodes, and the nodes i try to reposition snap to the gameobjects origin and stay there. When placing and scaling up instances of the prefab manually, it works fine. Is this a bug with prefab instantiation and the ShadowCaster2D's shape-thingy?
So my question is: Any ideas on how to fix that? My original goal was to generate the shadow casters in a way so that i can tweak them by hand afterwards if i desire.
I also have trouble how to make the editor save the instances. i tried to do a Undo.RecordObject on them afterwards, and tried moving the generate code into the button that triggers if, both of which failed to achive permanence. but thats a side-problem, help would be appreciated anyway.
I think many people would potentially be interested in a script like this, when it first successfully generated the shadow casters i was eager to tell the forums about it :) But right now its of limited use. I really hope someone can help me fix this.
Here's a screenshot of the generated shadow casters:

Here is how i instantiate the prefab:
 currentInstance = (GameObject)PrefabUtility.InstantiatePrefab(shadowCasterPrefab, shadowCastersContainer);
Here's the complete script:
 using UnityEngine;
 using UnityEditor;
 using System.Collections.Generic;
 
 public class GridShadowCastersGenerator : MonoBehaviour {
 
     public string colliderTag = "GenerateShadowCasters";
     public GameObject shadowCasterPrefab;
     public Transform shadowCastersContainer;
     public bool removePreviouslyGenerated = true;
 
     bool[,] hits;
     GameObject[,] instances;
 
     public GameObject[] Generate() {
         Debug.Log("### Generating ShadowCasters ###");
 
         /* get the bounds of the area to check */
 
         // collect colliders specified by tag
 
         var colliders = new List<Collider2D>();
         var tagedGos = GameObject.FindGameObjectsWithTag(colliderTag);
 
         foreach (var go in tagedGos) {
             var goColliders = go.GetComponents<Collider2D>();
 
             foreach (var goc in goColliders) {
                 colliders.Add(goc);
             }
         }
 
         if (colliders.Count == 0) {
             Debug.Log("No colliders found, aborting.");
             return new GameObject[0];
         }
 
         // get outer-most bound vertices, defining the area to check
 
         var bottomLeft = new Vector2(Mathf.Infinity, Mathf.Infinity);
         var topRight = new Vector2(-Mathf.Infinity, -Mathf.Infinity);
 
         foreach (var col in colliders) {
             bottomLeft.x = Mathf.Min(bottomLeft.x, Mathf.Floor(col.bounds.min.x));
             bottomLeft.y = Mathf.Min(bottomLeft.y, Mathf.Floor(col.bounds.min.y));
             topRight.x = Mathf.Max(topRight.x, Mathf.Ceil(col.bounds.max.x));
             topRight.y = Mathf.Max(topRight.y, Mathf.Ceil(col.bounds.max.y));
         }
 
         Debug.Log("Bounds: downLeft = (" + bottomLeft.x + ", " + bottomLeft.y + ")");
         Debug.Log("Bounds: topRight = (" + topRight.x + ", " + topRight.y + ")");
 
         /* check the area for collisions */
 
         var countX = Mathf.RoundToInt(topRight.x - bottomLeft.x);
         var countY = Mathf.RoundToInt(topRight.y - bottomLeft.y);
 
         hits = new bool[countX, countY];
         instances = new GameObject[countX, countY];
 
         for (int y = 0; y < countY; y++) {
             for (int x = 0; x < countX; x++) {
                 hits[x, y] = IsHit(new Vector2(bottomLeft.x + x + 0.5f, bottomLeft.y + y + 0.5f));
             }
         }
 
         /* instantiate shadow casters, merging single tiles horizontaly */
 
         // removing old shadow casters! careful!
 
         if (removePreviouslyGenerated) {
             foreach (Transform shadowCaster in shadowCastersContainer) {
                 DestroyImmediate(shadowCaster.gameObject);
             }
         }
 
         // create new ones
 
         for (int y = 0; y < countY; y++) {
             var previousWasHit = false;
             GameObject currentInstance = null;
 
             for (int x = 0; x < countX; x++) {
                 if (hits[x, y]) {
                     if (!previousWasHit) {
                         // create new shadowCasterPrefab instance
 
                         //currentInstance = (GameObject)Instantiate(shadowCasterPrefab, shadowCastersContainer.transform);
                         currentInstance = (GameObject)PrefabUtility.InstantiatePrefab(shadowCasterPrefab, shadowCastersContainer);
 
                         currentInstance.transform.position = new Vector3(bottomLeft.x + x + 0.5f, bottomLeft.y + y + 0.5f, 0.0f);
                     } else {
                         // stretch prevois shadowCasterPrefab instance
                         var newWidth = currentInstance.transform.localScale.x + 1.0f;
 
                         currentInstance.transform.localScale = new Vector3(newWidth, 1.0f, 0.0f);
                         currentInstance.transform.Translate(new Vector3(0.5f, 0.0f, 0.0f));
                     }
 
                     instances[x, y] = currentInstance;
                     previousWasHit = true;
                 } else {
                     previousWasHit = false;
                 }
             }
         }
 
         /* merge vertically if they have the same dimensions */
 
         for (int y = 0; y < countY - 1; y++) { // -1 for skipping last row
             for (int x = 0; x < countX; x++) {
                 if (instances[x, y] != null && instances[x, y + 1] != null) {
                     var topInstance = instances[x, y];
                     var bottomInstance = instances[x, y + 1];
 
                     if (topInstance != bottomInstance && topInstance.transform.localScale.x == bottomInstance.transform.localScale.x) {
                         //merge! enlarge top instance...
 
                         topInstance.transform.localScale = new Vector3(topInstance.transform.localScale.x, topInstance.transform.localScale.y + 1.0f, 0.0f);
                         topInstance.transform.Translate(new Vector3(0.0f, 0.5f, 0.0f));
 
                         // ...destroy bottom instance, save to instances array
 
                         for (var i = 0; i < Mathf.RoundToInt(bottomInstance.transform.localScale.x); i++) {
                             instances[x + i, y + 1] = instances[x + i, y];
                         }
 
                         DestroyImmediate(bottomInstance);
                     }
                 }
             }
         }
 
         Debug.Log("ShadowCasters generated.");
 
         /* return shadow casters */
 
         var shadowCasterInstances = new List<GameObject>();
 
         for (int y = 0; y < countY; y++) {
             for (int x = 0; x < countX; x++) {
                 if (instances[x, y] != null && !shadowCasterInstances.Contains(instances[x, y])) {
                     shadowCasterInstances.Add(instances[x, y]);
                     instances[x, y].name = instances[x, y].name + "_" + shadowCasterInstances.Count.ToString();
                 }
             }
         }
 
         return shadowCasterInstances.ToArray();
     }
 
     bool IsHit(Vector2 pos) {
         var margin = .2f; // prevents overlapping
 
         // get tile bounds
 
         var bottomLeft = new Vector2(pos.x - 0.5f + margin, pos.y + 0.5f - margin);
         var topRight = new Vector2(pos.x + 0.5f - margin, pos.y - 0.5f + margin);
 
         //check for collisions
 
         Collider2D[] colliders = Physics2D.OverlapAreaAll(bottomLeft, topRight);
 
         foreach (var col in colliders) {
             if (col.CompareTag(colliderTag)) {
                 return true;
             }
         }
 
         return false;
     }
 }
 
 [CustomEditor(typeof(GridShadowCastersGenerator))]
 public class GridShadowCastersGeneratorEditor : Editor {
 
     public override void OnInspectorGUI() {
         DrawDefaultInspector();
 
         if (GUILayout.Button("Generate")) {
             var generator = (GridShadowCastersGenerator)target;
 
             Undo.RecordObject(generator.shadowCastersContainer, "GridShadowCastersGenerator.generate");
             generator.Generate();
         }
     }
 }
 
Your answer
 
 
             Follow this Question
Related Questions
Infinity runner - best way to spawn board in runtime. 0 Answers
When flipping player, instantiated objects spawn on different spot. 2D shooting 0 Answers
How to move Instantiated 2D objects by 0.5 using arrows 1 Answer
Instantied 2D Prefab Is Invisible 1 Answer
How to instantiate and destroy objects with 2d trigger 1 Answer
 koobas.hobune.stream
koobas.hobune.stream 
                       
                
                       
			     
			 
                