Skip to content

Instantly share code, notes, and snippets.

@joonjoonjoon
Last active June 13, 2016 17:55
Show Gist options
  • Save joonjoonjoon/e451f30c1044483f1e8b6cf2d206d316 to your computer and use it in GitHub Desktop.
Save joonjoonjoon/e451f30c1044483f1e8b6cf2d206d316 to your computer and use it in GitHub Desktop.
A little workaround for the lack of nested prefabs.
*** THIS IS MADE FOR A SPECIFIC USE CASE AND WILL PROBABLY NEED TO BE EDITED ***
The use case for this is: imagine you have a tiled game board. You'd make every tile a prefab, right?
Now imagine you have a bunch of variations on the game board, that you also want to instantiate multiple times.
Now you have an issue. GlitchPrefab is a workaround for specifically that problem.
(It's called 'Glitch-' because it's made by us, Glitchnap)
How to use:
- Add the glitchprefab script to a gameobject
- Add a prefab to the glitchprefab.prefab public variable
- Make sure there's nothing else in the gameobject hierarchy, glitchprefab (preferably) deletes all children of the attached gameobject
- Now you can either manually use 'create' and 'remove' buttons on the glitchprefab component, or refresh all of your (nested) glitchprefabs with the menu item: GlitchLibrary > Glitchprefab Refresh All
I'll gladly help out whoever wants to use this, contact me on twitter @joonturbo or email [email protected]
using UnityEngine;
using System.Collections;
[ScriptOrder(-300)]
public class GlitchPrefab : MonoBehaviour {
public GameObject prefab;
[HideInInspector]
public GameObject lastInstance;
public bool triggerOnAwakeIfHasFirstChild = true;
public bool disableFirstChild=true;
public bool destroyFirstChild= true;
public bool disableScriptAfterRun = true;
public bool destroyScriptAfterRun = true;
public bool hasHappened =false;
public bool destroyPrefabInstance = true;
int count = 0;
void Awake()
{
if (!hasHappened )
{
if (triggerOnAwakeIfHasFirstChild || transform.childCount == 0)
{
hasHappened = true;
Instantiate();
}
}
}
public GameObject Instantiate()
{
if (disableFirstChild && transform.childCount > 0) transform.GetChild(0).gameObject.SetActive(false);
if (destroyFirstChild && transform.childCount > 0) Destroy(transform.GetChild(0).gameObject);
if (prefab == null) return null;
GameObject go = null;
if(Application.isPlaying)
{
go = Instantiate(prefab) as GameObject;
}
else
{
#if UNITY_EDITOR
if(UnityEditor.PrefabUtility.GetPrefabType(prefab) == UnityEditor.PrefabType.Prefab)
{
go = UnityEditor.PrefabUtility.InstantiatePrefab(prefab) as GameObject;
}
else
{
go = Instantiate(prefab) as GameObject;
//Debug.Log(UnityEditor.PrefabUtility.GetPrefabType(prefab));
}
#endif
}
go.transform.SetParent(transform);
go.transform.localPosition = prefab.transform.localPosition;
go.transform.localRotation = prefab.transform.localRotation;
go.transform.localScale = prefab.transform.localScale;
go.name = go.name.Replace("(Clone)", "");
count++;
var t = transform;
while (t.parent != null)
{
t = t.parent;
}
if (Application.isPlaying && disableScriptAfterRun) this.enabled = false;
if (Application.isPlaying && destroyScriptAfterRun)
{
Destroy(this);
}
if (destroyPrefabInstance)
{
#if UNITY_EDITOR
UnityEditor.PrefabUtility.DisconnectPrefabInstance(go);
#endif
}
return go;
}
public void DestroyLastInstance()
{
#if UNITY_EDITOR
DestroyImmediate(lastInstance);
#else
Destroy(lastInstance);
#endif
}
public void DestroyAllChildren()
{
transform.Clear();
DestroyLastInstance();
}
#if UNITY_EDITOR
[UnityEditor.MenuItem("GlitchLibrary/GlitchPrefab Refresh All")]
static void RefreshAll()
{
int counter = 0;
foreach (var root in UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects())
{
foreach (var glitchPrefab in root.GetComponentsInChildren<GlitchPrefab>(true))
{
glitchPrefab.DestroyLastInstance();
glitchPrefab.Instantiate();
counter++;
}
}
Debug.Log("Refreshed " + counter + " GlitchPrefabs.");
}
[UnityEditor.MenuItem("GlitchLibrary/GlitchPrefab Refresh All + Destroy All Children")]
static void RefreshAllAndDestroyChildren()
{
int counter = 0;
foreach (var root in UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects())
{
foreach (var glitchPrefab in root.GetComponentsInChildren<GlitchPrefab>(true))
{
glitchPrefab.DestroyAllChildren();
glitchPrefab.Instantiate();
counter++;
}
}
Debug.Log("Refreshed " + counter + " GlitchPrefabs.");
}
#endif
}
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
[CanEditMultipleObjects]
[CustomEditor(typeof(GlitchPrefab))]
public class GlitchPrefabEditor : Editor {
private bool dirty;
public override void OnInspectorGUI()
{
DrawDefaultInspector();
if (!Application.isPlaying)
{
if (GUILayout.Button("Create instance (" + targets.Length + ")"))
{
foreach (var item in targets)
{
var gp = (item as GlitchPrefab);
gp.Instantiate();
}
}
if ((targets.Length > 1 || (target as GlitchPrefab).lastInstance != null) && GUILayout.Button("Remove instance (" + targets.Length + ")"))
{
foreach (var item in targets)
{
var gp = (item as GlitchPrefab);
gp.DestroyLastInstance();
}
}
if (GUILayout.Button("Remove all children (" + targets.Length + ")"))
{
foreach (var item in targets)
{
var gp = (item as GlitchPrefab);
gp.DestroyAllChildren();
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment