-
Notifications
You must be signed in to change notification settings - Fork 6
/
Prototype.cs
115 lines (91 loc) · 2.94 KB
/
Prototype.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
using UnityEngine;
using System.Collections.Generic;
using System;
/// <summary>
/// Convenience way to create objects in the hierarchy that are a bit like prefabs, except that they
/// aren't. They exist in the scene, immediately deactivate themselves, then provide an easy way to
/// instantiate a copy in the same place in the hierarchy.
/// If you call ReturnToPool() once you're done with the instance, then it's returned
/// to the original prototype to be reused if necessary instead of creating a brand new GameObject.
/// </summary>
public class Prototype : MonoBehaviour {
public event Action OnReturnToPool;
public bool isOriginalPrototype {
get {
return _originalPrototype == null;
}
}
public Prototype originalPrototype {
get {
return _originalPrototype;
}
}
void Start()
{
if( isOriginalPrototype )
this.gameObject.SetActive(false);
}
void OnDestroy()
{
if( _instancePool != null )
foreach(var inst in _instancePool)
Destroy(inst);
}
public T Instantiate<T>() where T : Component
{
Prototype instance = null;
// Re-use instance from pool
if( _instancePool != null && _instancePool.Count > 0 ) {
var instanceIdx = _instancePool.Count-1;
instance = _instancePool[instanceIdx];
_instancePool.RemoveAt(instanceIdx);
}
// Instantiate fresh instance
else {
instance = UnityEngine.Object.Instantiate(this);
instance.transform.SetParent(transform.parent, worldPositionStays:false);
var protoRT = transform as RectTransform;
if( protoRT ) {
var instRT = instance.transform as RectTransform;
instRT.anchorMin = protoRT.anchorMin;
instRT.anchorMax = protoRT.anchorMax;
instRT.pivot = protoRT.pivot;
instRT.sizeDelta = protoRT.sizeDelta;
}
instance.transform.localPosition = transform.localPosition;
instance.transform.localRotation = transform.localRotation;
instance.transform.localScale = transform.localScale;
instance._originalPrototype = this;
}
instance.gameObject.SetActive(true);
return instance.GetComponent<T>();
}
public void ReturnToPool()
{
if( isOriginalPrototype ) {
Debug.LogError("Can't return to pool because the original prototype doesn't exist. Is this prototype the original?");
Destroy(gameObject);
return;
}
_originalPrototype.AddToPool(this);
}
public T GetOriginal<T>()
{
if( isOriginalPrototype )
return GetComponent<T>();
else
return originalPrototype.GetComponent<T>();
}
void AddToPool(Prototype instancePrototype)
{
if( !isOriginalPrototype )
Debug.LogError("Adding "+instancePrototype.name+" to prototype pool of "+this.name+" but this appears to be an instance itself?");
instancePrototype.gameObject.SetActive(false);
if( _instancePool == null ) _instancePool = new List<Prototype>();
_instancePool.Add(instancePrototype);
if( instancePrototype.OnReturnToPool != null )
instancePrototype.OnReturnToPool();
}
Prototype _originalPrototype;
List<Prototype> _instancePool;
}