├── .gitignore ├── Assets ├── ObserverPattern.meta ├── ObserverPattern │ ├── Example.meta │ ├── Example │ │ ├── CubeController.cs │ │ ├── CubeController.cs.meta │ │ ├── MyCube.cs │ │ ├── MyCube.cs.meta │ │ ├── New Material.mat │ │ ├── New Material.mat.meta │ │ ├── TestEvent.cs │ │ └── TestEvent.cs.meta │ ├── example │ │ ├── ObservePattern.unity │ │ └── ObservePattern.unity.meta │ ├── structure.meta │ └── structure │ │ ├── BaseBehavior.cs │ │ ├── BaseBehavior.cs.meta │ │ ├── ObserverPattern.cs │ │ ├── ObserverPattern.cs.meta │ │ ├── Singleton.cs │ │ └── Singleton.cs.meta ├── ObserverUnityPattern.meta ├── ObserverUnityPattern │ ├── Messages.meta │ ├── Messages │ │ ├── new_Message.asset │ │ └── new_Message.asset.meta │ ├── Scenes.meta │ ├── Scenes │ │ ├── OberverImplementation.unity │ │ └── OberverImplementation.unity.meta │ ├── Scripts.meta │ └── Scripts │ │ ├── Observer.meta │ │ ├── Observer │ │ ├── Message.meta │ │ ├── Message │ │ │ ├── Messages.cs │ │ │ └── Messages.cs.meta │ │ ├── Observers.cs │ │ └── Observers.cs.meta │ │ ├── Stream.meta │ │ └── Stream │ │ ├── Receiver.cs │ │ ├── Receiver.cs.meta │ │ ├── Sender.cs │ │ └── Sender.cs.meta ├── States.meta ├── States │ ├── Scenes.meta │ ├── Scenes │ │ ├── Example States Pattern.unity │ │ └── Example States Pattern.unity.meta │ ├── Scripts.meta │ └── Scripts │ │ ├── Exemples.meta │ │ ├── Exemples │ │ ├── Data.meta │ │ ├── Data │ │ │ ├── ExampleStateData.cs │ │ │ └── ExampleStateData.cs.meta │ │ ├── Editor.meta │ │ ├── Editor │ │ │ ├── ExampleStatesMachineEditor.cs │ │ │ └── ExampleStatesMachineEditor.cs.meta │ │ ├── ExampleStatesMachine.cs │ │ ├── ExampleStatesMachine.cs.meta │ │ ├── States.meta │ │ └── States │ │ │ ├── BlueColorState.cs │ │ │ ├── BlueColorState.cs.meta │ │ │ ├── RedColorState.cs │ │ │ └── RedColorState.cs.meta │ │ ├── States.meta │ │ └── States │ │ ├── IStates.cs │ │ ├── IStates.cs.meta │ │ ├── Machines.meta │ │ └── Machines │ │ ├── StatesMachine.cs │ │ └── StatesMachine.cs.meta ├── abstract factory.meta ├── abstract factory │ ├── example.meta │ ├── example │ │ ├── PrimitiveClient.cs │ │ ├── PrimitiveClient.cs.meta │ │ ├── PrimitiveFactory.cs │ │ ├── PrimitiveFactory.cs.meta │ │ ├── PrimitiveFactory2.cs │ │ ├── PrimitiveFactory2.cs.meta │ │ ├── PrimitiveFactoryAbstracts.cs │ │ ├── PrimitiveFactoryAbstracts.cs.meta │ │ ├── PrimitiveFactoryController.cs │ │ ├── PrimitiveFactoryController.cs.meta │ │ ├── abstract factory example.unity │ │ └── abstract factory example.unity.meta │ ├── readme.md │ ├── readme.md.meta │ ├── structure.meta │ └── structure │ │ ├── AbstractFactory.cs │ │ └── AbstractFactory.cs.meta ├── builder pattern.meta ├── builder pattern │ ├── example.meta │ ├── example │ │ ├── BuilderController.cs │ │ ├── BuilderController.cs.meta │ │ ├── BuilderExampleStructure.cs │ │ ├── BuilderExampleStructure.cs.meta │ │ ├── CarBuilder.cs │ │ ├── CarBuilder.cs.meta │ │ ├── MotorCycleBuilder.cs │ │ ├── MotorCycleBuilder.cs.meta │ │ ├── ScooterBuilder.cs │ │ ├── ScooterBuilder.cs.meta │ │ ├── builder_pattern_example.unity │ │ └── builder_pattern_example.unity.meta │ ├── readme.md │ ├── readme.md.meta │ ├── structure.meta │ └── structure │ │ ├── BuilderPattern.cs │ │ └── BuilderPattern.cs.meta ├── command pattern.meta ├── command pattern │ ├── Command.cs │ ├── Command.cs.meta │ ├── InputHandler.cs │ ├── InputHandler.cs.meta │ ├── MoveCommand.cs │ ├── MoveCommand.cs.meta │ ├── MoveCommandReceiver.cs │ ├── MoveCommandReceiver.cs.meta │ ├── README.md │ ├── README.md.meta │ ├── command pattern example.unity │ └── command pattern example.unity.meta ├── decorator.meta ├── decorator │ ├── example1.meta │ ├── example1 │ │ ├── MeleeAttack.cs │ │ ├── MeleeAttack.cs.meta │ │ ├── MeleeAttackClient.cs │ │ ├── MeleeAttackClient.cs.meta │ │ ├── melee_attack_decorator.unity │ │ └── melee_attack_decorator.unity.meta │ ├── readme.md │ ├── readme.md.meta │ ├── structure.meta │ └── structure │ │ ├── DecoratorParticipants.cs │ │ └── DecoratorParticipants.cs.meta ├── extras.meta ├── extras │ ├── 3D Text Shader.shader │ ├── 3D Text Shader.shader.meta │ ├── 3d font material.mat │ ├── 3d font material.mat.meta │ ├── ARIAL.TTF │ ├── ARIAL.TTF.meta │ ├── DestroyOnTime.cs │ ├── DestroyOnTime.cs.meta │ ├── ParticleSystemDebug.cs │ ├── ParticleSystemDebug.cs.meta │ ├── ground.mat │ └── ground.mat.meta ├── factory method pattern.meta ├── factory method pattern │ ├── example.meta │ ├── example │ │ ├── ConcreteDocuments.cs │ │ ├── ConcreteDocuments.cs.meta │ │ ├── ConcretePages.cs │ │ ├── ConcretePages.cs.meta │ │ ├── DocumentMaker.cs │ │ ├── DocumentMaker.cs.meta │ │ ├── FactoryMethodExampleAbstractions.cs │ │ ├── FactoryMethodExampleAbstractions.cs.meta │ │ ├── factory_method_pattern.unity │ │ └── factory_method_pattern.unity.meta │ ├── readme.md │ ├── readme.md.meta │ ├── structure.meta │ └── structure │ │ ├── FactoryMethodStructure.cs │ │ └── FactoryMethodStructure.cs.meta ├── flyweight pattern.meta ├── flyweight pattern │ ├── README.md │ ├── README.md.meta │ ├── example.meta │ ├── example │ │ ├── Insects.cs │ │ ├── Insects.cs.meta │ │ ├── InsectsFlyweightExample.cs │ │ ├── InsectsFlyweightExample.cs.meta │ │ ├── insects_flyweight_example.unity │ │ └── insects_flyweight_example.unity.meta │ ├── example2.meta │ ├── example2 │ │ ├── ConcreteSoldiers.cs │ │ ├── ConcreteSoldiers.cs.meta │ │ ├── ISoldierFlyweight.cs │ │ ├── ISoldierFlyweight.cs.meta │ │ ├── SoldierFlyweightFactory.cs │ │ ├── SoldierFlyweightFactory.cs.meta │ │ ├── SoldierGameObject.cs │ │ ├── SoldierGameObject.cs.meta │ │ ├── SoldierSceneController.cs │ │ ├── SoldierSceneController.cs.meta │ │ ├── soldier_flyweight_example.unity │ │ └── soldier_flyweight_example.unity.meta │ ├── structure.meta │ └── structure │ │ ├── ConcreteFlyweight.cs │ │ ├── ConcreteFlyweight.cs.meta │ │ ├── FlyweightBase.cs │ │ ├── FlyweightBase.cs.meta │ │ ├── FlyweightFactory.cs │ │ ├── FlyweightFactory.cs.meta │ │ ├── UnsharedFlyweight.cs │ │ └── UnsharedFlyweight.cs.meta ├── observer.meta ├── observer │ ├── ObserverStructure.cs │ └── ObserverStructure.cs.meta ├── singleton.meta ├── singleton │ ├── example.meta │ ├── example │ │ ├── GameManagerExample.unity │ │ ├── GameManagerExample.unity.meta │ │ ├── Prefabs.meta │ │ ├── Prefabs │ │ │ ├── GameManager.prefab │ │ │ ├── GameManager.prefab.meta │ │ │ ├── ManagerSpawner.prefab │ │ │ └── ManagerSpawner.prefab.meta │ │ ├── Scripts.meta │ │ └── Scripts │ │ │ ├── GameManager.cs │ │ │ ├── GameManager.cs.meta │ │ │ ├── ManagerSpawner.cs │ │ │ └── ManagerSpawner.cs.meta │ ├── structure.meta │ └── structure │ │ ├── Singleton.cs │ │ └── Singleton.cs.meta ├── strategy pattern.meta └── strategy pattern │ ├── StrategyPatternStructure.cs │ ├── StrategyPatternStructure.cs.meta │ ├── example_enemy_behavior.meta │ ├── example_enemy_behavior │ ├── EnemyBehaviour.cs │ ├── EnemyBehaviour.cs.meta │ ├── StrategyExampleMainApp.cs │ ├── StrategyExampleMainApp.cs.meta │ ├── strategy_pattern_example.unity │ └── strategy_pattern_example.unity.meta │ ├── example_output_string.meta │ ├── example_output_string │ ├── OutputStrategy.cs │ ├── OutputStrategy.cs.meta │ ├── OutputStrategyController.cs │ ├── OutputStrategyController.cs.meta │ ├── output_strategy.unity │ └── output_strategy.unity.meta │ ├── readme.md │ └── readme.md.meta ├── LICENSE ├── ProjectSettings ├── AudioManager.asset ├── ClusterInputManager.asset ├── DynamicsManager.asset ├── EditorBuildSettings.asset ├── EditorSettings.asset ├── GraphicsSettings.asset ├── InputManager.asset ├── NavMeshAreas.asset ├── NetworkManager.asset ├── Physics2DSettings.asset ├── ProjectSettings.asset ├── ProjectVersion.txt ├── QualitySettings.asset ├── TagManager.asset ├── TimeManager.asset ├── UnityAdsSettings.asset └── UnityConnectSettings.asset ├── README.md └── contributors.md /.gitignore: -------------------------------------------------------------------------------- 1 | [Ll]ibrary/ 2 | [Tt]emp/ 3 | [Oo]bj/ 4 | [Bb]uild/ 5 | 6 | # Autogenerated VS/MD solution and project files 7 | *.csproj 8 | *.unityproj 9 | *.sln 10 | *.suo 11 | *.tmp 12 | *.user 13 | *.userprefs 14 | *.pidb 15 | *.booproj 16 | 17 | # Unity3D generated meta files 18 | *.pidb.meta 19 | 20 | # Unity3D Generated File On Crash Reports 21 | sysinfo.txt 22 | Assets/UnityVS/ 23 | -------------------------------------------------------------------------------- /Assets/ObserverPattern.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a6ad9f449b1f10743b1c59ca71b0e98d 3 | folderAsset: yes 4 | timeCreated: 1481189121 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/ObserverPattern/Example.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5725dec185c997444a63f875cfb2d23c 3 | folderAsset: yes 4 | timeCreated: 1481189588 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/ObserverPattern/Example/CubeController.cs: -------------------------------------------------------------------------------- 1 | using NG.Patterns.Structure.ObserverPattern; 2 | using UnityEngine; 3 | 4 | namespace NG.Patterns.Structure.ObserverPatternExample 5 | { 6 | public class CubeController : MonoBehaviour 7 | { 8 | Observer observer; 9 | 10 | public MyCube myCube0; 11 | public MyCube myCube1; 12 | 13 | public void Awake() 14 | { 15 | observer = Observer.Instance; 16 | } 17 | 18 | // Use this for initialization 19 | void Start() 20 | { 21 | observer.AddListener(TestEvent.JUMP, myCube0, myCube0.Jump); 22 | observer.AddListener(TestEvent.JUMP, myCube1, myCube1.Jump); 23 | } 24 | 25 | // Update is called once per frame 26 | void Update() 27 | { 28 | if (Input.GetKeyDown(KeyCode.W)) 29 | { 30 | observer.SendMessage(TestEvent.JUMP, 200f); 31 | } 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /Assets/ObserverPattern/Example/CubeController.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 255073d423dd69e429d7205cc08ea2dc 3 | timeCreated: 1481193754 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/ObserverPattern/Example/MyCube.cs: -------------------------------------------------------------------------------- 1 | using NG.Patterns.Structure.ObserverPattern; 2 | using UnityEngine; 3 | 4 | namespace NG.Patterns.Structure.ObserverPatternExample 5 | { 6 | public class MyCube : BaseBehaviour 7 | { 8 | Rigidbody rigid; 9 | 10 | public int id; 11 | 12 | Observer observer; 13 | 14 | public void Awake() 15 | { 16 | observer = Observer.Instance; 17 | rigid = GetComponent(); 18 | } 19 | 20 | // Use this for initialization 21 | void Start() 22 | { 23 | observer.AddListener(TestEvent.CHANGE_COLOR, this, ChangeColor); 24 | } 25 | 26 | private void ChangeColor(ObservParam obj) 27 | { 28 | if (id != 0) 29 | { 30 | GetComponent().material.color = new Color(Random.Range(0.0f, 1f), Random.Range(0.0f, 1f), Random.Range(0.0f, 1f)); 31 | } 32 | } 33 | 34 | // Update is called once per frame 35 | void Update() 36 | { 37 | if (Input.GetKeyDown(KeyCode.C)) 38 | { 39 | observer.SendMessage(TestEvent.CHANGE_COLOR); 40 | } 41 | } 42 | 43 | public void Jump(ObservParam obj) 44 | { 45 | float param = (float)obj.data; 46 | rigid.AddForce(new Vector3(0, param, 0)); 47 | } 48 | } 49 | 50 | } 51 | 52 | -------------------------------------------------------------------------------- /Assets/ObserverPattern/Example/MyCube.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 60f5e05c9be99a64094281e8f3fb9ed3 3 | timeCreated: 1481193638 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/ObserverPattern/Example/New Material.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: New Material 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: 12 | m_LightmapFlags: 5 13 | m_CustomRenderQueue: -1 14 | stringTagMap: {} 15 | m_SavedProperties: 16 | serializedVersion: 2 17 | m_TexEnvs: 18 | data: 19 | first: 20 | name: _MainTex 21 | second: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | data: 26 | first: 27 | name: _BumpMap 28 | second: 29 | m_Texture: {fileID: 0} 30 | m_Scale: {x: 1, y: 1} 31 | m_Offset: {x: 0, y: 0} 32 | data: 33 | first: 34 | name: _DetailNormalMap 35 | second: 36 | m_Texture: {fileID: 0} 37 | m_Scale: {x: 1, y: 1} 38 | m_Offset: {x: 0, y: 0} 39 | data: 40 | first: 41 | name: _ParallaxMap 42 | second: 43 | m_Texture: {fileID: 0} 44 | m_Scale: {x: 1, y: 1} 45 | m_Offset: {x: 0, y: 0} 46 | data: 47 | first: 48 | name: _OcclusionMap 49 | second: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | data: 54 | first: 55 | name: _EmissionMap 56 | second: 57 | m_Texture: {fileID: 0} 58 | m_Scale: {x: 1, y: 1} 59 | m_Offset: {x: 0, y: 0} 60 | data: 61 | first: 62 | name: _DetailMask 63 | second: 64 | m_Texture: {fileID: 0} 65 | m_Scale: {x: 1, y: 1} 66 | m_Offset: {x: 0, y: 0} 67 | data: 68 | first: 69 | name: _DetailAlbedoMap 70 | second: 71 | m_Texture: {fileID: 0} 72 | m_Scale: {x: 1, y: 1} 73 | m_Offset: {x: 0, y: 0} 74 | data: 75 | first: 76 | name: _MetallicGlossMap 77 | second: 78 | m_Texture: {fileID: 0} 79 | m_Scale: {x: 1, y: 1} 80 | m_Offset: {x: 0, y: 0} 81 | m_Floats: 82 | data: 83 | first: 84 | name: _SrcBlend 85 | second: 1 86 | data: 87 | first: 88 | name: _DstBlend 89 | second: 0 90 | data: 91 | first: 92 | name: _Cutoff 93 | second: 0.5 94 | data: 95 | first: 96 | name: _Parallax 97 | second: 0.02 98 | data: 99 | first: 100 | name: _ZWrite 101 | second: 1 102 | data: 103 | first: 104 | name: _Glossiness 105 | second: 0.5 106 | data: 107 | first: 108 | name: _BumpScale 109 | second: 1 110 | data: 111 | first: 112 | name: _OcclusionStrength 113 | second: 1 114 | data: 115 | first: 116 | name: _DetailNormalMapScale 117 | second: 1 118 | data: 119 | first: 120 | name: _UVSec 121 | second: 0 122 | data: 123 | first: 124 | name: _Mode 125 | second: 0 126 | data: 127 | first: 128 | name: _Metallic 129 | second: 0 130 | m_Colors: 131 | data: 132 | first: 133 | name: _EmissionColor 134 | second: {r: 0, g: 0, b: 0, a: 1} 135 | data: 136 | first: 137 | name: _Color 138 | second: {r: 0.97794116, g: 0.028763002, b: 0.028763002, a: 1} 139 | -------------------------------------------------------------------------------- /Assets/ObserverPattern/Example/New Material.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 245bab9afb5519d439d848b1211bf36a 3 | timeCreated: 1481284964 4 | licenseType: Free 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/ObserverPattern/Example/TestEvent.cs: -------------------------------------------------------------------------------- 1 | namespace NG.Patterns.Structure.ObserverPatternExample 2 | { 3 | public enum TestEvent 4 | { 5 | JUMP, 6 | CHANGE_COLOR 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Assets/ObserverPattern/Example/TestEvent.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 01a7d6ae24de9694b8fcd3b9707c1e26 3 | timeCreated: 1481193922 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/ObserverPattern/example/ObservePattern.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7895cb559a590b34f845ef797d0d31f9 3 | timeCreated: 1481284780 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/ObserverPattern/structure.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f2a9af6d50cc42b409e0a1b43ac767ce 3 | folderAsset: yes 4 | timeCreated: 1481283623 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/ObserverPattern/structure/BaseBehavior.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace NG.Patterns.Structure.ObserverPattern 5 | { 6 | public class BaseBehaviour : MonoBehaviour 7 | { 8 | internal void OnHandlerMessage(ObservParam observParam, Action value) 9 | { 10 | value(observParam); 11 | } 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /Assets/ObserverPattern/structure/BaseBehavior.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8c2ffed1e74cc4b449aa6a88ad0ffd08 3 | timeCreated: 1481189301 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/ObserverPattern/structure/ObserverPattern.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace NG.Patterns.Structure.ObserverPattern 6 | { 7 | public class ObservParam 8 | { 9 | public object data; 10 | public object key; 11 | } 12 | 13 | public class Observer : Singleton 14 | { 15 | public Dictionary, BaseBehaviour>> observList = new Dictionary, BaseBehaviour>>(); 16 | 17 | public void AddListener(object key, BaseBehaviour obj, Action callback) 18 | { 19 | if (!observList.ContainsKey(key)) 20 | { 21 | Dictionary, BaseBehaviour> actions = new Dictionary, BaseBehaviour>(); 22 | actions.Add(callback, obj); 23 | observList.Add(key, actions); 24 | } 25 | else 26 | { 27 | observList[key].Add(callback, obj); 28 | } 29 | } 30 | 31 | public void SendMessage(object key) 32 | { 33 | if (observList.ContainsKey(key)) 34 | { 35 | ObservParam observParam = new ObservParam(); 36 | observParam.data = null; 37 | observParam.key = key; 38 | Dictionary, BaseBehaviour> actions = observList[key]; 39 | 40 | for (int i = 0; i < actions.Count; i++) 41 | { 42 | BaseBehaviour tmpBehavior = actions.Values.ElementAt(i); 43 | tmpBehavior.OnHandlerMessage(observParam, actions.Keys.ElementAt(i)); 44 | } 45 | } 46 | } 47 | 48 | public void SendMessage(object key, object param) 49 | { 50 | if (observList.ContainsKey(key)) 51 | { 52 | ObservParam observParam = new ObservParam(); 53 | observParam.data = param; 54 | observParam.key = key; 55 | Dictionary, BaseBehaviour> actions = observList[key]; 56 | 57 | for (int i = 0; i < actions.Count; i++) 58 | { 59 | BaseBehaviour tmpBehavior = actions.Values.ElementAt(i); 60 | tmpBehavior.OnHandlerMessage(observParam, actions.Keys.ElementAt(i)); 61 | } 62 | } 63 | } 64 | 65 | public void RemoveListener(object key, BaseBehaviour obj, Action callback) 66 | { 67 | if (observList.ContainsKey(key)) 68 | { 69 | Dictionary, BaseBehaviour> actions = observList[key]; 70 | for (int i = 0; i < actions.Count; i++) 71 | { 72 | if (actions.Keys.ElementAt(i) == callback && actions.Values.ElementAt(i) == obj) 73 | { 74 | actions.Remove(callback); 75 | } 76 | } 77 | } 78 | } 79 | 80 | public void RemoveAllListeners(BaseBehaviour obj) 81 | { 82 | foreach (KeyValuePair, BaseBehaviour>> item in observList) 83 | { 84 | Dictionary, BaseBehaviour> actions = item.Value; 85 | if (actions.ContainsValue(obj)) 86 | { 87 | for (int i = 0; i < actions.Count; i++) 88 | { 89 | if (actions.Values.ElementAt(i) == obj) 90 | { 91 | actions.Remove(actions.Keys.ElementAt(i)); 92 | } 93 | } 94 | } 95 | } 96 | } 97 | } 98 | } 99 | 100 | -------------------------------------------------------------------------------- /Assets/ObserverPattern/structure/ObserverPattern.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c9859d71736136d4993368eea390e207 3 | timeCreated: 1481189574 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/ObserverPattern/structure/Singleton.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | /// 4 | /// Be aware this will not prevent a non singleton constructor 5 | /// such as `T myT = new T();` 6 | /// To prevent that, add `protected T () {}` to your singleton class. 7 | /// 8 | /// As a note, this is made as MonoBehaviour because we need Coroutines. 9 | /// 10 | 11 | namespace NG.Patterns.Structure.ObserverPattern 12 | { 13 | public class Singleton : MonoBehaviour where T : MonoBehaviour 14 | { 15 | private static T _instance; 16 | 17 | private static object _lock = new object(); 18 | 19 | public static T Instance 20 | { 21 | get 22 | { 23 | if (applicationIsQuitting) 24 | { 25 | Debug.LogWarning("[Singleton] Instance '" + typeof(T) + 26 | "' already destroyed on application quit." + 27 | " Won't create again - returning null."); 28 | return null; 29 | } 30 | 31 | lock (_lock) 32 | { 33 | if (_instance == null) 34 | { 35 | _instance = (T)FindObjectOfType(typeof(T)); 36 | 37 | if (FindObjectsOfType(typeof(T)).Length > 1) 38 | { 39 | Debug.LogError("[Singleton] Something went really wrong " + 40 | " - there should never be more than 1 singleton!" + 41 | " Reopening the scene might fix it."); 42 | return _instance; 43 | } 44 | 45 | if (_instance == null) 46 | { 47 | GameObject singleton = new GameObject(); 48 | _instance = singleton.AddComponent(); 49 | singleton.name = "(singleton) " + typeof(T).ToString(); 50 | 51 | DontDestroyOnLoad(singleton); 52 | 53 | Debug.Log("[Singleton] An instance of " + typeof(T) + 54 | " is needed in the scene, so '" + singleton + 55 | "' was created with DontDestroyOnLoad."); 56 | } 57 | else 58 | { 59 | Debug.Log("[Singleton] Using instance already created: " + 60 | _instance.gameObject.name); 61 | } 62 | } 63 | 64 | return _instance; 65 | } 66 | } 67 | } 68 | 69 | private static bool applicationIsQuitting = false; 70 | /// 71 | /// When Unity quits, it destroys objects in a random order. 72 | /// In principle, a Singleton is only destroyed when application quits. 73 | /// If any script calls Instance after it have been destroyed, 74 | /// it will create a buggy ghost object that will stay on the Editor scene 75 | /// even after stopping playing the Application. Really bad! 76 | /// So, this was made to be sure we're not creating that buggy ghost object. 77 | /// 78 | public void OnDestroy() 79 | { 80 | applicationIsQuitting = true; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Assets/ObserverPattern/structure/Singleton.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a5f1d276de65e024cafeb59890adf8d6 3 | timeCreated: 1481284108 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/ObserverUnityPattern.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3d8560bd8c3e24144b98760c0ebaac05 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/ObserverUnityPattern/Messages.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4a92e59ebd302874ebeda12ab5c84d92 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/ObserverUnityPattern/Messages/new_Message.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: 51b113b2c0d54be4a8907eea61fc3fec, type: 3} 13 | m_Name: new_Message 14 | m_EditorClassIdentifier: 15 | -------------------------------------------------------------------------------- /Assets/ObserverUnityPattern/Messages/new_Message.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e57f7a07ef555624ab5acc24f76ad1ea 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/ObserverUnityPattern/Scenes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e0b645dff04526044895120eebf51fd2 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/ObserverUnityPattern/Scenes/OberverImplementation.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1671ec2bc289057449a67d2dc7ad35cb 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Assets/ObserverUnityPattern/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 13cbe75ce134aa84e87fda8ed6dd72a4 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/ObserverUnityPattern/Scripts/Observer.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 71ed474586e149f8bf8d8d6f8c81fd79 3 | timeCreated: 1747402454 -------------------------------------------------------------------------------- /Assets/ObserverUnityPattern/Scripts/Observer/Message.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5c226de5a6154bd3b0ae572d365f0e68 3 | timeCreated: 1747402492 -------------------------------------------------------------------------------- /Assets/ObserverUnityPattern/Scripts/Observer/Message/Messages.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace logandlp.Observer.Message 5 | { 6 | [CreateAssetMenu(fileName = "new_" + nameof(Message), menuName = "Observers/Messages")] 7 | public class Messages : ScriptableObject 8 | { 9 | // The message can contain type with Action. 10 | public Action Message { get; set; } 11 | 12 | // If the message contains a type the method must contain an overload of this same type. 13 | public void InvokeMessages() 14 | { 15 | Message?.Invoke(); 16 | } 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /Assets/ObserverUnityPattern/Scripts/Observer/Message/Messages.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 51b113b2c0d54be4a8907eea61fc3fec 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/ObserverUnityPattern/Scripts/Observer/Observers.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEngine.Events; 3 | 4 | namespace logandlp.Observer 5 | { 6 | using Message; 7 | 8 | public class Observers : MonoBehaviour 9 | { 10 | [SerializeField] private Messages _messages; 11 | [SerializeField] private UnityEvent _callbacks; 12 | 13 | private void OnEnable() 14 | { 15 | // Subscribe event. 16 | _messages.Message += InvokeCallbacks; 17 | } 18 | 19 | private void OnDisable() 20 | { 21 | // Unsubscribe event. 22 | _messages.Message -= InvokeCallbacks; 23 | } 24 | 25 | // If the message contains a type the method must contain an overload of this same type as well as the Unity Event "UnityEvent". 26 | private void InvokeCallbacks() 27 | { 28 | _callbacks?.Invoke(); 29 | } 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /Assets/ObserverUnityPattern/Scripts/Observer/Observers.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ccf7bf877d6382644a4885272b9ebaee 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/ObserverUnityPattern/Scripts/Stream.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9aedece9bce74020908095fd5866b4c0 3 | timeCreated: 1747402585 -------------------------------------------------------------------------------- /Assets/ObserverUnityPattern/Scripts/Stream/Receiver.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace logandlp.Stream 4 | { 5 | public class Receiver : MonoBehaviour 6 | { 7 | public void ReceiveMessage() 8 | { 9 | Debug.Log($"'{gameObject.name}' received message !"); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Assets/ObserverUnityPattern/Scripts/Stream/Receiver.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a7350728d06b428280db098a7f7e5d6c 3 | timeCreated: 1747402612 -------------------------------------------------------------------------------- /Assets/ObserverUnityPattern/Scripts/Stream/Sender.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace logandlp.Stream 4 | { 5 | using Observer.Message; 6 | 7 | public class Sender : MonoBehaviour 8 | { 9 | [SerializeField] private Messages _messages; 10 | 11 | [ContextMenu("Send Message")] 12 | public void SendMessage() 13 | { 14 | _messages?.InvokeMessages(); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Assets/ObserverUnityPattern/Scripts/Stream/Sender.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0651af8c1e2f48f9a4d40dfc91479abd 3 | timeCreated: 1747402600 -------------------------------------------------------------------------------- /Assets/States.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 486c8f0793fb9a84cb7653779187ee44 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/States/Scenes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f49c952257083ab479ea9679aeaf93a8 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/States/Scenes/Example States Pattern.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 770509df80161a944acbb0f843fd9681 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Assets/States/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5d36b40befb8b6044a2e9747fb93e9ec 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/States/Scripts/Exemples.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 670901be68364846a08f2b92544e1435 3 | timeCreated: 1748094322 -------------------------------------------------------------------------------- /Assets/States/Scripts/Exemples/Data.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2c0a7a1c67274c2b88b74c1667b9db04 3 | timeCreated: 1748094530 -------------------------------------------------------------------------------- /Assets/States/Scripts/Exemples/Data/ExampleStateData.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace logandlp.StatesPattern.Examples.Data 4 | { 5 | public struct ExampleStateData 6 | { 7 | public bool IsColorChanged { get; set; } 8 | public Renderer Renderer { get; set; } 9 | } 10 | } -------------------------------------------------------------------------------- /Assets/States/Scripts/Exemples/Data/ExampleStateData.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2ec4e57b13274073ba4389652de65500 3 | timeCreated: 1748094553 -------------------------------------------------------------------------------- /Assets/States/Scripts/Exemples/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bab33005a6e448bf9fdb992a34ae0568 3 | timeCreated: 1748099164 -------------------------------------------------------------------------------- /Assets/States/Scripts/Exemples/Editor/ExampleStatesMachineEditor.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_EDITOR 2 | 3 | using UnityEditor; 4 | using UnityEngine; 5 | 6 | namespace logandlp.StatesPattern.Examples.Editor 7 | { 8 | [CustomEditor(typeof(ExampleStatesMachine))] 9 | public class ExampleStatesMachineEditor : UnityEditor.Editor 10 | { 11 | public override void OnInspectorGUI() 12 | { 13 | serializedObject.Update(); 14 | 15 | GUI.enabled = Application.isPlaying; 16 | 17 | if (GUILayout.Button("Change Color State")) 18 | { 19 | ExampleStatesMachine stateMachine = (ExampleStatesMachine)target; 20 | stateMachine.InvokeChangeColor(); 21 | } 22 | 23 | GUI.enabled = true; 24 | 25 | serializedObject.ApplyModifiedProperties(); 26 | } 27 | } 28 | } 29 | 30 | #endif -------------------------------------------------------------------------------- /Assets/States/Scripts/Exemples/Editor/ExampleStatesMachineEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9e774de733b74bd7a23e49a3bdde500f 3 | timeCreated: 1748099189 -------------------------------------------------------------------------------- /Assets/States/Scripts/Exemples/ExampleStatesMachine.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace logandlp.StatesPattern.Examples 4 | { 5 | using Data; 6 | using States; 7 | 8 | using StatesPattern.States; 9 | using StatesPattern.States.Machines; 10 | 11 | public class ExampleStatesMachine : StatesMachine 12 | { 13 | [ContextMenu("Change State")] 14 | public void InvokeChangeColor() 15 | { 16 | _currentStateData.IsColorChanged = true; 17 | } 18 | 19 | protected override ExampleStateData DataImplementation() 20 | { 21 | return new ExampleStateData 22 | { 23 | IsColorChanged = false, 24 | Renderer = GetComponent(), 25 | }; 26 | } 27 | 28 | protected override IStates FirstStatesCalled() 29 | { 30 | return new RedColorState(); 31 | } 32 | 33 | protected override void OnNextStateEvent() 34 | { 35 | _currentStateData.IsColorChanged = false; 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /Assets/States/Scripts/Exemples/ExampleStatesMachine.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 82cf269a46d240ed971bc11e1b5788fa 3 | timeCreated: 1748094392 -------------------------------------------------------------------------------- /Assets/States/Scripts/Exemples/States.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: de0a1ee8c76d49858856efb1e6045cca 3 | timeCreated: 1748094805 -------------------------------------------------------------------------------- /Assets/States/Scripts/Exemples/States/BlueColorState.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace logandlp.StatesPattern.Examples.States 4 | { 5 | using Data; 6 | using StatesPattern.States; 7 | 8 | public class BlueColorState : IStates 9 | { 10 | public void Enter(ExampleStateData data) 11 | { 12 | Debug.Log($"{nameof(BlueColorState)} is Entered !"); 13 | 14 | data.Renderer.material.color = Color.blue; 15 | } 16 | 17 | public IStates Update(ExampleStateData data) 18 | { 19 | Debug.Log($"{nameof(BlueColorState)} is Updating !"); 20 | 21 | if (data.IsColorChanged) 22 | { 23 | return new RedColorState(); 24 | } 25 | 26 | return null; 27 | } 28 | 29 | public void Exit(ExampleStateData data) 30 | { 31 | Debug.Log($"{nameof(BlueColorState)} is Exiting !"); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /Assets/States/Scripts/Exemples/States/BlueColorState.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7f16f3234d254d5e896c7a1d9028002b 3 | timeCreated: 1748095727 -------------------------------------------------------------------------------- /Assets/States/Scripts/Exemples/States/RedColorState.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace logandlp.StatesPattern.Examples.States 4 | { 5 | using Data; 6 | using StatesPattern.States; 7 | 8 | public class RedColorState : IStates 9 | { 10 | public void Enter(ExampleStateData data) 11 | { 12 | Debug.Log($"{nameof(RedColorState)} is Entered !"); 13 | 14 | data.Renderer.material.color = Color.red; 15 | } 16 | 17 | public IStates Update(ExampleStateData data) 18 | { 19 | Debug.Log($"{nameof(RedColorState)} is Updating !"); 20 | 21 | if (data.IsColorChanged) 22 | { 23 | return new BlueColorState(); 24 | } 25 | 26 | return null; 27 | } 28 | 29 | public void Exit(ExampleStateData data) 30 | { 31 | Debug.Log($"{nameof(RedColorState)} is Exiting !"); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /Assets/States/Scripts/Exemples/States/RedColorState.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9eb82c166f4748c791d5c2a2dfb21325 3 | timeCreated: 1748094832 -------------------------------------------------------------------------------- /Assets/States/Scripts/States.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3abd3dcea9cdb774d8e1a590982c7274 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/States/Scripts/States/IStates.cs: -------------------------------------------------------------------------------- 1 | namespace logandlp.StatesPattern.States 2 | { 3 | public interface IStates where T : struct 4 | { 5 | /// 6 | /// State entry event. 7 | /// 8 | /// State data. 9 | public void Enter(T data); 10 | 11 | /// 12 | /// State update event. 13 | /// 14 | /// State data. 15 | /// Next state. 16 | public IStates Update(T data); 17 | 18 | /// 19 | /// State exit event. 20 | /// 21 | /// State data. 22 | public void Exit(T data); 23 | } 24 | } -------------------------------------------------------------------------------- /Assets/States/Scripts/States/IStates.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 29abe07dbad440849c0117634391a279 3 | timeCreated: 1748089410 -------------------------------------------------------------------------------- /Assets/States/Scripts/States/Machines.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f9f6d8a4463437c41a62048603defc21 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/States/Scripts/States/Machines/StatesMachine.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace logandlp.StatesPattern.States.Machines 4 | { 5 | /// State data. 6 | public abstract class StatesMachine : MonoBehaviour where T : struct 7 | { 8 | protected T _currentStateData; 9 | 10 | private IStates _currentState; 11 | 12 | protected virtual void Awake() 13 | { 14 | _currentStateData = DataImplementation(); 15 | StatesTransition(FirstStatesCalled()); 16 | } 17 | 18 | protected virtual void Update() 19 | { 20 | IStates nextState = _currentState?.Update(_currentStateData); 21 | if (nextState != null) 22 | { 23 | OnNextStateEvent(); 24 | StatesTransition(nextState); 25 | } 26 | } 27 | 28 | private void StatesTransition(IStates nextState) 29 | { 30 | _currentState?.Exit(_currentStateData); 31 | _currentState = nextState; 32 | _currentState?.Enter(_currentStateData); 33 | } 34 | 35 | #region Abstract methode 36 | 37 | /// 38 | /// Implementation of current state data called in awake method. 39 | /// 40 | /// Current state data. 41 | protected abstract T DataImplementation(); 42 | 43 | /// 44 | /// Set the first state to call. 45 | /// 46 | /// First state of the state machine. 47 | protected abstract IStates FirstStatesCalled(); 48 | 49 | /// 50 | /// Manages events before moving on to the following state. 51 | /// 52 | protected virtual void OnNextStateEvent() {} 53 | 54 | #endregion 55 | } 56 | } -------------------------------------------------------------------------------- /Assets/States/Scripts/States/Machines/StatesMachine.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fc49a122010c9b848a7b711f60bc077b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/abstract factory.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 603766d2f6b3c47498bd83b432c95282 3 | folderAsset: yes 4 | timeCreated: 1449106294 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/abstract factory/example.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: eda41969ca03c034fa9aee8acb8eeadb 3 | folderAsset: yes 4 | timeCreated: 1449116275 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/abstract factory/example/PrimitiveClient.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace NG.AbstractFactoryExample 6 | { 7 | public class PrimitiveClient 8 | { 9 | private List _abstractProductsA = new List(); 10 | private List _abstractProductsB = new List(); 11 | 12 | private AbstractPrimitiveFactory factory; 13 | 14 | private Vector3 productPositionStep = new Vector3(0, 1f, 0f); 15 | private Vector3 productAPosition = new Vector3(-2f, -0.5f, 0f); 16 | private Vector3 productBPosition = new Vector3(2f, -0.5f, 0f); 17 | 18 | 19 | public PrimitiveClient(AbstractPrimitiveFactory factory) 20 | { 21 | this.factory = factory; 22 | } 23 | 24 | public void CreateProducts(System.Type type) 25 | { 26 | if (type == typeof(PrimitiveA)) 27 | { 28 | _abstractProductsA.Add(factory.CreateProductA(productAPosition) as PrimitiveA); 29 | productAPosition += productPositionStep; 30 | } 31 | 32 | if (type == typeof(PrimitiveB)) 33 | { 34 | _abstractProductsB.Add(factory.CreateProductB(productBPosition) as PrimitiveB); 35 | productBPosition += productPositionStep; 36 | } 37 | } 38 | 39 | public bool isRunning { get; private set; } 40 | public string runState { get; private set; } 41 | 42 | public IEnumerator Run() 43 | { 44 | isRunning = true; 45 | runState = "Run starts"; 46 | yield return new WaitForSeconds(2f); 47 | 48 | 49 | if (_abstractProductsA.Count > 1) 50 | { 51 | runState = "Combine all product A with A"; 52 | for (int i = 0; i < _abstractProductsA.Count; i++) 53 | { 54 | _abstractProductsA[0].Interact(_abstractProductsA[i]); 55 | yield return new WaitForSeconds(0.5f); 56 | } 57 | } 58 | 59 | 60 | if (_abstractProductsB.Count > 1) 61 | { 62 | runState = "Combine all product B with B"; 63 | for (int i = 0; i < _abstractProductsB.Count; i++) 64 | { 65 | _abstractProductsB[0].Interact(_abstractProductsB[i]); 66 | yield return new WaitForSeconds(0.5f); 67 | } 68 | } 69 | 70 | if (_abstractProductsA.Count > 0 && _abstractProductsB.Count > 0) 71 | { 72 | runState = "Last B absorbs last A"; 73 | _abstractProductsB[0].Interact(_abstractProductsA[0]); 74 | } 75 | 76 | yield return new WaitForSeconds(2f); 77 | 78 | if (_abstractProductsB.Count > 0) 79 | { 80 | if (_abstractProductsB[0].gameObject != null) 81 | GameObject.Destroy(_abstractProductsB[0].gameObject); 82 | } 83 | isRunning = false; 84 | } 85 | 86 | 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Assets/abstract factory/example/PrimitiveClient.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 039c4f6614e09f247a5148689a5be157 3 | timeCreated: 1449211052 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/abstract factory/example/PrimitiveFactory.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace NG.AbstractFactoryExample 4 | { 5 | // Must implement CreateProductA and CreateProductB methods 6 | public class PrimitiveFactory : AbstractPrimitiveFactory 7 | { 8 | public override AbstractPrimitiveProduct CreateProductA(Vector3 position) 9 | { 10 | return new Cube(position); 11 | } 12 | 13 | public override AbstractPrimitiveProduct CreateProductB(Vector3 position) 14 | { 15 | return new Sphere(position); 16 | } 17 | } 18 | 19 | public class Cube : PrimitiveA 20 | { 21 | // Constructor 22 | public Cube (Vector3 position) 23 | { 24 | Instantiate(PrimitiveType.Cube, position); 25 | } 26 | 27 | // Interact with another like product 28 | public override void Interact(PrimitiveA a) 29 | { 30 | CombineWith(a); 31 | } 32 | } 33 | 34 | 35 | public class Sphere : PrimitiveB 36 | { 37 | // Constructor 38 | public Sphere(Vector3 position) 39 | { 40 | Instantiate(PrimitiveType.Sphere, position); 41 | } 42 | 43 | // Combine with product A, destroying it and making a capsule 44 | public override void Interact(PrimitiveA a) 45 | { 46 | CombineWith(a); 47 | 48 | ReplaceWithCapsule(); 49 | } 50 | 51 | private void ReplaceWithCapsule() 52 | { 53 | Vector3 position = gameObject.transform.position; 54 | Vector3 scale = gameObject.transform.localScale; 55 | GameObject.Destroy(gameObject); 56 | 57 | gameObject = GameObject.CreatePrimitive(PrimitiveType.Capsule); 58 | gameObject.transform.position = position; 59 | gameObject.transform.localScale = scale; 60 | 61 | meshRenderer = gameObject.GetComponent(); 62 | if (meshRenderer != null) 63 | { 64 | // Do not generate a new color, but use the combined one 65 | //color = RColor.Random(); 66 | meshRenderer.material.color = color; 67 | } 68 | } 69 | 70 | 71 | // Interaction with non-like products 72 | public override void Interact(PrimitiveB b) 73 | { 74 | CombineWith(b); 75 | } 76 | 77 | } 78 | 79 | 80 | 81 | 82 | public class RColor 83 | { 84 | public static Color Random() 85 | { 86 | return new Color( 87 | 0.25f * UnityEngine.Random.value, 88 | 0.25f * UnityEngine.Random.value, 89 | 0.25f * UnityEngine.Random.value, 90 | 1f 91 | ); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /Assets/abstract factory/example/PrimitiveFactory.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 12cf9f1eceb88694bae154634c4a0cdd 3 | timeCreated: 1449116275 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/abstract factory/example/PrimitiveFactory2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace NG.AbstractFactoryExample 5 | { 6 | public class PrimitiveFactory2 : PrimitiveFactory 7 | { 8 | public override AbstractPrimitiveProduct CreateProductA(Vector3 position) 9 | { 10 | return new Cylinder(position); 11 | } 12 | 13 | public override AbstractPrimitiveProduct CreateProductB(Vector3 position) 14 | { 15 | return new Cylinder2(position); 16 | } 17 | } 18 | 19 | public class Cylinder : PrimitiveA 20 | { 21 | public Cylinder(Vector3 position) 22 | { 23 | Instantiate(PrimitiveType.Cylinder, position); 24 | } 25 | 26 | public override void Interact(PrimitiveA a) 27 | { 28 | gameObject.transform.Rotate(new Vector3(0f, 0f, a.gameObject.transform.eulerAngles.z + 45f)); 29 | CombineWith(a); 30 | 31 | } 32 | } 33 | 34 | public class Cylinder2 : PrimitiveB 35 | { 36 | public Cylinder2(Vector3 position) 37 | { 38 | Instantiate(PrimitiveType.Cylinder, position); 39 | } 40 | 41 | public override void Interact(PrimitiveA a) 42 | { 43 | 44 | CombineWith(a); 45 | 46 | } 47 | 48 | public override void Interact(PrimitiveB b) 49 | { 50 | gameObject.transform.Rotate(new Vector3(0f, 0f, b.gameObject.transform.eulerAngles.z - 45f)); 51 | CombineWith(b); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Assets/abstract factory/example/PrimitiveFactory2.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1cc951f168211e44dbae8ec2fe606a35 3 | timeCreated: 1449211534 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/abstract factory/example/PrimitiveFactoryAbstracts.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | /// 4 | /// This is the structure of our pattern's implementation. 5 | /// 6 | namespace NG.AbstractFactoryExample 7 | { 8 | /// 9 | /// This is our abstract factory interface which allows us to create any abstract product we define. 10 | /// Note how we are defining a method for each product. This may cause some inflexibility in the design, 11 | /// but the design still has an advantage at the end point since when you create the products you won't 12 | /// need to know the concrete products. 13 | /// 14 | public abstract class AbstractPrimitiveFactory 15 | { 16 | public abstract AbstractPrimitiveProduct CreateProductA(Vector3 position); 17 | public abstract AbstractPrimitiveProduct CreateProductB(Vector3 position); 18 | } 19 | 20 | 21 | public abstract class AbstractPrimitiveProduct 22 | { 23 | public GameObject gameObject { get; protected set; } 24 | public Color color { get; protected set; } 25 | public MeshRenderer meshRenderer { get; protected set; } 26 | 27 | public void Instantiate(PrimitiveType primitiveType , Vector3 position) 28 | { 29 | color = RColor.Random(); 30 | gameObject = GameObject.CreatePrimitive(primitiveType); 31 | gameObject.transform.position = position; 32 | 33 | meshRenderer = gameObject.GetComponent(); 34 | if (meshRenderer != null) 35 | meshRenderer.material.color = color; 36 | } 37 | 38 | public void CombineWith(AbstractPrimitiveProduct other) 39 | { 40 | // prevent self interaction 41 | if (other == this) 42 | return; 43 | 44 | if (other.gameObject == null) 45 | return; 46 | 47 | if (other.meshRenderer != null) 48 | { 49 | // Combine colors onto this product. 50 | Color newColor = other.color + this.color; 51 | this.color = newColor; 52 | this.meshRenderer.material.color = newColor; 53 | } 54 | 55 | gameObject.transform.localScale *= 1.1f; 56 | 57 | Vector3 newPosition = 0.5f * (other.gameObject.transform.position - gameObject.transform.position); 58 | gameObject.transform.position += newPosition; 59 | 60 | GameObject.Destroy(other.gameObject); 61 | other = null; 62 | } 63 | } 64 | 65 | /// 66 | /// Can only interact with like products 67 | /// 68 | public abstract class PrimitiveA : AbstractPrimitiveProduct 69 | { 70 | public abstract void Interact(PrimitiveA a); 71 | } 72 | 73 | /// 74 | /// Can interact with either product 75 | /// 76 | public abstract class PrimitiveB : AbstractPrimitiveProduct 77 | { 78 | public abstract void Interact(PrimitiveA a); 79 | public abstract void Interact(PrimitiveB b); 80 | } 81 | } -------------------------------------------------------------------------------- /Assets/abstract factory/example/PrimitiveFactoryAbstracts.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f53e1188e42bbb6469ca7609bc6a1109 3 | timeCreated: 1449116278 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/abstract factory/example/PrimitiveFactoryController.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using NG.AbstractFactoryExample; 4 | 5 | /// 6 | /// This class is NOT part of the pattern. 7 | /// It simply exists as our main program from which we will 8 | /// run our application. 9 | /// 10 | 11 | public class PrimitiveFactoryController : MonoBehaviour 12 | { 13 | void Start() 14 | { 15 | StartCoroutine(FactoryRunner()); 16 | } 17 | 18 | PrimitiveClient runningClient; 19 | IEnumerator FactoryRunner() 20 | { 21 | PrimitiveFactory factory = new PrimitiveFactory(); 22 | PrimitiveClient client = new PrimitiveClient(factory); 23 | runningClient = client; 24 | for (int i = 0; i < 5; i++) 25 | { 26 | client.CreateProducts(typeof(PrimitiveA)); 27 | client.CreateProducts(typeof(PrimitiveB)); 28 | } 29 | 30 | StartCoroutine(client.Run()); 31 | 32 | while (client.isRunning) 33 | yield return new WaitForEndOfFrame(); 34 | 35 | PrimitiveFactory2 factory2 = new PrimitiveFactory2(); 36 | PrimitiveClient client2 = new PrimitiveClient(factory2); 37 | runningClient = client2; 38 | for (int i = 0; i < 5; i++) 39 | { 40 | client2.CreateProducts(typeof(PrimitiveA)); 41 | client2.CreateProducts(typeof(PrimitiveB)); 42 | } 43 | StartCoroutine(client2.Run()); 44 | } 45 | 46 | 47 | void OnGUI() 48 | { 49 | if (runningClient != null && runningClient.runState != null) 50 | { 51 | GUI.Label(new Rect(0, 0, 500, 500), runningClient.runState); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Assets/abstract factory/example/PrimitiveFactoryController.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: aea9425408de90e4381211d30feecda7 3 | timeCreated: 1449116275 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/abstract factory/example/abstract factory example.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 82a9a7aa7c23e7a40bb8be117beede70 3 | timeCreated: 1449118019 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/abstract factory/readme.md: -------------------------------------------------------------------------------- 1 | # Abstract Factory 2 | The abstract factory is pretty cool. What this does is sets up an interface for creating families of related or dependent objects and you don't need to specify what their concrete class is. 3 | The structure is broken down like this (see AbstractFactory.cs): 4 | - AbstractFactory class - this defines what abstract products can be created. For example, Mazda factory would create Mazda vehicles. 5 | - AbstractProduct classes - these define an interface for each of the products and any required methods that would be used to define interaction between the other products that can be created by the factory. 6 | - ConcreteProduct classes - these define the actual product that will be created by our ConcreteFactory class and modifies the methods that define interaction with other products. 7 | - ConcreteFactory class - this is the class that is responsible for creating the ConcreteProducts. 8 | - Client class - the client makes use of the factories, tells them to create products, and tells the products to interact. 9 | 10 | In the example I have fleshed out an abstract factory, abstract products, 2 concrete factories each with 2 concrete products, and a client that can easily run either factory. 11 | - PrimitiveFactoryAbstracts.cs 12 | - AbstractPrimitiveFactory - tells us that each concrete primitive factory is able to create 2 product type. 13 | - AbstractPrimitiveProduct - this is the base class for any product for the factory. It defines some common varaibles and functionality that all products will inherit. Each product will have a GameObject, Color, and MeshRenderer. 14 | - Instantiate will create the game object and fill out the required fields. 15 | - CombineWith will allow this product to "absorb" another product. What products it can combine with will be defined in the concrete definitions. 16 | - PrimitiveA and PrimitiveB - these are the final abstract products that will be created by the factory. Note how some behaviour has been set up for them. PrimitiveA can only interact with other PrimitiveA products, PrimitiveB can interact with either. 17 | 18 | - PrimitiveFactory.cs - in this file we define our concrete factory and concrete products. I've also added a class RColor to get a random color. 19 | - PrimitiveFactory - Now we're finally setting up the factory and defining the concrete products it will create. 20 | - Cube - This is our first product, pretty basic. It has a constructor that will instantiate the game object at the input position and set up all of the fields in the abstract class. It also defines interaction. 21 | - Sphere - Similar to the Cube product, but when it interacts with PrimitiveA (in this case a cube) it will be replaced with a capsule. When combining with another PrimitiveB it will just use the default combine behaviour. Note how these concrete product classes are now quite compact making it easy for us to write lots of them. 22 | 23 | - PrimitiveFactory2.cs - This is similar to our first factory, but it now creates 2 types of cylinders that have slightly different behaviour than the primitives in the first factory. 24 | 25 | - PrimitiveClient.cs - This class is responsible for running the factories. Note how it doesn't care what type of concrete factory or concrete products are being made. It leaves that up to the factories and the products. It maintains a list of the products so that it can Run() the behaviour on them after they've been created. It also keeps track of a position to place the products at. We'll be able to view the behaviour in progress with the Run() coroutine and I've set up a publically accessible string so that our Monobehaviour class can report the state via OnGUI. 26 | 27 | - PrimitiveFactoryController.cs - This is our final endpoint, our "app". It sets up the factories and the clients, tells them to create products, and shows us the client state in OnGUI. Note how this class is really bare minimum. It takes just a few lines of code to create the factory, client, the products, and run the client to make the products interact. Really streamlined at this point. 28 | 29 | That's all there is to it! See it in action by loading up the example scene and hitting play. Explore the code lots and tinker with your own factories and products with varying behaviour. I hope this is a helpful example. If anyone has another I'd love to see it! 30 | 31 | 32 | -------------------------------------------------------------------------------- /Assets/abstract factory/readme.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 07f8543e997217c439d63b6db0296168 3 | timeCreated: 1449290299 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/abstract factory/structure.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9530437a827448a49810a2d6ee08f86e 3 | folderAsset: yes 4 | timeCreated: 1449106324 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/abstract factory/structure/AbstractFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NG.Patterns.Structure.AbstractFactory 4 | { 5 | #region Abstractions 6 | public abstract class AbstractFactory 7 | { 8 | public abstract AbstractProductA CreateProductA(); 9 | public abstract AbstractProductB CreateProductB(); 10 | } 11 | 12 | public abstract class AbstractProductA{} 13 | 14 | public abstract class AbstractProductB 15 | { 16 | public abstract void Interact(AbstractProductA a); 17 | } 18 | #endregion 19 | 20 | #region concretes 21 | public class ProductA1 : AbstractProductA {} 22 | 23 | public class ProductA2 : AbstractProductA { } 24 | 25 | public class ProductB1 : AbstractProductB 26 | { 27 | public override void Interact(AbstractProductA a) 28 | { 29 | Console.WriteLine(this.GetType().Name + " interacts with " + a.GetType().Name); 30 | } 31 | } 32 | 33 | public class ProductB2 : AbstractProductB 34 | { 35 | public override void Interact(AbstractProductA a) 36 | { 37 | Console.WriteLine(this.GetType().Name + " interacts with " + a.GetType().Name); 38 | } 39 | } 40 | 41 | public class ConcreteFactory1 : AbstractFactory 42 | { 43 | public override AbstractProductA CreateProductA() 44 | { 45 | return new ProductA1(); 46 | } 47 | 48 | public override AbstractProductB CreateProductB() 49 | { 50 | return new ProductB1(); 51 | } 52 | } 53 | 54 | public class ConcreteFactory2 : AbstractFactory 55 | { 56 | public override AbstractProductA CreateProductA() 57 | { 58 | return new ProductA2(); 59 | } 60 | 61 | public override AbstractProductB CreateProductB() 62 | { 63 | return new ProductB2(); 64 | } 65 | } 66 | #endregion 67 | 68 | 69 | public class Client 70 | { 71 | private AbstractProductA _abstractProductA; 72 | private AbstractProductB _abstractProductB; 73 | 74 | public Client (AbstractFactory factory) 75 | { 76 | _abstractProductA = factory.CreateProductA(); 77 | _abstractProductB = factory.CreateProductB(); 78 | } 79 | 80 | public void Run() 81 | { 82 | _abstractProductB.Interact(_abstractProductA); 83 | } 84 | 85 | } 86 | 87 | // construct factories, clients, and run functionality. 88 | public class MainApp 89 | { 90 | public void Main() 91 | { 92 | AbstractFactory factory1 = new ConcreteFactory1(); 93 | Client client1 = new Client(factory1); 94 | client1.Run(); 95 | 96 | AbstractFactory factory2 = new ConcreteFactory2(); 97 | Client client2 = new Client(factory2); 98 | client2.Run(); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /Assets/abstract factory/structure/AbstractFactory.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0b8b0a3d79f0d324d910961ee51c6a64 3 | timeCreated: 1449106339 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/builder pattern.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6426fd37139415044b32582d4267e30c 3 | folderAsset: yes 4 | timeCreated: 1449356455 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/builder pattern/example.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5126b492ea597f84880f1fcfd08bd9bc 3 | folderAsset: yes 4 | timeCreated: 1449356455 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/builder pattern/example/BuilderController.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using NG.builder_pattern.example; 3 | 4 | public class BuilderController : MonoBehaviour 5 | { 6 | void Start() 7 | { 8 | // Instantiate the director and builders 9 | ShopForeman shopForeman = new ShopForeman(); 10 | CarBuilder carBuilder = new CarBuilder(); 11 | MotorCycleBuilder motorCycleBuilder = new MotorCycleBuilder(); 12 | ScooterBuilder scooterBuilder = new ScooterBuilder(); 13 | 14 | // Make the products, the vehicles. 15 | shopForeman.Construct(carBuilder); 16 | shopForeman.Construct(motorCycleBuilder); 17 | shopForeman.Construct(scooterBuilder); 18 | 19 | // Get the vehicles and access their methods. 20 | Vehicle car = carBuilder.vehicle; 21 | Debug.Log(car.GetPartsList()); 22 | 23 | Vehicle motorCycle = motorCycleBuilder.vehicle; 24 | Debug.Log(motorCycle.GetPartsList()); 25 | 26 | Vehicle scooter = scooterBuilder.vehicle; 27 | Debug.Log(scooter.GetPartsList()); 28 | 29 | 30 | // These calls don't have anything to do with the pattern. 31 | // They are simply here to make our visual display of the vehicles 32 | // in the Unity scene look nice. 33 | car.parent.transform.position = new Vector3(-6f, 0, 0); 34 | motorCycle.parent.transform.position = new Vector3(6f, 0, 0); 35 | } 36 | 37 | void Update() 38 | { 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Assets/builder pattern/example/BuilderController.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e8049594bd0fbb946acc40c702105063 3 | timeCreated: 1449356459 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/builder pattern/example/BuilderExampleStructure.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections.Generic; 3 | 4 | namespace NG.builder_pattern.example 5 | { 6 | // Our 'Director' class. Tells us how to construct the vehicles. 7 | class ShopForeman 8 | { 9 | public void Construct(VehicleBuilder vehicleBuilder) 10 | { 11 | vehicleBuilder.BuildFrame(); 12 | vehicleBuilder.BuildEngine(); 13 | vehicleBuilder.BuildWheels(); 14 | vehicleBuilder.BuildDoors(); 15 | } 16 | } 17 | 18 | // Our 'abstract Builder' class 19 | // Definition of what methods will be used to actually build the vehicles. 20 | interface VehicleBuilder 21 | { 22 | // Gets the vehicle instance 23 | Vehicle vehicle { get; } 24 | 25 | // Contract methods for building the components 26 | void BuildFrame(); 27 | void BuildEngine(); 28 | void BuildWheels(); 29 | void BuildDoors(); 30 | } 31 | 32 | enum VehicleType { Scooter, Car, MotorCycle } 33 | // Our final product 34 | class Vehicle 35 | { 36 | public VehicleType vehicleType { get; private set; } 37 | public GameObject parent { get; private set; } 38 | private List _parts = new List(); 39 | 40 | // Constructor method 41 | public Vehicle(VehicleType vehicleType) 42 | { 43 | this.vehicleType = vehicleType; 44 | parent = new GameObject(vehicleType.ToString()); 45 | } 46 | 47 | public void AddPart(GameObject part, Vector3 localPosition) 48 | { 49 | part.transform.SetParent(parent.transform); 50 | part.transform.localPosition = localPosition; 51 | _parts.Add(part); 52 | } 53 | 54 | public string GetPartsList() 55 | { 56 | string partsList = vehicleType.ToString() + " parts:\n\t"; 57 | foreach (GameObject part in _parts) 58 | { 59 | partsList += part.name + " "; 60 | } 61 | 62 | return partsList; 63 | } 64 | 65 | // Provides a common function to make the parts. Not truly a part of the standard 66 | // pattern, but included in this example to make part creation easier. 67 | public GameObject MakePart(PrimitiveType primitiveType, string name, Vector3 scale, Color color) 68 | { 69 | GameObject go = GameObject.CreatePrimitive(primitiveType); 70 | go.name = name; 71 | go.transform.localScale = scale; 72 | MeshRenderer meshRenderer = go.GetComponent(); 73 | if (meshRenderer != null) 74 | meshRenderer.material.color = color; 75 | 76 | return go; 77 | } 78 | } 79 | 80 | 81 | 82 | } 83 | -------------------------------------------------------------------------------- /Assets/builder pattern/example/BuilderExampleStructure.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bee6a72f7a467864a9d50153642ffa44 3 | timeCreated: 1449356455 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/builder pattern/example/CarBuilder.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace NG.builder_pattern.example 4 | { 5 | // Makes the parts and adds them to the vehicle at the correct local position. 6 | class CarBuilder : VehicleBuilder 7 | { 8 | private Vehicle _vehicle; 9 | public Vehicle vehicle 10 | { 11 | get 12 | { 13 | return _vehicle; 14 | } 15 | } 16 | 17 | public CarBuilder() 18 | { 19 | _vehicle = new Vehicle(VehicleType.Car); 20 | } 21 | 22 | 23 | public void BuildFrame() 24 | { 25 | GameObject frame = _vehicle.MakePart(PrimitiveType.Cube, "frame", new Vector3(2, 1, 1), Color.blue); 26 | 27 | _vehicle.AddPart(frame, Vector3.zero); 28 | } 29 | 30 | 31 | public void BuildDoors() 32 | { 33 | Vector3 doorScale = new Vector3(1, 1, 0.05f); 34 | 35 | GameObject leftDoor = _vehicle.MakePart(PrimitiveType.Cube, "left door", doorScale, Color.cyan); 36 | _vehicle.AddPart(leftDoor, new Vector3(0, 0, 0.5f)); 37 | 38 | GameObject rightDoor = _vehicle.MakePart(PrimitiveType.Cube, "right door", doorScale, Color.cyan); 39 | _vehicle.AddPart(rightDoor, new Vector3(0, 0, -0.5f)); 40 | } 41 | 42 | 43 | 44 | public void BuildEngine() 45 | { 46 | GameObject engine = _vehicle.MakePart(PrimitiveType.Cube, "engine", 0.5f * Vector3.one, Color.gray); 47 | _vehicle.AddPart(engine, new Vector3(1, -0.25f, 0)); 48 | } 49 | 50 | 51 | 52 | public void BuildWheels() 53 | { 54 | Vector3 wheelScale = new Vector3(0.5f, 0.1f, 0.5f); 55 | 56 | GameObject wheel = _vehicle.MakePart(PrimitiveType.Cylinder, "wheel", wheelScale, Color.black); 57 | _vehicle.AddPart(wheel, new Vector3(0.75f, -0.5f, 0.5f)); 58 | wheel.transform.Rotate(new Vector3(90, 0, 0)); 59 | 60 | wheel = _vehicle.MakePart(PrimitiveType.Cylinder, "wheel", wheelScale, Color.black); 61 | _vehicle.AddPart(wheel, new Vector3(-0.75f, -0.5f, 0.5f)); 62 | wheel.transform.Rotate(new Vector3(90, 0, 0)); 63 | 64 | wheel = _vehicle.MakePart(PrimitiveType.Cylinder, "wheel", wheelScale, Color.black); 65 | _vehicle.AddPart(wheel, new Vector3(-0.75f, -0.5f, -0.5f)); 66 | wheel.transform.Rotate(new Vector3(90, 0, 0)); 67 | 68 | wheel = _vehicle.MakePart(PrimitiveType.Cylinder, "wheel", wheelScale, Color.black); 69 | _vehicle.AddPart(wheel, new Vector3(0.75f, -0.5f, -0.5f)); 70 | wheel.transform.Rotate(new Vector3(90, 0, 0)); 71 | 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Assets/builder pattern/example/CarBuilder.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 96dfc5fe7f5e2544989c646803dd9bb6 3 | timeCreated: 1449356455 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/builder pattern/example/MotorCycleBuilder.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace NG.builder_pattern.example 4 | { 5 | class MotorCycleBuilder : VehicleBuilder 6 | { 7 | private Vehicle _vehicle; 8 | public Vehicle vehicle 9 | { 10 | get 11 | { 12 | return _vehicle; 13 | } 14 | } 15 | 16 | 17 | public MotorCycleBuilder() 18 | { 19 | _vehicle = new Vehicle(VehicleType.MotorCycle); 20 | } 21 | 22 | 23 | 24 | public void BuildDoors() 25 | { 26 | // We don't need no doors. 27 | } 28 | 29 | 30 | public void BuildEngine() 31 | { 32 | GameObject engine = _vehicle.MakePart(PrimitiveType.Cube, "engine", new Vector3(0.75f, 0.5f, 0.75f), Color.gray); 33 | _vehicle.AddPart(engine, new Vector3(0, -0.25f, 0)); 34 | } 35 | 36 | 37 | public void BuildFrame() 38 | { 39 | GameObject frame = _vehicle.MakePart(PrimitiveType.Cube, "frame", new Vector3(2, 0.5f, 0.5f), Color.red); 40 | _vehicle.AddPart(frame, Vector3.zero); 41 | } 42 | 43 | 44 | public void BuildWheels() 45 | { 46 | Vector3 scale = new Vector3(0.75f, 0.1f, 0.75f); 47 | 48 | GameObject wheel = _vehicle.MakePart(PrimitiveType.Cylinder, "wheel", scale, Color.black); 49 | _vehicle.AddPart(wheel, new Vector3(1, -0.25f, 0)); 50 | wheel.transform.Rotate(new Vector3(90f, 0, 0)); 51 | 52 | wheel = _vehicle.MakePart(PrimitiveType.Cylinder, "wheel", scale, Color.black); 53 | _vehicle.AddPart(wheel, new Vector3(-1, -0.25f, 0)); 54 | wheel.transform.Rotate(new Vector3(90f, 0, 0)); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Assets/builder pattern/example/MotorCycleBuilder.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ba70c4e446be6a94b9016c0acb24a246 3 | timeCreated: 1449356455 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/builder pattern/example/ScooterBuilder.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace NG.builder_pattern.example 4 | { 5 | class ScooterBuilder : VehicleBuilder 6 | { 7 | private Vehicle _vehicle; 8 | public Vehicle vehicle 9 | { 10 | get 11 | { 12 | return _vehicle; 13 | } 14 | } 15 | 16 | 17 | public ScooterBuilder() 18 | { 19 | _vehicle = new Vehicle(VehicleType.Scooter); 20 | } 21 | 22 | 23 | 24 | public void BuildDoors() 25 | { 26 | // We don't need no doors. 27 | } 28 | 29 | 30 | public void BuildEngine() 31 | { 32 | GameObject engine = _vehicle.MakePart(PrimitiveType.Cube, "engine", 0.5f * (new Vector3(.5f, 0.5f, 0.25f)), Color.gray); 33 | _vehicle.AddPart(engine, new Vector3(1.25f, 0.3f, 0)); 34 | } 35 | 36 | 37 | public void BuildFrame() 38 | { 39 | GameObject frame = _vehicle.MakePart(PrimitiveType.Cube, "frame", 0.5f * new Vector3(2, 0.5f, 0.5f), Color.magenta); 40 | _vehicle.AddPart(frame, Vector3.zero); 41 | 42 | frame = _vehicle.MakePart(PrimitiveType.Cube, "frame2", 0.5f * new Vector3(0.25f, 2f, 0.5f), Color.magenta); 43 | _vehicle.AddPart(frame, new Vector3(1f, 0.75f, 0f)); 44 | } 45 | 46 | 47 | public void BuildWheels() 48 | { 49 | Vector3 scale = 0.5f * new Vector3(0.75f, 0.1f, 0.75f); 50 | 51 | GameObject wheel = _vehicle.MakePart(PrimitiveType.Cylinder, "wheel", scale, Color.black); 52 | _vehicle.AddPart(wheel, new Vector3(1, -0.25f, 0)); 53 | wheel.transform.Rotate(new Vector3(90f, 0, 0)); 54 | 55 | wheel = _vehicle.MakePart(PrimitiveType.Cylinder, "wheel", scale, Color.black); 56 | _vehicle.AddPart(wheel, new Vector3(-1, -0.25f, 0)); 57 | wheel.transform.Rotate(new Vector3(90f, 0, 0)); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Assets/builder pattern/example/ScooterBuilder.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b242a2d39d8cd9b40a1e64b6e7b372db 3 | timeCreated: 1449356455 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/builder pattern/example/builder_pattern_example.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3f81f76b40564f54b82d57aaecd94617 3 | timeCreated: 1449357066 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/builder pattern/readme.md: -------------------------------------------------------------------------------- 1 | # Builder Pattern 2 | A builder pattern assists in the creation of complex objects that share the same types of components. The builder uses the same process for each product, but each component in the product does not need to be the same. For instance consider a builder that will make vehicles. All vehicles have similar component types: body, wheels, doors, etc. 3 | 4 | ### Structure 5 | All classes can be found in **BuilderPattern.cs**. 6 | 7 | - **Builder** - This defines our abstract interface that will construct the final product and has the ability to return the final product. 8 | - **ConcreteBuilder** - This constructs and assembles the parts of the product by implementing the abstract Builder's methods and provides the ability to retrieve the actual final product. 9 | - **Director** - This is responsible for running the creation of the final products using the abstract Builder. 10 | - **Product** - The final object that will be created. It should include the references to the parts of the product and the ability to integrate the new parts. 11 | 12 | ### Example 13 | The example sets up a vehicle builder that can make a car, a motorcycle, or a scooter. The pattern structures are contained in **BuilderExampleStructure.cs**. Here you'll find: 14 | 15 | - **ShopForeman** (our 'director' class) is responsible for telling the builders the tasks needed to make a vehicle. 16 | - **VehicleBuilder** (the 'abstract builder' class) will define the framework for all of the vehicle builders. We do need a reference to the vehicle being constructed in every concrete builder so those have been set up. An unfortunate side effect of this is that it forces us to use an abstract class and we cannot have an abstract constructor. Yet all of the concrete builders will need a constructor to instantiate the Vehicle that will be referenced in the concrete VehicleBuilders. I don't see a simple way around this. If you do, let me know! 17 | - **Vehicle** (the 'product') - This will create an empty game object when constructed that will function as a parent to all of the parts we create. It also provides us with a method to add parts to the vehicle and finally a method to list the parts which is not necessary for the pattern, but just there so the class does a little more. 18 | - **CarBuilder.cs**, **MotorCycleBuilder.cs**, and **ScooterBuilder.cs** - These are our concrete builders. Each has a constructor that will instantiate a Vehicle class and assign it to the _vehicle field so we can make references to it when adding parts. Then we have the required methods to add the parts. Here I'm just making some primitives and placing them so they look somewhat like the vehicle I'm trying to make (don't judge me :P). 19 | - **BuilderController.cs** - This is our MonoBehaviour that can be attached to a game object in the scene. It just makes the ShopForeman and builders, tells the foreman to put the builders to work. Then we can get references to our actual vehicles and do things with them. 20 | 21 | -------------------------------------------------------------------------------- /Assets/builder pattern/readme.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: df6c1b58ccd8d664fb4f892b26bda8ed 3 | timeCreated: 1449356455 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/builder pattern/structure.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 30096dbe346555643a1956044beb517b 3 | folderAsset: yes 4 | timeCreated: 1449356455 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/builder pattern/structure/BuilderPattern.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace NG.builder_pattern.structure 5 | { 6 | class Director 7 | { 8 | public void Construct(Builder builder) 9 | { 10 | builder.BuildPartA(); 11 | builder.BuildPartB(); 12 | } 13 | } 14 | 15 | abstract class Builder 16 | { 17 | protected Product _product; 18 | public abstract void BuildPartA(); 19 | public abstract void BuildPartB(); 20 | public abstract Product GetProduct(); 21 | } 22 | 23 | class ConcreteBuilder1 : Builder 24 | { 25 | public ConcreteBuilder1() 26 | { 27 | _product = new Product(); 28 | } 29 | 30 | public override void BuildPartA() 31 | { 32 | _product.Add("PartA"); 33 | } 34 | 35 | public override void BuildPartB() 36 | { 37 | _product.Add("PartB"); 38 | } 39 | 40 | public override Product GetProduct() 41 | { 42 | return _product; 43 | } 44 | } 45 | 46 | class ConcreteBuilder2 : Builder 47 | { 48 | public ConcreteBuilder2() 49 | { 50 | _product = new Product(); 51 | } 52 | 53 | public override void BuildPartA() 54 | { 55 | _product.Add("PartX"); 56 | } 57 | 58 | public override void BuildPartB() 59 | { 60 | _product.Add("PartY"); 61 | } 62 | 63 | public override Product GetProduct() 64 | { 65 | return _product; 66 | } 67 | } 68 | 69 | class Product 70 | { 71 | private List _parts = new List(); 72 | public void Add(string part) 73 | { 74 | _parts.Add(part); 75 | } 76 | 77 | public void Show() 78 | { 79 | Console.WriteLine("\nProduct Parts --- "); 80 | foreach (string part in _parts) 81 | { 82 | Console.WriteLine("\t" + part); 83 | } 84 | } 85 | } 86 | 87 | // Note how simple it is to make the products at the endpoint. 88 | // Also the director doesn't care what builders it is fed. 89 | class ExampleApp 90 | { 91 | void Run() 92 | { 93 | // Instantiate the director and builders 94 | Director director = new Director(); 95 | Builder b1 = new ConcreteBuilder1(); 96 | Builder b2 = new ConcreteBuilder2(); 97 | 98 | // Construct the two products 99 | director.Construct(b1); 100 | Product p1 = b1.GetProduct(); 101 | p1.Show(); 102 | 103 | director.Construct(b2); 104 | Product p2 = b2.GetProduct(); 105 | p2.Show(); 106 | 107 | Console.Read(); 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /Assets/builder pattern/structure/BuilderPattern.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 995d3969547232946a047aea65e032ab 3 | timeCreated: 1449356455 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/command pattern.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0f33ddf11b1fc4b49b9bb6334847d981 3 | folderAsset: yes 4 | timeCreated: 1443733418 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/command pattern/Command.cs: -------------------------------------------------------------------------------- 1 | namespace NG.CommandPatternExample 2 | { 3 | /// 4 | /// The 'Command' abstract class that we will inherit from 5 | /// 6 | abstract class Command 7 | { 8 | public abstract void Execute(); 9 | public abstract void UnExecute(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Assets/command pattern/Command.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fb48245b7ca84e84695a50cc2d1f3d63 3 | timeCreated: 1443726689 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/command pattern/InputHandler.cs: -------------------------------------------------------------------------------- 1 | /// 2 | /// The 'Invoker' class that makes calls to execute the commands 3 | /// 4 | 5 | using UnityEngine; 6 | using System.Collections.Generic; 7 | using NG.CommandPatternExample; 8 | 9 | public class InputHandler : MonoBehaviour 10 | { 11 | public float moveDistance = 10f; 12 | public GameObject objectToMove; 13 | 14 | private MoveCommandReceiver moveCommandReciever; 15 | private List commands = new List(); 16 | private int currentCommandNum = 0; 17 | 18 | void Start() 19 | { 20 | moveCommandReciever = new MoveCommandReceiver(); 21 | 22 | if (objectToMove == null) 23 | { 24 | Debug.LogError("objectToMove must be assigned via inspector"); 25 | this.enabled = false; 26 | } 27 | } 28 | 29 | 30 | public void Undo() 31 | { 32 | if (currentCommandNum > 0) 33 | { 34 | currentCommandNum--; 35 | MoveCommand moveCommand = commands[currentCommandNum]; 36 | moveCommand.UnExecute(); 37 | } 38 | } 39 | 40 | public void Redo() 41 | { 42 | if (currentCommandNum < commands.Count) 43 | { 44 | MoveCommand moveCommand = commands[currentCommandNum]; 45 | currentCommandNum++; 46 | moveCommand.Execute(); 47 | } 48 | } 49 | 50 | private void Move(MoveDirection direction) 51 | { 52 | MoveCommand moveCommand = new MoveCommand(moveCommandReciever, direction, moveDistance, objectToMove); 53 | moveCommand.Execute(); 54 | commands.Add(moveCommand); 55 | currentCommandNum++; 56 | } 57 | 58 | 59 | //Simple move commands to attach to UI buttons 60 | public void MoveUp() { Move(MoveDirection.up); } 61 | public void MoveDown() { Move(MoveDirection.down); } 62 | public void MoveLeft() { Move(MoveDirection.left); } 63 | public void MoveRight() { Move(MoveDirection.right); } 64 | 65 | //Shows what's going on in the command list 66 | void OnGUI() 67 | { 68 | string label = " start"; 69 | if (currentCommandNum == 0) 70 | { 71 | label = ">" + label; 72 | } 73 | label += "\n"; 74 | 75 | for (int i = 0; i < commands.Count; i++) 76 | { 77 | if (i == currentCommandNum - 1) 78 | label += "> " + commands[i].ToString() + "\n"; 79 | else 80 | label += " " + commands[i].ToString() + "\n"; 81 | 82 | } 83 | GUI.Label(new Rect(0, 0, 400, 800), label); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Assets/command pattern/InputHandler.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 65852039ecae1544bb206a2d800923b0 3 | timeCreated: 1443729901 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/command pattern/MoveCommand.cs: -------------------------------------------------------------------------------- 1 | /// 2 | /// A simple example of a class inheriting from a command pattern 3 | /// This handles execution of the command as well as unexecution of the command 4 | /// 5 | 6 | using UnityEngine; 7 | 8 | namespace NG.CommandPatternExample 9 | { 10 | // A basic enum to describe our movement 11 | public enum MoveDirection { up, down, left, right }; 12 | 13 | class MoveCommand : Command 14 | { 15 | private MoveDirection _direction; 16 | private MoveCommandReceiver _receiver; 17 | private float _distance; 18 | private GameObject _gameObject; 19 | 20 | 21 | //Constructor 22 | public MoveCommand(MoveCommandReceiver reciever, MoveDirection direction, float distance, GameObject gameObjectToMove) 23 | { 24 | this._receiver = reciever; 25 | this._direction = direction; 26 | this._distance = distance; 27 | this._gameObject = gameObjectToMove; 28 | } 29 | 30 | 31 | //Execute new command 32 | public override void Execute() 33 | { 34 | _receiver.MoveOperation(_gameObject, _direction, _distance); 35 | } 36 | 37 | 38 | //Undo last command 39 | public override void UnExecute() 40 | { 41 | _receiver.MoveOperation(_gameObject, InverseDirection(_direction), _distance); 42 | } 43 | 44 | 45 | //invert the direction for undo 46 | private MoveDirection InverseDirection(MoveDirection direction) 47 | { 48 | switch (direction) 49 | { 50 | case MoveDirection.up: 51 | return MoveDirection.down; 52 | case MoveDirection.down: 53 | return MoveDirection.up; 54 | case MoveDirection.left: 55 | return MoveDirection.right; 56 | case MoveDirection.right: 57 | return MoveDirection.left; 58 | default: 59 | Debug.LogError("Unknown MoveDirection"); 60 | return MoveDirection.up; 61 | } 62 | } 63 | 64 | 65 | //So we can show this command in debug output easily 66 | public override string ToString() 67 | { 68 | return _gameObject.name + " : " + MoveDirectionString(_direction) + " : " + _distance.ToString(); 69 | } 70 | 71 | 72 | //Convert the MoveDirection enum to a string for debug 73 | public string MoveDirectionString(MoveDirection direction) 74 | { 75 | switch (direction) 76 | { 77 | case MoveDirection.up: 78 | return "up"; 79 | case MoveDirection.down: 80 | return "down"; 81 | case MoveDirection.left: 82 | return "left"; 83 | case MoveDirection.right: 84 | return "right"; 85 | default: 86 | return "unkown"; 87 | } 88 | } 89 | } 90 | } 91 | 92 | -------------------------------------------------------------------------------- /Assets/command pattern/MoveCommand.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6640f3d189ff07f429337a511fb740f1 3 | timeCreated: 1443729901 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/command pattern/MoveCommandReceiver.cs: -------------------------------------------------------------------------------- 1 | /// 2 | /// The 'Receiver' class - this handles what a move command actually does 3 | /// 4 | 5 | using UnityEngine; 6 | namespace NG.CommandPatternExample 7 | { 8 | class MoveCommandReceiver 9 | { 10 | public void MoveOperation(GameObject gameObjectToMove, MoveDirection direction, float distance) 11 | { 12 | switch (direction) 13 | { 14 | case MoveDirection.up: 15 | MoveY(gameObjectToMove, distance); 16 | break; 17 | case MoveDirection.down: 18 | MoveY(gameObjectToMove, -distance); 19 | break; 20 | case MoveDirection.left: 21 | MoveX(gameObjectToMove, -distance); 22 | break; 23 | case MoveDirection.right: 24 | MoveX(gameObjectToMove, distance); 25 | break; 26 | } 27 | } 28 | 29 | private void MoveY(GameObject gameObjectToMove, float distance) 30 | { 31 | Vector3 newPos = gameObjectToMove.transform.position; 32 | newPos.y += distance; 33 | gameObjectToMove.transform.position = newPos; 34 | } 35 | 36 | private void MoveX(GameObject gameObjectToMove, float distance) 37 | { 38 | Vector3 newPos = gameObjectToMove.transform.position; 39 | newPos.x += distance; 40 | gameObjectToMove.transform.position = newPos; 41 | } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /Assets/command pattern/MoveCommandReceiver.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8b876aa2447a543409330fcc88e0615b 3 | timeCreated: 1443729901 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/command pattern/README.md: -------------------------------------------------------------------------------- 1 | # Command Pattern 2 | 3 | Command patterns are most useful for when you want a generic way to store a command and be able to undo it. 4 | In the scene "command pattern example" you'll see a simple dot that can be moved by GUI buttons. 5 | After making a move you can then undo and redo it. I've added a simple OnGUI label output to the screen so you can see the list of commands with an indication of which is the current command. 6 | 7 | There are 4 classes that get used in this example: 8 | * **Command** - this is the basic structure (abstract class) that any command pattern can inherit from. You can use this class in any project. 9 | * **MoveCommand** - this is the structure that inherits from the Command class and will make use of Execute and UnExecute (undo). Each movement is done via a MoveCommand which is in turn recorded in a list so it can be undone or redone. Notice how we have not inherited from Monobehaviour at all yet. It also contains a function to reverse the movement direction, an override for ToString() for the class so we can see it's fields, and a function to convert our MoveDirection enum to a string for easy reading later. The class is constructed with parameters for the receiver of the command (more on that next), the direction of the movement, distance of the movement, and the game object that is being moved. 10 | * **MoveCommandReceiver** - this class handles the actual movement of the game object and is really only needed once. It plays the part of an intermediate between input and the MoveCommand. All of the actual movement is defined here. 11 | * **InputHandler** - this is the class that brings it all together, the "Invoker". It sends player input to the MoveCommandReceiver via MoveCommands.. They get stored in a standard List so that we can later undo and redo them. It has a functions for each direction of movement so they can be attached to uGUI buttons. It has a simple use of OnGUI to illustrate the command sequence. 12 | 13 | Final thoughts:
14 | MoveCommand and MoveCommandReciever are not very flexible. Also, they're tied together. It feels like these could even be in a single class where the MoveCommandReciever could be completely eliminated. I may be missing something. It feels like using this pattern will lead to a lot of classes. 2 for each command. Not really cool. 15 | 16 | -------------------------------------------------------------------------------- /Assets/command pattern/README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8296c9c30e4d44f44b8c3632d901cfe4 3 | timeCreated: 1449216650 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/command pattern/command pattern example.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 84db78d1aa884244cb57b98cac903f64 3 | timeCreated: 1443726226 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/decorator.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fb7905bf3f9a3554f8d561f9cb924f70 3 | folderAsset: yes 4 | timeCreated: 1450985674 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/decorator/example1.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e9b4216bd9419a7478c4e4d93aadcfd3 3 | folderAsset: yes 4 | timeCreated: 1450985674 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/decorator/example1/MeleeAttack.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using UnityEngine; 6 | 7 | namespace Assets.decorator.example1 8 | { 9 | abstract class MeleeAttack 10 | { 11 | public abstract int Attack(); 12 | } 13 | 14 | 15 | class BaseMelee : MeleeAttack 16 | { 17 | public override int Attack() 18 | { 19 | int value = UnityEngine.Random.Range(1, 7); // 1d6 20 | return value; 21 | } 22 | } 23 | 24 | abstract class MeleeDecorator : MeleeAttack 25 | { 26 | MeleeAttack meleeAttack; 27 | 28 | public override int Attack() 29 | { 30 | if (meleeAttack != null) 31 | return meleeAttack.Attack(); 32 | else 33 | return 0; 34 | } 35 | 36 | public void SetMeleeAttack(MeleeAttack meleeAttack) 37 | { 38 | this.meleeAttack = meleeAttack; 39 | } 40 | } 41 | 42 | class HardPunch : MeleeDecorator 43 | { 44 | public override int Attack() 45 | { 46 | return base.Attack() + 10; 47 | } 48 | } 49 | 50 | class KiPunch : MeleeDecorator 51 | { 52 | ParticleSystem particleSystem; 53 | 54 | public KiPunch(ParticleSystem particleSystem) 55 | { 56 | if (particleSystem == null) 57 | throw new ArgumentNullException("Particle system cannot be null"); 58 | 59 | this.particleSystem = particleSystem; 60 | } 61 | 62 | public override int Attack() 63 | { 64 | AddedBehavior(); 65 | return base.Attack() + 100; 66 | } 67 | 68 | void AddedBehavior() 69 | { 70 | if (particleSystem != null) 71 | { 72 | GameObject newPsys = GameObject.Instantiate(particleSystem.gameObject); 73 | newPsys.SetActive(true); 74 | 75 | DestroyOnTime dot = newPsys.AddComponent(); 76 | 77 | dot.time = particleSystem.duration * 2f; 78 | } 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Assets/decorator/example1/MeleeAttack.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b3694270c5994474a96e528776c7e1e8 3 | timeCreated: 1450985674 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/decorator/example1/MeleeAttackClient.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using Assets.decorator.example1; 4 | 5 | public class MeleeAttackClient : MonoBehaviour 6 | { 7 | public ParticleSystem kiParticles; 8 | MeleeAttack baseMeleeAttack; 9 | MeleeDecorator hardPunch; 10 | MeleeDecorator kiPunch; 11 | MeleeDecorator superKiPunch; 12 | 13 | void Start() 14 | { 15 | baseMeleeAttack = new BaseMelee(); 16 | 17 | hardPunch = new HardPunch(); 18 | hardPunch.SetMeleeAttack(baseMeleeAttack); 19 | 20 | kiPunch = new KiPunch(kiParticles); 21 | kiPunch.SetMeleeAttack(baseMeleeAttack); 22 | 23 | // Set up the Super Ki Punch 24 | HardPunch hpDeco = new HardPunch(); 25 | hpDeco.SetMeleeAttack(baseMeleeAttack); 26 | superKiPunch = hpDeco; 27 | KiPunch kpDeco = new KiPunch(kiParticles); 28 | kpDeco.SetMeleeAttack(superKiPunch); 29 | superKiPunch = kpDeco; 30 | } 31 | 32 | 33 | void Update() 34 | { 35 | if (Input.GetKeyDown(KeyCode.Q)) 36 | Debug.Log("Base attack value: " + baseMeleeAttack.Attack()); 37 | 38 | if (Input.GetKeyDown(KeyCode.W)) 39 | Debug.Log("Hard punch value: " + hardPunch.Attack()); 40 | 41 | if (Input.GetKeyDown(KeyCode.E)) 42 | Debug.Log("Ki Punch value: " + kiPunch.Attack()); 43 | 44 | if (Input.GetKeyDown(KeyCode.R)) 45 | Debug.Log("Super Ki Punch value: " + superKiPunch.Attack()); 46 | } 47 | 48 | void OnGUI() 49 | { 50 | string label = "Q = Base attack\nW = Hard Punch\nE = Ki Punch\nR = Super Ki Punch"; 51 | 52 | GUI.Label(new Rect(0, 0, 500, 500), label); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Assets/decorator/example1/MeleeAttackClient.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2e5cb62f3cfaea3459a0739bbb888cef 3 | timeCreated: 1450985674 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/decorator/example1/melee_attack_decorator.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4a5feee92e4c06544b536eb980b6f629 3 | timeCreated: 1450985706 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/decorator/readme.md: -------------------------------------------------------------------------------- 1 | # Decorator Pattern 2 | Decorators attach additional responsibilities to an object dynamically. They provide a flexible alternative for extending functionality. 3 | 4 | ## Participants 5 | - **Component** - defines the interface for objects that can have responsibilities added to them dynamically. 6 | - **ConcreteComponent** - defines an object to which additional responsibilities can be attached. 7 | - **Decorator** - maintains a reference to a Component object and defines an interface that conforms to the Component's interface. 8 | - **ConcreteDecorator** adds responsibilities to the Component. 9 | 10 | ## Advantages 11 | 12 | - Allows behavior to be extended without modifying existing code. 13 | - Provides an alternative to subclassing for extending behavior. 14 | - Mirrors the type of components they decorate (they are actually the same type either through inheritance or interface implementation). 15 | - Alters the behavior of their components by adding new functionality before and / or after (or replaces) method calls to the components. 16 | - Components can be wrapped with any number of decorators. 17 | - They are typically transparent to the client of the component - unless the client is relying on the component's concrete type. 18 | 19 | ## Disadvantages 20 | 21 | - Can results in many small objects in the design and overuse can be complex making the API hard to understand. 22 | - If some code needs to be dependent on specific concrete types then the decorator's hiding of the concrete type can be a problem. 23 | - Instantiation of the component can be complex due to multiple layers of wrapping. 24 | 25 | ## Common Uses 26 | 27 | - Data streams are often wrapped by another stream to get added functionality (i.e. GZipStream around a FileStream). 28 | - Altering the sprite sheet used by an actor in the game based on any game state 29 | - Adding objects to an object while maintaining the base functionality (coffee shop example). 30 | 31 | 32 | ## Melee Attack Example 33 | 34 | **MeleeAttack.cs** 35 | 36 | - **MeleeAttack** - The **Component** class of the pattern, a very simple abstract class defining the Attack() method (the behavior). In the Decorator pattern the **Component** will often be an abstract class since we will need to override the behavior method with new methods in each decorator class. 37 | - **BaseMelee** - This is the **Concrete Component** class of the pattern inheriting from the abstract component. This is the component that will be decorated. Here I have defined the most basic form of attack. 38 | - **MeleeDecorator** - This is the **Decorator** class of the pattern, an abstract implementation of the component. It maintains a reference to the component class and overrides the Attack() method with a call to the referenced component class's Attack() method. 39 | - **HardPunch** and **KiPunch** - These are our **Concrete Decorators**. These inherit from the MeleeDecorator and override the Attack() method with additional behavior. In HardPunch, that is simply adding 10 to the attack. In KiPunch it is adding 100 to the attack as well as activating a particle system for the special effect. 40 | 41 | **MeleeAttackClient.cs** 42 | This is our MonoBehaviour class that will actually run the example. I have a public property, kiParticles, which is used to assign a particle system in the inspector that the ki punch will fire. Then there are some fields that will retain reference to the type of each attack so that we can call them specifically later. Note that the baseMeleeAttack needs to be of the type MeleeAttack. The others need to be of the type MeleeDecorator since that class contains the method to set the melee attack that is being decorated. 43 | In the Start() method I set up each of the attacks by decorating the same baseMelee attack since I want the other attacks to only add to the base attack. You can use the decorator to create many different attack combinations very easily. 44 | In the Update() method I have a some simple input handling so that we can see the differences logged for each attack / decorated attack. 45 | 46 | #### Notes 47 | 48 | Notice how building the Super Ki Punch is starting to make the process of decorating complicated and a little hard to follow. This is one of the disadvantages of the pattern as it has multiple layers wrapping the base component. This also may make it more difficult to tell what behaviors have been added to the base component later on in the code. Also the component and decorator abstractions seem to need to be abstract classes and can't be interfaces. This is due to the need to be able to override the behavior method and add the base to it. Therefore our concrete decorators are limited to inheritance instead of interface implementation and they're closely coupled to the concrete component. 49 | 50 | -------------------------------------------------------------------------------- /Assets/decorator/readme.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 303b267c980112c488605856ccbc8c45 3 | timeCreated: 1450985674 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/decorator/structure.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1adf1bf883171294c91ec3567f90b608 3 | folderAsset: yes 4 | timeCreated: 1450985674 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/decorator/structure/DecoratorParticipants.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Assets.decorator.structure 7 | { 8 | abstract class Component 9 | { 10 | public abstract void Operation(); 11 | } 12 | 13 | class ConcreteComponent : Component 14 | { 15 | public override void Operation() 16 | { 17 | Console.WriteLine("ConcreteComponent.Operation()"); 18 | } 19 | } 20 | 21 | abstract class Decorator : Component 22 | { 23 | protected Component component; 24 | 25 | public void SetComponent(Component component) 26 | { 27 | this.component = component; 28 | } 29 | 30 | public override void Operation() 31 | { 32 | if (component != null) 33 | { 34 | component.Operation(); 35 | } 36 | } 37 | } 38 | 39 | class ConcreteDecoratorA : Decorator 40 | { 41 | public override void Operation() 42 | { 43 | base.Operation(); 44 | Console.WriteLine("ConcreteDecoratorA.Operation()"); 45 | } 46 | } 47 | 48 | class ConcreteDecoratorB : Decorator 49 | { 50 | public override void Operation() 51 | { 52 | base.Operation(); 53 | AddedBehavior(); 54 | Console.WriteLine("ConcreteDecoratorB.Operation()"); 55 | } 56 | 57 | void AddedBehavior() 58 | { 59 | Console.WriteLine("ConcreteDecoratorB.AddedBehavior()"); 60 | } 61 | 62 | } 63 | 64 | class App 65 | { 66 | static void Main() 67 | { 68 | // Create ConcreteComponent and 2 decorators 69 | ConcreteComponent c = new ConcreteComponent(); 70 | ConcreteDecoratorA d1 = new ConcreteDecoratorA(); 71 | ConcreteDecoratorB d2 = new ConcreteDecoratorB(); 72 | 73 | // Link decorators 74 | d1.SetComponent(c); 75 | d2.SetComponent(d1); 76 | 77 | d2.Operation(); 78 | 79 | /* 80 | Will output: 81 | ConcreteComponent.Operation() 82 | ConcreteDecoratorA.Operation() 83 | ConcreteDecoratorB.AddedBehavior() 84 | ConcreteDecoratorB.Operation() 85 | */ 86 | 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Assets/decorator/structure/DecoratorParticipants.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d53c9155531a65d4380f5c29df57dad4 3 | timeCreated: 1450985677 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/extras.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4b15af96bd23d9440ae4f0184bd7d61b 3 | folderAsset: yes 4 | timeCreated: 1449380063 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/extras/3D Text Shader.shader: -------------------------------------------------------------------------------- 1 | Shader "GUI/3D Text Shader" { 2 | Properties{ 3 | _MainTex("Font Texture", 2D) = "white" {} 4 | _Color("Text Color", Color) = (1,1,1,1) 5 | } 6 | 7 | SubShader{ 8 | Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" } 9 | Lighting Off Cull Off ZWrite Off Fog{ Mode Off } 10 | Blend SrcAlpha OneMinusSrcAlpha 11 | Pass{ 12 | Color[_Color] 13 | SetTexture[_MainTex]{ 14 | combine primary, texture * primary 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Assets/extras/3D Text Shader.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ef498df3bdef20b4185bca5fa6655306 3 | timeCreated: 1449380021 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/extras/3d font material.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: 3d font material 10 | m_Shader: {fileID: 4800000, guid: ef498df3bdef20b4185bca5fa6655306, type: 3} 11 | m_ShaderKeywords: 12 | m_LightmapFlags: 5 13 | m_CustomRenderQueue: 3000 14 | stringTagMap: {} 15 | m_SavedProperties: 16 | serializedVersion: 2 17 | m_TexEnvs: 18 | data: 19 | first: 20 | name: _MainTex 21 | second: 22 | m_Texture: {fileID: 2800000, guid: 3305a5dce35ebce42b9ca54b51041f70, type: 3} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | data: 26 | first: 27 | name: _BumpMap 28 | second: 29 | m_Texture: {fileID: 0} 30 | m_Scale: {x: 1, y: 1} 31 | m_Offset: {x: 0, y: 0} 32 | data: 33 | first: 34 | name: _DetailNormalMap 35 | second: 36 | m_Texture: {fileID: 0} 37 | m_Scale: {x: 1, y: 1} 38 | m_Offset: {x: 0, y: 0} 39 | data: 40 | first: 41 | name: _ParallaxMap 42 | second: 43 | m_Texture: {fileID: 0} 44 | m_Scale: {x: 1, y: 1} 45 | m_Offset: {x: 0, y: 0} 46 | data: 47 | first: 48 | name: _OcclusionMap 49 | second: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | data: 54 | first: 55 | name: _EmissionMap 56 | second: 57 | m_Texture: {fileID: 0} 58 | m_Scale: {x: 1, y: 1} 59 | m_Offset: {x: 0, y: 0} 60 | data: 61 | first: 62 | name: _DetailMask 63 | second: 64 | m_Texture: {fileID: 0} 65 | m_Scale: {x: 1, y: 1} 66 | m_Offset: {x: 0, y: 0} 67 | data: 68 | first: 69 | name: _DetailAlbedoMap 70 | second: 71 | m_Texture: {fileID: 0} 72 | m_Scale: {x: 1, y: 1} 73 | m_Offset: {x: 0, y: 0} 74 | data: 75 | first: 76 | name: _MetallicGlossMap 77 | second: 78 | m_Texture: {fileID: 0} 79 | m_Scale: {x: 1, y: 1} 80 | m_Offset: {x: 0, y: 0} 81 | m_Floats: 82 | data: 83 | first: 84 | name: _SrcBlend 85 | second: 1 86 | data: 87 | first: 88 | name: _DstBlend 89 | second: 0 90 | data: 91 | first: 92 | name: _Cutoff 93 | second: 0.5 94 | data: 95 | first: 96 | name: _Parallax 97 | second: 0.02 98 | data: 99 | first: 100 | name: _ZWrite 101 | second: 1 102 | data: 103 | first: 104 | name: _Glossiness 105 | second: 0.5 106 | data: 107 | first: 108 | name: _BumpScale 109 | second: 1 110 | data: 111 | first: 112 | name: _OcclusionStrength 113 | second: 1 114 | data: 115 | first: 116 | name: _DetailNormalMapScale 117 | second: 1 118 | data: 119 | first: 120 | name: _UVSec 121 | second: 0 122 | data: 123 | first: 124 | name: _Mode 125 | second: 0 126 | data: 127 | first: 128 | name: _Metallic 129 | second: 0 130 | m_Colors: 131 | data: 132 | first: 133 | name: _EmissionColor 134 | second: {r: 0, g: 0, b: 0, a: 1} 135 | data: 136 | first: 137 | name: _Color 138 | second: {r: 0, g: 0, b: 0, a: 1} 139 | -------------------------------------------------------------------------------- /Assets/extras/3d font material.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9840d07baaa60ce479e04287eb92df60 3 | timeCreated: 1449380117 4 | licenseType: Free 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/extras/ARIAL.TTF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Naphier/unity-design-patterns/ab864774b0b75b2ecad1ef8f946ba985d02ea7dd/Assets/extras/ARIAL.TTF -------------------------------------------------------------------------------- /Assets/extras/ARIAL.TTF.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3305a5dce35ebce42b9ca54b51041f70 3 | timeCreated: 1449380172 4 | licenseType: Free 5 | TrueTypeFontImporter: 6 | serializedVersion: 2 7 | fontSize: 16 8 | forceTextureCase: -2 9 | characterSpacing: 1 10 | characterPadding: 0 11 | includeFontData: 1 12 | use2xBehaviour: 0 13 | fontNames: [] 14 | fallbackFontReferences: [] 15 | customCharacters: 16 | fontRenderingMode: 0 17 | userData: 18 | assetBundleName: 19 | assetBundleVariant: 20 | -------------------------------------------------------------------------------- /Assets/extras/DestroyOnTime.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | public class DestroyOnTime : MonoBehaviour 5 | { 6 | public float time = 0f; 7 | void Start() 8 | { 9 | StartCoroutine(DelayedDestroy()); 10 | } 11 | 12 | IEnumerator DelayedDestroy() 13 | { 14 | yield return new WaitForSeconds(time); 15 | 16 | Destroy(gameObject); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /Assets/extras/DestroyOnTime.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 430fde0ab9370c44fad36149c70bfc24 3 | timeCreated: 1450994828 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/extras/ParticleSystemDebug.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | [RequireComponent(typeof(ParticleSystem))] 5 | public class ParticleSystemDebug : MonoBehaviour 6 | { 7 | ParticleSystem pSys; 8 | public bool show = true; 9 | 10 | void Start() 11 | { 12 | pSys = gameObject.GetComponent(); 13 | } 14 | 15 | void Update() 16 | { 17 | if (Input.GetMouseButtonDown(0)) 18 | { 19 | pSys.Stop(); 20 | pSys.Clear(); 21 | pSys.Play(); 22 | } 23 | 24 | if (Input.GetMouseButton(0)) 25 | pSys.Emit(1); 26 | } 27 | 28 | void OnGUI() 29 | { 30 | if (!show) 31 | return; 32 | 33 | string meessage = string.Format( 34 | "isPlaying: {0}" + 35 | "\nisPaused: {1}" + 36 | "\nisStopped: {2}" + 37 | "\nisAlive: {3}" + 38 | "\nemission.enabled: {4}" + 39 | "\nparticleCount: {5}", 40 | pSys.isPlaying, 41 | pSys.isPaused, 42 | pSys.isStopped, 43 | pSys.IsAlive(), 44 | pSys.emission.enabled, 45 | pSys.particleCount 46 | ); 47 | 48 | GUI.Label(new Rect(300, 0, 500, 500), meessage); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Assets/extras/ParticleSystemDebug.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: da4be137777c2314fa6de4394955df7e 3 | timeCreated: 1450993600 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/extras/ground.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: ground 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: 12 | m_LightmapFlags: 5 13 | m_CustomRenderQueue: -1 14 | stringTagMap: {} 15 | m_SavedProperties: 16 | serializedVersion: 2 17 | m_TexEnvs: 18 | data: 19 | first: 20 | name: _MainTex 21 | second: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | data: 26 | first: 27 | name: _BumpMap 28 | second: 29 | m_Texture: {fileID: 0} 30 | m_Scale: {x: 1, y: 1} 31 | m_Offset: {x: 0, y: 0} 32 | data: 33 | first: 34 | name: _DetailNormalMap 35 | second: 36 | m_Texture: {fileID: 0} 37 | m_Scale: {x: 1, y: 1} 38 | m_Offset: {x: 0, y: 0} 39 | data: 40 | first: 41 | name: _ParallaxMap 42 | second: 43 | m_Texture: {fileID: 0} 44 | m_Scale: {x: 1, y: 1} 45 | m_Offset: {x: 0, y: 0} 46 | data: 47 | first: 48 | name: _OcclusionMap 49 | second: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | data: 54 | first: 55 | name: _EmissionMap 56 | second: 57 | m_Texture: {fileID: 0} 58 | m_Scale: {x: 1, y: 1} 59 | m_Offset: {x: 0, y: 0} 60 | data: 61 | first: 62 | name: _DetailMask 63 | second: 64 | m_Texture: {fileID: 0} 65 | m_Scale: {x: 1, y: 1} 66 | m_Offset: {x: 0, y: 0} 67 | data: 68 | first: 69 | name: _DetailAlbedoMap 70 | second: 71 | m_Texture: {fileID: 0} 72 | m_Scale: {x: 1, y: 1} 73 | m_Offset: {x: 0, y: 0} 74 | data: 75 | first: 76 | name: _MetallicGlossMap 77 | second: 78 | m_Texture: {fileID: 0} 79 | m_Scale: {x: 1, y: 1} 80 | m_Offset: {x: 0, y: 0} 81 | m_Floats: 82 | data: 83 | first: 84 | name: _SrcBlend 85 | second: 1 86 | data: 87 | first: 88 | name: _DstBlend 89 | second: 0 90 | data: 91 | first: 92 | name: _Cutoff 93 | second: 0.5 94 | data: 95 | first: 96 | name: _Parallax 97 | second: 0.02 98 | data: 99 | first: 100 | name: _ZWrite 101 | second: 1 102 | data: 103 | first: 104 | name: _Glossiness 105 | second: 0 106 | data: 107 | first: 108 | name: _BumpScale 109 | second: 1 110 | data: 111 | first: 112 | name: _OcclusionStrength 113 | second: 1 114 | data: 115 | first: 116 | name: _DetailNormalMapScale 117 | second: 1 118 | data: 119 | first: 120 | name: _UVSec 121 | second: 0 122 | data: 123 | first: 124 | name: _Mode 125 | second: 0 126 | data: 127 | first: 128 | name: _Metallic 129 | second: 0 130 | m_Colors: 131 | data: 132 | first: 133 | name: _EmissionColor 134 | second: {r: 0, g: 0, b: 0, a: 1} 135 | data: 136 | first: 137 | name: _Color 138 | second: {r: 0.051318508, g: 0.32352942, b: 0, a: 1} 139 | -------------------------------------------------------------------------------- /Assets/extras/ground.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d6c91508741316e44a8f4d7012827dd6 3 | timeCreated: 1450937307 4 | licenseType: Free 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/factory method pattern.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5bc79961dae6d414ab34647167738f46 3 | folderAsset: yes 4 | timeCreated: 1449375932 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/factory method pattern/example.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 42f43bfd75fb9844394ca9c497171c9d 3 | folderAsset: yes 4 | timeCreated: 1449375932 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/factory method pattern/example/ConcreteDocuments.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace NG.factory_method_pattern.example 4 | { 5 | class CharacterSheet : Document 6 | { 7 | public CharacterSheet(GameObject textMesh, GameObject paper) : base(textMesh, paper) 8 | { 9 | documentHolder.name = this.GetType().Name; 10 | } 11 | 12 | 13 | public override void CreatePages(GameObject textMesh, GameObject paper) 14 | { 15 | int pageNum = 1; 16 | Page p = new Contents("Table of Contents", textMesh, paper, pageNum++); 17 | Page contents = p; 18 | p.page.transform.SetParent(documentHolder.transform); 19 | _pages.Add(p); 20 | p = new Stats("Character Stats", textMesh, paper, pageNum++); 21 | p.page.transform.SetParent(documentHolder.transform); 22 | _pages.Add(p); 23 | p = new Skills("Character Skills", textMesh, paper, pageNum++); 24 | p.page.transform.SetParent(documentHolder.transform); 25 | _pages.Add(p); 26 | 27 | SetTableOfContentsList(contents); 28 | } 29 | } 30 | 31 | class Spellbook : Document 32 | { 33 | public Spellbook(GameObject textMesh, GameObject paper) : base(textMesh, paper) 34 | { 35 | documentHolder.name = this.GetType().Name; 36 | } 37 | 38 | 39 | public override void CreatePages(GameObject textMesh, GameObject paper) 40 | { 41 | int pageNum = 1; 42 | Page p = new Contents("Table of Contents", textMesh, paper, pageNum++); 43 | Page contents = p; 44 | p.page.transform.SetParent(documentHolder.transform); 45 | _pages.Add(p); 46 | p = new EarthSpells("Earth", textMesh, paper, pageNum++); 47 | p.page.transform.SetParent(documentHolder.transform); 48 | _pages.Add(p); 49 | p = new WindSpells("Wind", textMesh, paper, pageNum++); 50 | p.page.transform.SetParent(documentHolder.transform); 51 | _pages.Add(p); 52 | p = new FireSpells("Fire", textMesh, paper, pageNum++); 53 | p.page.transform.SetParent(documentHolder.transform); 54 | _pages.Add(p); 55 | p = new WaterSpells("Water", textMesh, paper, pageNum++); 56 | p.page.transform.SetParent(documentHolder.transform); 57 | _pages.Add(p); 58 | 59 | SetTableOfContentsList(contents); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Assets/factory method pattern/example/ConcreteDocuments.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4d0662007dd81864aa93dc1a7eaeb989 3 | timeCreated: 1449382182 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/factory method pattern/example/ConcretePages.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace NG.factory_method_pattern.example 4 | { 5 | public class Contents : Page 6 | { 7 | public Contents(string text, GameObject textMesh, GameObject paper, int pageNum) : base(text, textMesh, paper, pageNum) 8 | { 9 | if (page != null) 10 | page.name = this.GetType().Name; 11 | } 12 | } 13 | 14 | public class Stats : Page 15 | { 16 | public Stats(string text, GameObject textMesh, GameObject paper, int pageNum) : base(text, textMesh, paper, pageNum) 17 | { 18 | if (page != null) 19 | page.name = this.GetType().Name; 20 | } 21 | } 22 | 23 | public class Skills : Page 24 | { 25 | public Skills(string text, GameObject textMesh, GameObject paper, int pageNum) : base(text, textMesh, paper, pageNum) 26 | { 27 | if (page != null) 28 | page.name = this.GetType().Name; 29 | } 30 | } 31 | 32 | public class EarthSpells : Page 33 | { 34 | public EarthSpells(string text, GameObject textMesh, GameObject paper, int pageNum) : base(text, textMesh, paper, pageNum) 35 | { 36 | if (page != null) 37 | page.name = this.GetType().Name; 38 | } 39 | } 40 | 41 | public class WindSpells : Page 42 | { 43 | public WindSpells(string text, GameObject textMesh, GameObject paper, int pageNum) : base(text, textMesh, paper, pageNum) 44 | { 45 | if (page != null) 46 | page.name = this.GetType().Name; 47 | } 48 | } 49 | 50 | public class FireSpells : Page 51 | { 52 | public FireSpells(string text, GameObject textMesh, GameObject paper, int pageNum) : base(text, textMesh, paper, pageNum) 53 | { 54 | if (page != null) 55 | page.name = this.GetType().Name; 56 | } 57 | } 58 | 59 | public class WaterSpells : Page 60 | { 61 | public WaterSpells(string text, GameObject textMesh, GameObject paper, int pageNum) : base(text, textMesh, paper, pageNum) 62 | { 63 | if (page != null) 64 | page.name = this.GetType().Name; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Assets/factory method pattern/example/ConcretePages.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4f8f9325ed39e9040ade5bd95415dd62 3 | timeCreated: 1449382182 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/factory method pattern/example/DocumentMaker.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections.Generic; 3 | using System.Collections; 4 | using NG.factory_method_pattern.example; 5 | 6 | public class DocumentMaker : MonoBehaviour 7 | { 8 | public GameObject textMeshPrefab; 9 | public GameObject paperPrefab; 10 | 11 | private List documents = new List(); 12 | 13 | void Start() 14 | { 15 | documents.Add(new CharacterSheet(textMeshPrefab, paperPrefab)); 16 | documents.Add(new Spellbook(textMeshPrefab, paperPrefab)); 17 | StartCoroutine(DisplayDocuments()); 18 | } 19 | 20 | IEnumerator DisplayDocuments() 21 | { 22 | while (true) 23 | { 24 | foreach (Document d in documents) 25 | { 26 | d.documentHolder.SetActive(false); 27 | } 28 | 29 | foreach (Document d in documents) 30 | { 31 | d.documentHolder.SetActive(true); 32 | foreach (Page p in d.pages) 33 | { 34 | p.page.SetActive(true); 35 | } 36 | yield return new WaitForSeconds(2f); 37 | 38 | for (int i = 1; i < d.pages.Count; i++) 39 | { 40 | yield return new WaitForSeconds(1f); 41 | d.pages[i - 1].page.SetActive(false); 42 | 43 | } 44 | 45 | yield return new WaitForSeconds(1f); 46 | d.documentHolder.SetActive(false); 47 | 48 | } 49 | 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Assets/factory method pattern/example/DocumentMaker.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f3533dff403791646b7909d7ecb48562 3 | timeCreated: 1449377220 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/factory method pattern/example/FactoryMethodExampleAbstractions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using UnityEngine; 6 | 7 | namespace NG.factory_method_pattern.example 8 | { 9 | public class Page 10 | { 11 | public GameObject page; 12 | public GameObject paper; 13 | public GameObject textMesh; 14 | private TextMesh _tm; 15 | 16 | 17 | public Page(string text , GameObject textMesh , GameObject paper, int pageNum) 18 | { 19 | this.page = new GameObject("page"); 20 | 21 | this.textMesh = GameObject.Instantiate(textMesh, Vector3.zero, Quaternion.identity) as GameObject; 22 | this.textMesh.transform.SetParent(this.page.transform); 23 | this.textMesh.transform.localPosition = new Vector3(-4.7f, 4.7f, -0.1f); 24 | _tm = this.textMesh.GetComponent(); 25 | if (_tm != null) 26 | _tm.text = text; 27 | 28 | this.paper = GameObject.Instantiate(paper, Vector3.zero, Quaternion.identity) as GameObject; 29 | this.paper.transform.SetParent(this.page.transform); 30 | this.paper.transform.eulerAngles = new Vector3(-90f, 0, 0); 31 | 32 | this.page.transform.position += Vector3.forward * pageNum / 5f; 33 | } 34 | 35 | public void SetPageContents(string text) 36 | { 37 | if (_tm != null) 38 | _tm.text = text; 39 | } 40 | 41 | public void AddToPageContents(string text) 42 | { 43 | if (_tm != null) 44 | _tm.text += text; 45 | } 46 | 47 | public string GetPageText() 48 | { 49 | string text = ""; 50 | 51 | if (_tm != null) 52 | { 53 | text = _tm.text; 54 | } 55 | 56 | return text; 57 | } 58 | } 59 | 60 | 61 | abstract class Document 62 | { 63 | protected List _pages = new List(); 64 | public GameObject documentHolder { get; protected set; } 65 | 66 | public Document(GameObject textMesh, GameObject paper) 67 | { 68 | documentHolder = new GameObject(); 69 | this.CreatePages(textMesh, paper); 70 | } 71 | 72 | public List pages 73 | { 74 | get { return _pages; } 75 | } 76 | 77 | public abstract void CreatePages(GameObject textMesh, GameObject paper); 78 | 79 | protected void SetTableOfContentsList(Page contents) 80 | { 81 | foreach (Page page in _pages) 82 | { 83 | if (page != contents) 84 | contents.AddToPageContents("\n" + page.GetType().Name); 85 | } 86 | } 87 | } 88 | 89 | 90 | } 91 | -------------------------------------------------------------------------------- /Assets/factory method pattern/example/FactoryMethodExampleAbstractions.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f7f5c1ddd8f25f74f9b5d32373fa69f2 3 | timeCreated: 1449377220 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/factory method pattern/example/factory_method_pattern.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f8182c383d9322544ab99675bfc61dbc 3 | timeCreated: 1449375984 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/factory method pattern/readme.md: -------------------------------------------------------------------------------- 1 | # Factory Method 2 | The Factory Method pattern defines an interface for creating an object where the subclasses decide which class to instantiate. 3 | 4 | ### Structure 5 | The structural example can be found in **FactoryMethodStructure.cs**. Note how in the MainApp class endpoint where we are actually using the factory method our calls to create the instances of the product classes are fairly ambiguous. 6 | 7 | - **Product** - This is the abstraction of a base class that would be used for the subclasses which can be created by the Creator. 8 | - **ConcreteProduct** - The actual classes that will get instantiated by the creator. 9 | - **Creator** - An abstract class that allows us to interface with the concrete creators. 10 | - **ConcreteCreator** - The actual classes that decide what products to instantiate. 11 | 12 | ### Example 13 | Let's take into consideration a game where we need to build a variety of types of books. 14 | 15 | - **FactoryMethodExampleAbstractions.cs** 16 | - **Page** This is a base class from which we will create our subclasses (our concrete pages). It has a constructor that assigns the class fields and does some work to create the game object structure for a page. I added in some methods for getting, setting, and adding to the text contents of the pages. 17 | - **Document** This is the 'abstract Creator' for the pattern. It has a constructor to make a parent game object to hold all of our pages, an abstract method to create pages (all Creators need to define how this is done. Note that the constructor also calls CreatePages which is actually defined in the subclasses. It also has a common method to automatically fill out the table of contents page. 18 | 19 | - **ConcretePages.cs** - Here we define our actual pages and basically each page just has a constructor that only adds to the base constructor by setting the name of the 'page' game object in the Page class. 20 | 21 | - **ConcreteDocuments.cs** - Here we define our 'ConcreteCreator' classes. They have a constructor which adds to the base class's constructor and sets the name on the documentHolder game object to the name of the concrete document class (i.e. ChracterSheet, SpellBook). Then we have our required definition of CreatePages. CreatePages makes each concrete page via its constructor, adds them to the _page List for the document, and finally sets the table of contents list. 22 | 23 | - **DocumentMaker.cs** - This is our MonoBehaviour class that will run the Document creators and then it has a simple coroutine that flips through the pages so we can see them all there. 24 | 25 | ### Afterthoughts 26 | This pattern feels a bit heavy and very similar to a Builder pattern. The main difference is that in the Factory Method pattern the subclasses are deciding how to put the products (pages) together to form the final product. In the Builder pattern the 'Director' class tells the 'Builder' classes how to construct their final products. I'd love to have a discussion on the differences between this pattern and the Builder pattern. Anyone interested can start an issue where we can discuss it! 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Assets/factory method pattern/readme.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e983bfd817f63a74aa12eac051ead261 3 | timeCreated: 1449375932 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/factory method pattern/structure.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cfcd10342b4ffe94cb8aa4ae9c8223a1 3 | folderAsset: yes 4 | timeCreated: 1449375932 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/factory method pattern/structure/FactoryMethodStructure.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NG.factory_method_pattern.structure 4 | { 5 | abstract class Product { } 6 | 7 | class ConcreteProductA : Product { } 8 | 9 | class ConcreteProductB : Product { } 10 | 11 | abstract class Creator 12 | { 13 | public abstract Product FactoryMethod(); 14 | } 15 | 16 | class ConcreteCreatorA : Creator 17 | { 18 | public override Product FactoryMethod() 19 | { 20 | return new ConcreteProductA(); 21 | } 22 | } 23 | 24 | class ConcreteCreatorB : Creator 25 | { 26 | public override Product FactoryMethod() 27 | { 28 | return new ConcreteProductB(); 29 | } 30 | } 31 | 32 | 33 | class MainApp 34 | { 35 | void Run() 36 | { 37 | Creator[] creators = new Creator[2]; 38 | creators[0] = new ConcreteCreatorA(); 39 | creators[1] = new ConcreteCreatorB(); 40 | 41 | foreach (Creator creator in creators) 42 | { 43 | Product product = creator.FactoryMethod(); 44 | Console.WriteLine("Created {0}", product.GetType().Name); 45 | } 46 | 47 | Console.Read(); 48 | } 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Assets/factory method pattern/structure/FactoryMethodStructure.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2d448ac7e08a5d341989d6505f710541 3 | timeCreated: 1449375935 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/flyweight pattern.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7edd6f0448973f74fb944fef2b435dca 3 | folderAsset: yes 4 | timeCreated: 1444062649 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 88422b8b1a3d25244ba5ddea6ce2f4b8 3 | timeCreated: 1449216650 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/example.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0292e97f14e65554eb8889d6b2278d10 3 | folderAsset: yes 4 | timeCreated: 1446958626 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/example/Insects.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System; 3 | using System.Collections; 4 | 5 | namespace NG.Flyweight.Example 6 | { 7 | enum InsectType { fly, beetle, ant } 8 | 9 | abstract class InsectBase 10 | { 11 | // Total data size = 34 bytes 12 | // Imagine if we needed 10,000 of each insect, the data alone would require 3 * 10,000 * 34 = 102,000 bytes or 102kb 13 | // With the flyweight in use the shared data only ever requires at most 34 * 3 = 102 bytes 14 | #region Intrinsic States 15 | public InsectType insectType { get; protected set; }// 4 bytes 16 | protected int size; 17 | protected int legs; 18 | protected int eyes; 19 | protected int antennae; 20 | protected int toughness; 21 | public int maxHealth { get; protected set; } 22 | protected int hunger; 23 | protected bool canFly; // 1 byte 24 | protected bool canBurrow; 25 | #endregion 26 | 27 | #region Extrinsic State 28 | // Some "stateful" object - here an int that is calculated in the method. 29 | public abstract int GetStrength(int health); 30 | #endregion 31 | } 32 | 33 | class Insect : InsectBase 34 | { 35 | public Insect(InsectType insectType) 36 | { 37 | this.insectType = insectType; 38 | antennae = 2; 39 | legs = 6; 40 | 41 | switch (insectType) 42 | { 43 | case InsectType.fly: 44 | size = 2; 45 | eyes = 1000; 46 | toughness = 1; 47 | maxHealth = 100; 48 | hunger = 100; 49 | canFly = true; 50 | canBurrow = false; 51 | break; 52 | case InsectType.beetle: 53 | size = 4; 54 | eyes = 2; 55 | toughness = 10; 56 | maxHealth = 500; 57 | hunger = 10; 58 | canFly = true; 59 | canBurrow = true; 60 | break; 61 | case InsectType.ant: 62 | size = 1; 63 | eyes = 2; 64 | toughness = 10; 65 | maxHealth = 100; 66 | hunger = 50; 67 | canFly = false; 68 | canBurrow = true; 69 | break; 70 | default: 71 | throw new ArgumentException(); 72 | } 73 | } 74 | 75 | public override int GetStrength(int health) 76 | { 77 | return size + toughness + (canFly ? 1 : 0) + (canBurrow ? 1 : 0) + health; 78 | } 79 | } 80 | 81 | class InsectFlyweightFactory 82 | { 83 | public bool showMessages = false; 84 | 85 | private Hashtable _createdInsects = new Hashtable(); 86 | 87 | public Insect GetInsectData(InsectType insectType) 88 | { 89 | if (_createdInsects.ContainsKey(insectType)) 90 | { 91 | if (showMessages) 92 | Debug.Log("Reusing " + insectType.ToString()); 93 | 94 | return _createdInsects[insectType] as Insect; 95 | } 96 | else 97 | { 98 | if (showMessages) 99 | Debug.LogWarning("Creating " + insectType.ToString()); 100 | 101 | Insect insect = new Insect(insectType); 102 | _createdInsects.Add(insectType, insect); 103 | return insect; 104 | } 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/example/Insects.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4def9dcaa25a5bf4f98a1131e7e6b310 3 | timeCreated: 1449292898 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/example/InsectsFlyweightExample.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections.Generic; 3 | 4 | using NG.Flyweight.Example; 5 | 6 | public class InsectsFlyweightExample : MonoBehaviour 7 | { 8 | 9 | 10 | void Start() 11 | { 12 | // Illustrate that factory reuses already made insects 13 | InsectFlyweightFactory insectFactory = new InsectFlyweightFactory(); 14 | insectFactory.showMessages = true; 15 | 16 | Debug.LogError("Testing reuse of insects"); 17 | for (int i = 0; i < 3; i++) 18 | { 19 | for (int j = 0; j < 3; j++) 20 | { 21 | insectFactory.GetInsectData( (InsectType)i ); 22 | } 23 | } 24 | 25 | Debug.LogError("Testing the pattern in action"); 26 | // An example of how this might work to our advantage. 27 | for (int i = 0; i < 3; i++) 28 | { 29 | Insect challenger = insectFactory.GetInsectData( (InsectType)i ); 30 | Debug.Log("Insect to test: " + challenger.insectType.ToString()); 31 | 32 | List defeatedInsect = new List(); 33 | 34 | // At what point can challenger be stronger than other insects at varying health. 35 | for (int j = 0; j < challenger.maxHealth; j++) 36 | { 37 | for (int k = 0; k < 3; k++) 38 | { 39 | if (k == i) // Don't attack insects of the same type. 40 | continue; 41 | 42 | InsectType insectType = (InsectType)k; 43 | 44 | if (defeatedInsect.Contains(insectType)) 45 | continue; 46 | 47 | Insect defender = insectFactory.GetInsectData(insectType); 48 | 49 | for (int m = defender.maxHealth; m >= 0; m--) 50 | { 51 | int challengerStrength = challenger.GetStrength(j); 52 | int defenderStrength = defender.GetStrength(m); 53 | 54 | if (challengerStrength > defenderStrength) 55 | { 56 | defeatedInsect.Add(insectType); 57 | Debug.LogWarning(challenger.insectType.ToString() + " at health: " + j.ToString() + " defeated " + defender.insectType.ToString() + " at full health of " + defender.maxHealth.ToString()); 58 | break; 59 | } 60 | } 61 | 62 | } 63 | } 64 | 65 | // Check if anyone wasn't defeated. 66 | for (int h = 0; h < 3; h++) 67 | { 68 | if (h == i) // Insects of the same type won't be checked since we didn't even try to attack them. 69 | continue; 70 | 71 | InsectType insectType = (InsectType)h; 72 | if (!defeatedInsect.Contains(insectType)) 73 | Debug.LogError(challenger.insectType.ToString() + " could not defeat " + insectType.ToString()); 74 | } 75 | } 76 | } 77 | 78 | void Update() 79 | { 80 | 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/example/InsectsFlyweightExample.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 503ac55001b5e014fabbca70278c3a0d 3 | timeCreated: 1449296115 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/example/insects_flyweight_example.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f113ce4696e4f5f498516e74cb9ec2ac 3 | timeCreated: 1449298692 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/example2.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7c7812c748d49fc418b5aa9a500c57da 3 | folderAsset: yes 4 | timeCreated: 1450937206 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/example2/ConcreteSoldiers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using UnityEngine; 6 | 7 | namespace Assets.flyweight_pattern.example2 8 | { 9 | class Archer : ISoldierFlyweight 10 | { 11 | private SoldierStats _Stats = null; 12 | 13 | public SoldierStats Stats 14 | { 15 | get 16 | { 17 | if (_Stats == null) 18 | { 19 | _Stats = new SoldierStats() 20 | { 21 | Attack = 15, 22 | Defense = 4, 23 | MaxHealth = 20, 24 | Dexterity = 20, 25 | Level = 1 26 | }; 27 | } 28 | 29 | return _Stats; 30 | } 31 | } 32 | 33 | public WeaponType Weapon 34 | { 35 | get 36 | { 37 | return WeaponType.Bow; 38 | } 39 | } 40 | 41 | 42 | 43 | public void LevelUp() 44 | { 45 | Stats.Level++; 46 | Stats.Attack += Stats.Level; 47 | Stats.Dexterity = (int)Math.Round(1.25f * Stats.Dexterity); 48 | Stats.MaxHealth += Stats.Level; 49 | Stats.Defense++; 50 | } 51 | 52 | public Color GetColor(int hitPoints) 53 | { 54 | if (hitPoints <= Stats.MaxHealth / 2) 55 | return Color.red; 56 | else 57 | return Color.green; 58 | } 59 | } 60 | 61 | 62 | class Knight : ISoldierFlyweight 63 | { 64 | private SoldierStats _Stats = null; 65 | 66 | public SoldierStats Stats 67 | { 68 | get 69 | { 70 | if (_Stats == null) 71 | { 72 | _Stats = new SoldierStats() 73 | { 74 | Attack = 25, 75 | Defense = 20, 76 | MaxHealth = 30, 77 | Dexterity = 5, 78 | Level = 1 79 | }; 80 | } 81 | 82 | return _Stats; 83 | } 84 | } 85 | 86 | public WeaponType Weapon 87 | { 88 | get 89 | { 90 | return WeaponType.Sword; 91 | } 92 | } 93 | 94 | public void LevelUp() 95 | { 96 | Stats.Level++; 97 | Stats.Attack += (int)Math.Round(1.25f * Stats.Attack); 98 | Stats.Dexterity += Stats.Level / 2; 99 | Stats.MaxHealth += Stats.Level; 100 | Stats.Defense++; 101 | } 102 | 103 | public Color GetColor(int hitPoints) 104 | { 105 | if (hitPoints <= Stats.MaxHealth / 2) 106 | return Color.magenta; 107 | else 108 | return Color.gray; 109 | } 110 | } 111 | 112 | 113 | class Calvary : ISoldierFlyweight 114 | { 115 | private SoldierStats _Stats = null; 116 | 117 | public SoldierStats Stats 118 | { 119 | get 120 | { 121 | if (_Stats == null) 122 | { 123 | _Stats = new SoldierStats() 124 | { 125 | Attack = 30, 126 | Defense = 20, 127 | MaxHealth = 25, 128 | Dexterity = 10, 129 | Level = 1 130 | }; 131 | } 132 | 133 | return _Stats; 134 | } 135 | } 136 | 137 | public WeaponType Weapon 138 | { 139 | get 140 | { 141 | return WeaponType.Lance; 142 | } 143 | } 144 | 145 | public void LevelUp() 146 | { 147 | Stats.Level++; 148 | Stats.Attack += Stats.Level / 2; 149 | Stats.Dexterity += Stats.Level / 2; 150 | Stats.MaxHealth += Stats.Level / 2; 151 | Stats.Defense++; 152 | } 153 | 154 | public Color GetColor(int hitPoints) 155 | { 156 | if (hitPoints <= Stats.MaxHealth / 2) 157 | return Color.yellow; 158 | else 159 | return Color.black; 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/example2/ConcreteSoldiers.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4662d40363d79874486c4d0ac1725d9e 3 | timeCreated: 1450937206 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/example2/ISoldierFlyweight.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Assets.flyweight_pattern.example2 7 | { 8 | interface ISoldierFlyweight 9 | { 10 | #region Intrinsic States 11 | 12 | SoldierStats Stats { get;} 13 | WeaponType Weapon { get; } 14 | // Operation that will affect all concrete soldiers. 15 | // This modifies the intrinsic state of Stats 16 | void LevelUp(); 17 | 18 | #endregion 19 | 20 | 21 | #region Extrinsic State 22 | 23 | //Operation based on an extrinsic value, hitPoints 24 | UnityEngine.Color GetColor(int hitPoints); 25 | 26 | #endregion 27 | } 28 | 29 | public enum WeaponType 30 | { 31 | Sword, Bow, Lance 32 | } 33 | 34 | class SoldierStats 35 | { 36 | public int Attack; 37 | public int Defense; 38 | public int MaxHealth; 39 | public int Dexterity; 40 | public int Level; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/example2/ISoldierFlyweight.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7bb2891c4c1e91c449203e11641e3a92 3 | timeCreated: 1450937206 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/example2/SoldierFlyweightFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Assets.flyweight_pattern.example2 7 | { 8 | static class SoldierFlyweightFactory 9 | { 10 | private static Dictionary Soldiers = new Dictionary(); 11 | public static int SoldierCount { get; private set; } 12 | 13 | public static ISoldierFlyweight Soldier(WeaponType weaponType) 14 | { 15 | if (!Soldiers.ContainsKey(weaponType)) 16 | { 17 | switch (weaponType) 18 | { 19 | case WeaponType.Sword: 20 | Soldiers.Add(weaponType, new Knight()); 21 | break; 22 | case WeaponType.Bow: 23 | Soldiers.Add(weaponType, new Archer()); 24 | break; 25 | case WeaponType.Lance: 26 | default: 27 | Soldiers.Add(weaponType, new Calvary()); 28 | break; 29 | } 30 | 31 | SoldierCount++; 32 | } 33 | 34 | return Soldiers[weaponType]; 35 | } 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/example2/SoldierFlyweightFactory.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 304834b5765915d409ea726ce58f9041 3 | timeCreated: 1450937206 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/example2/SoldierGameObject.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using Assets.flyweight_pattern.example2; 4 | 5 | public class SoldierGameObject : MonoBehaviour 6 | { 7 | private ISoldierFlyweight soldier = null; 8 | public int health = 0; 9 | 10 | public void Create(WeaponType weaponType) 11 | { 12 | soldier = SoldierFlyweightFactory.Soldier(weaponType); 13 | gameObject.AddComponent(); 14 | } 15 | 16 | bool mouseOver = false; 17 | void OnMouseOver() 18 | { 19 | mouseOver = true; 20 | 21 | if (soldier != null) 22 | { 23 | if (Input.GetMouseButtonDown(1)) 24 | { 25 | // NOTE: Since health is extrinsic to the SoldierFlyweight 26 | // we need to make any adjustments to it specifically here. 27 | // Unfortunately, this means it is not simple to increase 28 | // the health on ALL SoldierGameObjects on the field. 29 | int addHealth = soldier.Stats.MaxHealth; 30 | soldier.LevelUp(); 31 | addHealth = soldier.Stats.MaxHealth - addHealth; 32 | health += addHealth; 33 | Debug.LogFormat("Leveling up all {0} soldiers to level {1}", soldier.Weapon, soldier.Stats.Level); 34 | } 35 | else if (Input.GetMouseButtonDown(0)) 36 | { 37 | health -= 5; 38 | if (health <= 0) 39 | Destroy(gameObject); 40 | else 41 | { 42 | gameObject.GetComponent().material.color = soldier.GetColor(health); 43 | } 44 | } 45 | } 46 | } 47 | 48 | void OnMouseExit() 49 | { 50 | mouseOver = false; 51 | } 52 | 53 | void OnGUI() 54 | { 55 | if (!mouseOver) 56 | return; 57 | if (soldier == null) 58 | return; 59 | 60 | string soldierInfo = string.Format( 61 | "Weapon: {0}\nLevel: {1}\nAttack: {2}\nDexterity: {3}\nMaxHealth: {4}\nDefense: {5}\nhealth: {6}", 62 | soldier.Weapon, 63 | soldier.Stats.Level, 64 | soldier.Stats.Attack, 65 | soldier.Stats.Dexterity, 66 | soldier.Stats.MaxHealth, 67 | soldier.Stats.Defense, 68 | health 69 | ); 70 | 71 | GUI.Label(new Rect(0, 50, 1000, 1000), soldierInfo); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/example2/SoldierGameObject.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ad3be24e0c6bfe14a8b61319c1bda208 3 | timeCreated: 1450937209 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/example2/SoldierSceneController.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using Assets.flyweight_pattern.example2; 4 | 5 | public class SoldierSceneController : MonoBehaviour 6 | { 7 | // We can create as many soldiers as we want and the max 8 | // flyweight count will be 3. Thus reducing memory overhead 9 | // for handling large amounts of soldiers. 10 | public int numberOfSoldiersToCreate = 99; 11 | public Vector2 minPosition; 12 | public Vector2 maxPosition; 13 | 14 | void Start() 15 | { 16 | int weaponType = 0; 17 | for (int i = 0; i < numberOfSoldiersToCreate; i++) 18 | { 19 | //Make visual representations of the soldiers 20 | GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cube); 21 | go.transform.localScale = new Vector3(0.25f, 0.25f, 0.25f); 22 | SoldierGameObject soldierGameObject = go.AddComponent(); 23 | soldierGameObject.Create((WeaponType)weaponType); 24 | go.name = ((WeaponType)weaponType).ToString(); 25 | int startHealth = SoldierFlyweightFactory.Soldier((WeaponType)weaponType).Stats.MaxHealth; 26 | soldierGameObject.health = startHealth; 27 | 28 | float x = Random.Range(minPosition.x, maxPosition.x); 29 | float y = Random.Range(minPosition.y, maxPosition.y); 30 | 31 | go.transform.position = new Vector3(x, 0.45f * go.transform.localScale.y, y); 32 | 33 | go.GetComponent().material.color = SoldierFlyweightFactory.Soldier((WeaponType)weaponType).GetColor(startHealth); 34 | 35 | weaponType = (weaponType + 1) % 3; 36 | } 37 | 38 | Debug.LogFormat("Created {0} soldiers. Flyweight count: {1}", numberOfSoldiersToCreate, SoldierFlyweightFactory.SoldierCount); 39 | } 40 | 41 | void OnGUI() 42 | { 43 | GUI.Label(new Rect(0, 0, 1000, 1000), "LMB=Damage unit -- RMB=Level up units"); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/example2/SoldierSceneController.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 50731ec3f53178145a94f693a17798dc 3 | timeCreated: 1450937206 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/example2/soldier_flyweight_example.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: afd198de618025f479e5ab9eeeb45835 3 | timeCreated: 1450938708 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/structure.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4cc066805bd63c44eb6aca74b585d516 3 | folderAsset: yes 4 | timeCreated: 1446958626 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/structure/ConcreteFlyweight.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace NG.Flyweight.Structure 3 | { 4 | public class ConcreteFlyweight : FlyweightBase 5 | { 6 | 7 | public override void StatefulOperation(object obj) 8 | { 9 | UnityEngine.Debug.Log("Not implemented - object: " + obj.ToString()); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/structure/ConcreteFlyweight.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: aa671e24d2638044c860531bcd78c104 3 | timeCreated: 1446958626 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/structure/FlyweightBase.cs: -------------------------------------------------------------------------------- 1 | namespace NG.Flyweight.Structure 2 | { 3 | public abstract class FlyweightBase 4 | { 5 | public abstract void StatefulOperation(object obj); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/structure/FlyweightBase.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6413d56f5feee864683a4c7610191b08 3 | timeCreated: 1446958626 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/structure/FlyweightFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | namespace NG.Flyweight.Structure 3 | { 4 | public class FlyweightFactory 5 | { 6 | private Hashtable _flyweights = new Hashtable(); 7 | 8 | public FlyweightBase GetFlyweight(string key) 9 | { 10 | if (_flyweights.Contains(key)) 11 | { 12 | return _flyweights[key] as FlyweightBase; 13 | } 14 | else 15 | { 16 | ConcreteFlyweight newFlyweight = new ConcreteFlyweight(); 17 | 18 | // Set flyweight's properties here. 19 | 20 | _flyweights.Add(key, newFlyweight); 21 | return newFlyweight; 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/structure/FlyweightFactory.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ee602065d4cb1194a9ab5247cd050cae 3 | timeCreated: 1446958628 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/structure/UnsharedFlyweight.cs: -------------------------------------------------------------------------------- 1 | namespace NG.Flyweight.Structure 2 | { 3 | public class UnsharedFlyweight : FlyweightBase 4 | { 5 | private object _state; 6 | 7 | public override void StatefulOperation(object obj) 8 | { 9 | _state = obj; 10 | UnityEngine.Debug.Log("Unshared flyweight StatefulOperation: " + _state.ToString()); 11 | } 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /Assets/flyweight pattern/structure/UnsharedFlyweight.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0229a7f33fa5e7d4496cd49057a9987c 3 | timeCreated: 1446958626 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/observer.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c6178b365fcdf5e45a41d6f679ca2325 3 | folderAsset: yes 4 | timeCreated: 1451534602 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/observer/ObserverStructure.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Assets.observer.structure 7 | { 8 | interface IObserver 9 | { 10 | void Update(); 11 | } 12 | 13 | abstract class Subject 14 | { 15 | private List _observers = new List(); 16 | 17 | public void Attach(IObserver observer) 18 | { 19 | _observers.Add(observer); 20 | } 21 | 22 | public void Detach(IObserver observer) 23 | { 24 | _observers.Remove(observer); 25 | } 26 | 27 | public void Notify() 28 | { 29 | for (int i = 0; i < _observers.Count; i++) 30 | { 31 | _observers[i].Update(); 32 | } 33 | } 34 | } 35 | 36 | class ConcreteSubject : Subject 37 | { 38 | private string _subjectState; 39 | 40 | // Usually want to run notify from this accessor's setter. 41 | public string SubjectState 42 | { 43 | get { return _subjectState; } 44 | set { _subjectState = value; } 45 | } 46 | } 47 | 48 | class ConcreteObserver : IObserver 49 | { 50 | private string _name; 51 | private string _observerState; 52 | private ConcreteSubject _subject; 53 | 54 | public ConcreteObserver(ConcreteSubject subject, string name) 55 | { 56 | _subject = subject; 57 | _name = name; 58 | } 59 | 60 | public void Update() 61 | { 62 | _observerState = _subject.SubjectState; 63 | Console.WriteLine("Observer {0}'s new state is {1}", 64 | _name, _observerState); 65 | } 66 | 67 | public ConcreteSubject Subject 68 | { 69 | get { return _subject; } 70 | set { _subject = value; } 71 | } 72 | } 73 | 74 | class MainApp 75 | { 76 | public void Run() 77 | { 78 | ConcreteSubject s = new ConcreteSubject(); 79 | s.Attach(new ConcreteObserver(s, "X")); 80 | s.Attach(new ConcreteObserver(s, "Y")); 81 | s.Attach(new ConcreteObserver(s, "Z")); 82 | 83 | //Change the subject and notify observers 84 | s.SubjectState = "ABC"; 85 | s.Notify(); 86 | 87 | Console.Read(); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Assets/observer/ObserverStructure.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b3ad3e48259febf4e955b2e9a4d7f85c 3 | timeCreated: 1451534602 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/singleton.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 622f8bf5630fd2c4990b3df7ecbe3b6d 3 | folderAsset: yes 4 | timeCreated: 1480896835 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/singleton/example.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b5a9101b0e0558b48b0a06b3aa921396 3 | folderAsset: yes 4 | timeCreated: 1480897503 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/singleton/example/GameManagerExample.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Naphier/unity-design-patterns/ab864774b0b75b2ecad1ef8f946ba985d02ea7dd/Assets/singleton/example/GameManagerExample.unity -------------------------------------------------------------------------------- /Assets/singleton/example/GameManagerExample.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 914d659e47373f544a61301648ea1bb9 3 | timeCreated: 1480897590 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/singleton/example/Prefabs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: eead199cd39844049850766fd3be83f8 3 | folderAsset: yes 4 | timeCreated: 1480897539 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/singleton/example/Prefabs/GameManager.prefab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Naphier/unity-design-patterns/ab864774b0b75b2ecad1ef8f946ba985d02ea7dd/Assets/singleton/example/Prefabs/GameManager.prefab -------------------------------------------------------------------------------- /Assets/singleton/example/Prefabs/GameManager.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e1f92006dfb187c45a02b0560e61ed22 3 | timeCreated: 1480897756 4 | licenseType: Free 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/singleton/example/Prefabs/ManagerSpawner.prefab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Naphier/unity-design-patterns/ab864774b0b75b2ecad1ef8f946ba985d02ea7dd/Assets/singleton/example/Prefabs/ManagerSpawner.prefab -------------------------------------------------------------------------------- /Assets/singleton/example/Prefabs/ManagerSpawner.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 203a76eff06e7d247a33c249c2035f25 3 | timeCreated: 1480900564 4 | licenseType: Free 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/singleton/example/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 93b299ccec1ea1449ba005c7e547b495 3 | folderAsset: yes 4 | timeCreated: 1480897546 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/singleton/example/Scripts/GameManager.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEngine.UI; 5 | 6 | namespace NG.Patterns.Structure.Singleton 7 | { 8 | //GameManagers, InputManagers and anything else you want to only exist once make great Singletons. 9 | public class GameManager : Singleton 10 | { 11 | public Text DebugText; 12 | 13 | private string _debugMessage = "GameManager Is Running"; 14 | 15 | private int _numElipses = 0; 16 | private string _elipses = "."; 17 | 18 | public void Start() 19 | { 20 | //Begin the GameLoop Coroutine on start 21 | StartCoroutine(GameLoop()); 22 | } 23 | 24 | //This is used to represent the Update() of the game. 25 | //Using a Coroutine in Unity is useful for GameLoops as it gives you more agency over the Game. 26 | //You can Start and Stop it as needed, and when the Coroutine Exits and Starts again, it begins from where it left off. 27 | //Rather than starting all over from the beginning. I frequently use nested Coroutines for game Update States. 28 | //i.e. RoundStarting(), RoundRunning(), RoundEnding() 29 | IEnumerator GameLoop() 30 | { 31 | while(true) 32 | { 33 | 34 | DebugText.text = _debugMessage + GetElipses(); 35 | yield return new WaitForSeconds(0.5f); 36 | } 37 | } 38 | 39 | private string GetElipses() 40 | { 41 | string text = ""; 42 | for (int i = 0; i < _numElipses; i++) 43 | { 44 | text += _elipses; 45 | } 46 | _numElipses++; 47 | if (_numElipses > 3) 48 | _numElipses = 0; 49 | return text; 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /Assets/singleton/example/Scripts/GameManager.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 703e290f8b1c1704a920230427c3def5 3 | timeCreated: 1480897644 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/singleton/example/Scripts/ManagerSpawner.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEngine.UI; 5 | 6 | public class ManagerSpawner : MonoBehaviour 7 | { 8 | public GameObject Manager; 9 | public Text DebugText; 10 | 11 | // Update is called once per frame 12 | void Update () 13 | { 14 | if(Input.GetKeyDown(KeyCode.Space)) 15 | { 16 | Instantiate(Manager); 17 | DebugText.text = "If you press space again, a warning will tell you the new instance failed, because it is a singleton.\n\nThis is great for scripts like Managers, that you only want to exist once, and to easily be accessed by other scripts."; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Assets/singleton/example/Scripts/ManagerSpawner.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d556380578dcf524e8ccf9cebb1ddcc9 3 | timeCreated: 1480898788 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/singleton/structure.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ff97efd039b740c41a45c860644ce5a1 3 | folderAsset: yes 4 | timeCreated: 1480897493 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/singleton/structure/Singleton.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace NG.Patterns.Structure.Singleton 4 | { 5 | public class Singleton : MonoBehaviour where T : Singleton 6 | { 7 | //The instance of the class type that has been specified 8 | private static T _instance; 9 | 10 | // Lock object, will prevent other threads from modifying _instance once one thread begins setting it 11 | private static object _instLock = new object(); 12 | 13 | // Boolean variable to prevent accessing a singleton in the process of being disposed/destroyed 14 | bool _disposing = false; 15 | 16 | //The public accessor for other classes to access the Singleton. Simply by typing the .Instance 17 | public static T Instance 18 | { 19 | get 20 | { 21 | if (_instance == null) 22 | { 23 | //If there isn't find the instance and set it. 24 | _instance = FindObjectOfType(); 25 | } 26 | 27 | if (!_disposing) 28 | return _instance; 29 | else 30 | return null; 31 | } 32 | 33 | set 34 | { 35 | lock(_instLock) // Ensures thread safety 36 | { 37 | if (_instance == null) // Only set it if it's null 38 | _instance = value; 39 | else if (_instance == this) // Only the current Instance can modify the _instance variable, for example, to set it null 40 | _instance = value; 41 | } 42 | } 43 | } 44 | 45 | //Making this a virtual function let's the programmer know that there is a function they must override 46 | //It allows the programmer to make the decision to override the call completely, or to include the base call with its new functionality. 47 | //In C# this is done by calling base.Awake() in the new class 48 | public virtual void Awake() 49 | { 50 | if (Instance == null) 51 | Instance = this; 52 | else if (Instance != this) //Check to make sure there isn't already an instance of this class. 53 | { 54 | //If there is already an instance of this class, destroy the object we just created. 55 | Debug.LogWarning("Attempted to spawn more then one singleton object. destroying new instance of " + gameObject.ToString() + "\nIf you would like more than one instance, ensure that the class you have written does not Inherit from a Singleton class."); 56 | Dispose(); 57 | } 58 | } 59 | 60 | // Proper cleanup of a Singleton instance includes nullifying any references to it in order to allow Garbage Collection 61 | private virtual void Dispose() 62 | { 63 | _disposing = true; 64 | Instance = null; 65 | 66 | Destroy(gameObject); 67 | } 68 | 69 | // In case it is destroyed in an improper manner 70 | public virtual void OnDestroy() 71 | { 72 | if (!_disposing) 73 | _disposing = true; 74 | 75 | if (Instance != null) 76 | Instance = null; 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Assets/singleton/structure/Singleton.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 94bee239c3f2a6b45ba9bc46e75deeeb 3 | timeCreated: 1480897137 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/strategy pattern.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7fdc461bd99eed44788eeff6eacb7796 3 | folderAsset: yes 4 | timeCreated: 1451371666 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/strategy pattern/StrategyPatternStructure.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace StrategyPattern.structure 4 | { 5 | abstract class Strategy 6 | { 7 | public abstract void AlgorithmInterface(); 8 | } 9 | 10 | class ConcreteStrategyA : Strategy 11 | { 12 | public override void AlgorithmInterface() 13 | { 14 | Console.WriteLine("ConcreteStrategyA.AlgorithmInterface()"); 15 | } 16 | } 17 | 18 | class ConcreteStrategyB : Strategy 19 | { 20 | public override void AlgorithmInterface() 21 | { 22 | Console.WriteLine("ConcreteStrategyB.AlgorithmInterface()"); 23 | } 24 | } 25 | 26 | class ConcreteStrategyC : Strategy 27 | { 28 | public override void AlgorithmInterface() 29 | { 30 | Console.WriteLine("ConcreteStrategyC.AlgorithmInterface()"); 31 | } 32 | } 33 | 34 | class Context 35 | { 36 | private Strategy _strategy; 37 | 38 | public Context(Strategy strategy) 39 | { 40 | this._strategy = strategy; 41 | } 42 | 43 | public void ContextInterface() 44 | { 45 | _strategy.AlgorithmInterface(); 46 | } 47 | } 48 | 49 | class MainApp 50 | { 51 | static void Main() 52 | { 53 | Context context; 54 | context = new Context(new ConcreteStrategyA()); 55 | context.ContextInterface(); 56 | 57 | context = new Context(new ConcreteStrategyB()); 58 | context.ContextInterface(); 59 | 60 | context = new Context(new ConcreteStrategyC()); 61 | context.ContextInterface(); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Assets/strategy pattern/StrategyPatternStructure.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fe675663c2a79714794d9d7aa85a0e64 3 | timeCreated: 1451371669 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/strategy pattern/example_enemy_behavior.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 972f1b8cee854eb4c8fe8a7aa2bd010d 3 | folderAsset: yes 4 | timeCreated: 1451371666 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/strategy pattern/example_enemy_behavior/EnemyBehaviour.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a5bb36eb328daeb4688945825a5657be 3 | timeCreated: 1451371666 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/strategy pattern/example_enemy_behavior/StrategyExampleMainApp.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using Assets.strategy_pattern.example; 5 | public class StrategyExampleMainApp : MonoBehaviour 6 | { 7 | List enemyBehaviors = new List(); 8 | public GameObject spawnPoint; 9 | public float minX, maxX; 10 | void Start() 11 | { 12 | StartCoroutine(MakeEnemies()); 13 | } 14 | 15 | IEnumerator MakeEnemies() 16 | { 17 | for (int i = 0; i < 10; i++) 18 | { 19 | GameObject enemy = GameObject.CreatePrimitive(PrimitiveType.Cube); 20 | 21 | 22 | enemy.transform.position = spawnPoint.transform.position; 23 | 24 | EnemyBehaviorContext context; 25 | IEnemyBehaviour enemyBehavior; 26 | if (i < 5) 27 | { 28 | enemy.name = "Drone"; 29 | enemyBehavior = new DroneBehavior(Time.time, enemy, minX, maxX); 30 | enemy.GetComponent().material.color = Color.blue; 31 | } 32 | else 33 | { 34 | enemy.name = "Fighter"; 35 | enemyBehavior = new FighterBehavior(Time.time, enemy, minX, maxX); 36 | enemy.GetComponent().material.color = Color.red; 37 | } 38 | 39 | context = new EnemyBehaviorContext(enemyBehavior); 40 | enemyBehaviors.Add(context); 41 | 42 | yield return new WaitForSeconds(1f); 43 | } 44 | } 45 | 46 | 47 | void Update() 48 | { 49 | for (int i = 0; i < enemyBehaviors.Count; i++) 50 | { 51 | enemyBehaviors[i].Act(); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Assets/strategy pattern/example_enemy_behavior/StrategyExampleMainApp.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9e7dc4d695520544c894c4a228cd8ff3 3 | timeCreated: 1451371666 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/strategy pattern/example_enemy_behavior/strategy_pattern_example.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 796cccc36eec3c64098655fd827d1662 3 | timeCreated: 1451372982 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/strategy pattern/example_output_string.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0444f236741fb2342a89b01d875844c3 3 | folderAsset: yes 4 | timeCreated: 1451417127 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/strategy pattern/example_output_string/OutputStrategy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Assets.strategy_pattern.example_output_string 7 | { 8 | public interface IOutputStrategy 9 | { 10 | string Output(string input); 11 | } 12 | 13 | public class CSVOutput : IOutputStrategy 14 | { 15 | char delimiter = ' '; 16 | public CSVOutput(char delimiter) 17 | { 18 | this.delimiter = delimiter; 19 | } 20 | 21 | public string Output(string input) 22 | { 23 | input = input.Replace(delimiter, ','); 24 | return input; 25 | } 26 | } 27 | 28 | public class EncryptedOutput : IOutputStrategy 29 | { 30 | public string Output(string input) 31 | { 32 | char[] array = input.ToCharArray(); 33 | for (int i = 0; i < array.Length; i++) 34 | { 35 | int number = (int)array[i]; 36 | 37 | if (number >= 'a' && number <= 'z') 38 | { 39 | if (number > 'm') 40 | { 41 | number -= 13; 42 | } 43 | else 44 | { 45 | number += 13; 46 | } 47 | } 48 | else if (number >= 'A' && number <= 'Z') 49 | { 50 | if (number > 'M') 51 | { 52 | number -= 13; 53 | } 54 | else 55 | { 56 | number += 13; 57 | } 58 | } 59 | array[i] = (char)number; 60 | } 61 | return new string(array); 62 | } 63 | } 64 | 65 | public class OutputContext 66 | { 67 | IOutputStrategy outputStrategy; 68 | public OutputContext(IOutputStrategy outputStrategy) 69 | { 70 | this.outputStrategy = outputStrategy; 71 | } 72 | 73 | public string GetOutput(string input) 74 | { 75 | return outputStrategy.Output(input); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Assets/strategy pattern/example_output_string/OutputStrategy.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fc5028e2560de9b478343c37246cb820 3 | timeCreated: 1451417127 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/strategy pattern/example_output_string/OutputStrategyController.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using Assets.strategy_pattern.example_output_string; 4 | 5 | public class OutputStrategyController : MonoBehaviour 6 | { 7 | public string input = "This is some arbitrary input string"; 8 | 9 | void Start() 10 | { 11 | OutputContext context = new OutputContext(new CSVOutput(' ')); 12 | Debug.Log("This is the CSV output:\n" + context.GetOutput(input)); 13 | 14 | //Easily change the context! 15 | context = new OutputContext(new EncryptedOutput()); 16 | Debug.Log("This is the encrypted output:\n" + context.GetOutput(input)); 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Assets/strategy pattern/example_output_string/OutputStrategyController.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a0795198b0d96d249a54f2ab89be1f21 3 | timeCreated: 1451417127 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/strategy pattern/example_output_string/output_strategy.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 374cec145d67e384c838b3656441f22b 3 | timeCreated: 1451417185 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/strategy pattern/readme.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fdcd17c6d9f97104fab5830e3d25c6ed 3 | timeCreated: 1451417127 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!11 &1 4 | AudioManager: 5 | m_ObjectHideFlags: 0 6 | m_Volume: 1 7 | Rolloff Scale: 1 8 | Doppler Factor: 1 9 | Default Speaker Mode: 2 10 | m_SampleRate: 0 11 | m_DSPBufferSize: 0 12 | m_VirtualVoiceCount: 512 13 | m_RealVoiceCount: 32 14 | m_SpatializerPlugin: 15 | m_DisableAudio: 0 16 | -------------------------------------------------------------------------------- /ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!236 &1 4 | ClusterInputManager: 5 | m_ObjectHideFlags: 0 6 | m_Inputs: [] 7 | -------------------------------------------------------------------------------- /ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!55 &1 4 | PhysicsManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Gravity: {x: 0, y: -9.81, z: 0} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_BounceThreshold: 2 10 | m_SleepThreshold: 0.005 11 | m_DefaultContactOffset: 0.01 12 | m_SolverIterationCount: 6 13 | m_QueriesHitTriggers: 1 14 | m_EnableAdaptiveForce: 0 15 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 16 | -------------------------------------------------------------------------------- /ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1045 &1 4 | EditorBuildSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Scenes: 8 | - enabled: 1 9 | path: Assets/scene1.unity 10 | - enabled: 1 11 | path: Assets/scene2.unity 12 | -------------------------------------------------------------------------------- /ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!159 &1 4 | EditorSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 3 7 | m_ExternalVersionControlSupport: Hidden Meta Files 8 | m_SerializationMode: 2 9 | m_WebSecurityEmulationEnabled: 0 10 | m_WebSecurityEmulationHostUrl: http://www.mydomain.com/mygame.unity3d 11 | m_DefaultBehaviorMode: 0 12 | m_SpritePackerMode: 2 13 | m_SpritePackerPaddingPower: 1 14 | m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd 15 | m_ProjectGenerationRootNamespace: 16 | -------------------------------------------------------------------------------- /ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Naphier/unity-design-patterns/ab864774b0b75b2ecad1ef8f946ba985d02ea7dd/ProjectSettings/GraphicsSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!126 &1 4 | NavMeshAreas: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | areas: 8 | - name: Walkable 9 | cost: 1 10 | - name: Not Walkable 11 | cost: 1 12 | - name: Jump 13 | cost: 2 14 | - name: 15 | cost: 1 16 | - name: 17 | cost: 1 18 | - name: 19 | cost: 1 20 | - name: 21 | cost: 1 22 | - name: 23 | cost: 1 24 | - name: 25 | cost: 1 26 | - name: 27 | cost: 1 28 | - name: 29 | cost: 1 30 | - name: 31 | cost: 1 32 | - name: 33 | cost: 1 34 | - name: 35 | cost: 1 36 | - name: 37 | cost: 1 38 | - name: 39 | cost: 1 40 | - name: 41 | cost: 1 42 | - name: 43 | cost: 1 44 | - name: 45 | cost: 1 46 | - name: 47 | cost: 1 48 | - name: 49 | cost: 1 50 | - name: 51 | cost: 1 52 | - name: 53 | cost: 1 54 | - name: 55 | cost: 1 56 | - name: 57 | cost: 1 58 | - name: 59 | cost: 1 60 | - name: 61 | cost: 1 62 | - name: 63 | cost: 1 64 | - name: 65 | cost: 1 66 | - name: 67 | cost: 1 68 | - name: 69 | cost: 1 70 | - name: 71 | cost: 1 72 | -------------------------------------------------------------------------------- /ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!149 &1 4 | NetworkManager: 5 | m_ObjectHideFlags: 0 6 | m_DebugLevel: 0 7 | m_Sendrate: 15 8 | m_AssetToPrefab: {} 9 | -------------------------------------------------------------------------------- /ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!19 &1 4 | Physics2DSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Gravity: {x: 0, y: -9.81} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_VelocityIterations: 8 10 | m_PositionIterations: 3 11 | m_VelocityThreshold: 1 12 | m_MaxLinearCorrection: 0.2 13 | m_MaxAngularCorrection: 8 14 | m_MaxTranslationSpeed: 100 15 | m_MaxRotationSpeed: 360 16 | m_MinPenetrationForPenalty: 0.01 17 | m_BaumgarteScale: 0.2 18 | m_BaumgarteTimeOfImpactScale: 0.75 19 | m_TimeToSleep: 0.5 20 | m_LinearSleepTolerance: 0.01 21 | m_AngularSleepTolerance: 2 22 | m_QueriesHitTriggers: 1 23 | m_QueriesStartInColliders: 1 24 | m_ChangeStopsCallbacks: 0 25 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 26 | -------------------------------------------------------------------------------- /ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 5.5.0f3 2 | -------------------------------------------------------------------------------- /ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!47 &1 4 | QualitySettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 5 7 | m_CurrentQuality: 5 8 | m_QualitySettings: 9 | - serializedVersion: 2 10 | name: Fastest 11 | pixelLightCount: 0 12 | shadows: 0 13 | shadowResolution: 0 14 | shadowProjection: 1 15 | shadowCascades: 1 16 | shadowDistance: 15 17 | shadowNearPlaneOffset: 2 18 | shadowCascade2Split: 0.33333334 19 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 20 | blendWeights: 1 21 | textureQuality: 1 22 | anisotropicTextures: 0 23 | antiAliasing: 0 24 | softParticles: 0 25 | softVegetation: 0 26 | realtimeReflectionProbes: 0 27 | billboardsFaceCameraPosition: 0 28 | vSyncCount: 0 29 | lodBias: 0.3 30 | maximumLODLevel: 0 31 | particleRaycastBudget: 4 32 | asyncUploadTimeSlice: 2 33 | asyncUploadBufferSize: 4 34 | excludedTargetPlatforms: [] 35 | - serializedVersion: 2 36 | name: Fast 37 | pixelLightCount: 0 38 | shadows: 0 39 | shadowResolution: 0 40 | shadowProjection: 1 41 | shadowCascades: 1 42 | shadowDistance: 20 43 | shadowNearPlaneOffset: 2 44 | shadowCascade2Split: 0.33333334 45 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 46 | blendWeights: 2 47 | textureQuality: 0 48 | anisotropicTextures: 0 49 | antiAliasing: 0 50 | softParticles: 0 51 | softVegetation: 0 52 | realtimeReflectionProbes: 0 53 | billboardsFaceCameraPosition: 0 54 | vSyncCount: 0 55 | lodBias: 0.4 56 | maximumLODLevel: 0 57 | particleRaycastBudget: 16 58 | asyncUploadTimeSlice: 2 59 | asyncUploadBufferSize: 4 60 | excludedTargetPlatforms: [] 61 | - serializedVersion: 2 62 | name: Simple 63 | pixelLightCount: 1 64 | shadows: 1 65 | shadowResolution: 0 66 | shadowProjection: 1 67 | shadowCascades: 1 68 | shadowDistance: 20 69 | shadowNearPlaneOffset: 2 70 | shadowCascade2Split: 0.33333334 71 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 72 | blendWeights: 2 73 | textureQuality: 0 74 | anisotropicTextures: 1 75 | antiAliasing: 0 76 | softParticles: 0 77 | softVegetation: 0 78 | realtimeReflectionProbes: 0 79 | billboardsFaceCameraPosition: 0 80 | vSyncCount: 0 81 | lodBias: 0.7 82 | maximumLODLevel: 0 83 | particleRaycastBudget: 64 84 | asyncUploadTimeSlice: 2 85 | asyncUploadBufferSize: 4 86 | excludedTargetPlatforms: [] 87 | - serializedVersion: 2 88 | name: Good 89 | pixelLightCount: 2 90 | shadows: 2 91 | shadowResolution: 1 92 | shadowProjection: 1 93 | shadowCascades: 2 94 | shadowDistance: 40 95 | shadowNearPlaneOffset: 2 96 | shadowCascade2Split: 0.33333334 97 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 98 | blendWeights: 2 99 | textureQuality: 0 100 | anisotropicTextures: 1 101 | antiAliasing: 0 102 | softParticles: 0 103 | softVegetation: 1 104 | realtimeReflectionProbes: 1 105 | billboardsFaceCameraPosition: 1 106 | vSyncCount: 1 107 | lodBias: 1 108 | maximumLODLevel: 0 109 | particleRaycastBudget: 256 110 | asyncUploadTimeSlice: 2 111 | asyncUploadBufferSize: 4 112 | excludedTargetPlatforms: [] 113 | - serializedVersion: 2 114 | name: Beautiful 115 | pixelLightCount: 3 116 | shadows: 2 117 | shadowResolution: 2 118 | shadowProjection: 1 119 | shadowCascades: 2 120 | shadowDistance: 70 121 | shadowNearPlaneOffset: 2 122 | shadowCascade2Split: 0.33333334 123 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 124 | blendWeights: 4 125 | textureQuality: 0 126 | anisotropicTextures: 2 127 | antiAliasing: 2 128 | softParticles: 1 129 | softVegetation: 1 130 | realtimeReflectionProbes: 1 131 | billboardsFaceCameraPosition: 1 132 | vSyncCount: 1 133 | lodBias: 1.5 134 | maximumLODLevel: 0 135 | particleRaycastBudget: 1024 136 | asyncUploadTimeSlice: 2 137 | asyncUploadBufferSize: 4 138 | excludedTargetPlatforms: [] 139 | - serializedVersion: 2 140 | name: Fantastic 141 | pixelLightCount: 4 142 | shadows: 2 143 | shadowResolution: 2 144 | shadowProjection: 1 145 | shadowCascades: 4 146 | shadowDistance: 150 147 | shadowNearPlaneOffset: 2 148 | shadowCascade2Split: 0.33333334 149 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 150 | blendWeights: 4 151 | textureQuality: 0 152 | anisotropicTextures: 2 153 | antiAliasing: 2 154 | softParticles: 1 155 | softVegetation: 1 156 | realtimeReflectionProbes: 1 157 | billboardsFaceCameraPosition: 1 158 | vSyncCount: 1 159 | lodBias: 2 160 | maximumLODLevel: 0 161 | particleRaycastBudget: 4096 162 | asyncUploadTimeSlice: 2 163 | asyncUploadBufferSize: 4 164 | excludedTargetPlatforms: [] 165 | m_PerPlatformDefaultQuality: 166 | Android: 2 167 | BlackBerry: 2 168 | GLES Emulation: 5 169 | PS3: 5 170 | PS4: 5 171 | PSM: 5 172 | PSP2: 5 173 | Samsung TV: 2 174 | Standalone: 5 175 | Tizen: 2 176 | WP8: 5 177 | Web: 5 178 | WebGL: 3 179 | Windows Store Apps: 5 180 | XBOX360: 5 181 | XboxOne: 5 182 | iPhone: 2 183 | -------------------------------------------------------------------------------- /ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!78 &1 4 | TagManager: 5 | serializedVersion: 2 6 | tags: 7 | - bullet 8 | layers: 9 | - Default 10 | - TransparentFX 11 | - Ignore Raycast 12 | - 13 | - Water 14 | - UI 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 | m_SortingLayers: 42 | - name: Default 43 | uniqueID: 0 44 | locked: 0 45 | -------------------------------------------------------------------------------- /ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!5 &1 4 | TimeManager: 5 | m_ObjectHideFlags: 0 6 | Fixed Timestep: 0.02 7 | Maximum Allowed Timestep: 0.33333334 8 | m_TimeScale: 1 9 | -------------------------------------------------------------------------------- /ProjectSettings/UnityAdsSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!292 &1 4 | UnityAdsSettings: 5 | m_ObjectHideFlags: 0 6 | m_Enabled: 0 7 | m_InitializeOnStartup: 1 8 | m_TestMode: 0 9 | m_EnabledPlatforms: 4294967295 10 | m_IosGameId: 11 | m_AndroidGameId: 12 | -------------------------------------------------------------------------------- /ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!310 &1 4 | UnityConnectSettings: 5 | m_ObjectHideFlags: 0 6 | UnityPurchasingSettings: 7 | m_Enabled: 0 8 | m_TestMode: 0 9 | UnityAnalyticsSettings: 10 | m_Enabled: 0 11 | m_InitializeOnStartup: 1 12 | m_TestMode: 0 13 | m_TestEventUrl: 14 | m_TestConfigUrl: 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Welcome to Unity Design Patterns 2 | ### Examples of programming design patterns in Unity3D C# 3 | 4 | Thanks to [Robert Nystrom's Game Programming Patterns][1] 5 | and the examples found on [Rivello Multimedia's website][2]. 6 | Each pattern is contained in a separate folder. Inside these are a folder ("structure") to show what classes are used in the pattern's structure and a folder ("example") showing a real-world example of using the pattern in Unity3D along with a scene showing it in action. 7 | 8 | As these are accomplished I plan to do a blog article on each. Once the articles are done they will be referenced in each pattern's readme.md. 9 | 10 | Details on each pattern can be found in the Readme.md file in each pattern's folder. 11 | 12 | Patterns done: 13 | 14 | - [Command Pattern] 15 | - [Abstract Factory Pattern] 16 | - [Flyweight Pattern] 17 | - [Builder Pattern] 18 | - [Factory Method Pattern] 19 | - [Decorator Pattern] 20 | - [Strategy Pattern] 21 | 22 | ### Contributors Welcome 23 | Please check out [contributors.md] if you'd like to help out with this project. It will take me forever to do all of these on my own and I'd love to have some help! 24 | 25 | Patterns to do: 26 | 27 | - Prototype 28 | - Singleton (Monobehaviour derived and non-derived) 29 | - Adapter 30 | - Bridge 31 | - Composite 32 | - Facade 33 | - Proxy 34 | - Chain of Responsibility 35 | - Interpreter 36 | - Iterator 37 | - Mediator 38 | - Memento 39 | - Observer 40 | - State 41 | - Strategy 42 | - Template Method 43 | - Visitor 44 | 45 | 46 | 47 | [1]: http://gameprogrammingpatterns.com/ 48 | [2]: http://www.rivellomultimediaconsulting.com/unity3d-csharp-design-patterns/ 49 | [command pattern]:https://github.com/Naphier/unity-design-patterns/tree/master/Assets/command%20pattern 50 | [abstract factory pattern]:https://github.com/Naphier/unity-design-patterns/tree/master/Assets/abstract%20factory 51 | [flyweight pattern]:https://github.com/Naphier/unity-design-patterns/tree/master/Assets/flyweight%20pattern 52 | [contributors.md]:https://github.com/Naphier/unity-design-patterns/blob/master/contributors.md 53 | [builder pattern]:https://github.com/Naphier/unity-design-patterns/tree/master/Assets/builder%20pattern 54 | [factory method pattern]:https://github.com/Naphier/unity-design-patterns/tree/master/Assets/factory%20method%20pattern 55 | [decorator pattern]:https://github.com/Naphier/unity-design-patterns/tree/master/Assets/decorator 56 | [strategy pattern]:https://github.com/Naphier/unity-design-patterns/tree/master/Assets/strategy%20pattern 57 | -------------------------------------------------------------------------------- /contributors.md: -------------------------------------------------------------------------------- 1 | # Contibutors Welcome! 2 | 3 | ## Guidelines 4 | 5 | ### Table of Contents 6 | - [How to Contribute](#how-to-contribute) 7 | - [Repository Structure](#repository-structure) 8 | - [Coding Guidelines](#coding-guidelines) 9 | - [Updating your Pull Request](#updating-your-pull-request) 10 | 11 | #### How to Contribute 12 | Contributing is easy! Just fork this repository to your own GitHub account, make the changes you want then submit a pull request to the **development** branch. All forks should merge into **development** as this will provide us with the opportunity to make test them out before merging into the master branch for public consumption. If a **development** branch does not exist when you are ready to make your pull request just shoot me a line and I'll make one (contact info is in my profile). 13 | 14 | Changes to folder structure or .gitignore should be discussed in an **issue** before attempting them. 15 | 16 | Your Unity project should be set to have visible meta files (Edit -> Project Settings -> Editor) and force text. 17 | 18 | Make sure to include a readme.md for each pattern and update them when you update the pattern if an explanation needs to be conveyed to the public. 19 | 20 | 21 | #### Repository Structure 22 | The folder structure should remain quite simple: 23 | - Each pattern should be in its own folder under Assets. 24 | - In these folders there should be a folder "example" and a folder "structure". "Structure" will just illustrate the patterns structure and is only good for reference. "Example" will actually contain the class files for a real-world example that will run in an example scene also contained in that folder. 25 | - assets/pattern name/structure 26 | - assets/pattern name/example 27 | - Classes for each structure and each example should be wrapped in their own namespace so that they have a very low chance of interfering with another person's project should they import the classes. 28 | 29 | #### Coding Guidelines 30 | - Each example and each structure should be contained in their own namespace. 31 | - Each file should normally contain one class unless the included classes are directly related and very small (like abstracts classes in a pattern structure). 32 | - Use comments liberally, but if something is clear then don't comment it (i.e. don't include comments like Unity's default "//Use this for initialization" where 99% of the people already should understand what the Start() method does). 33 | - Format your code nicely! I mainly prefer [MSDN's guidelines][1], but not their overusage of **var**. Basically if it is clean I will be OK with it. Use camel-case, capitilize the first letter of classes, namespaces, methods, etc. Don't capitalize the first letter of variables. Private variables should be indicated by a leading underscore (i.e. _iAmPrivate). Method names should be descriptive. I could go on, but hopefully you all get the point. 34 | 35 | 36 | #### Updating your Pull Request 37 | 38 | Sometimes, you will asked you to edit your Pull Request before it is included. This is normally due to spelling errors or because your request didn't match these guidelines. 39 | 40 | [Here](https://github.com/RichardLitt/docs/blob/master/amending-a-commit-guide.md) is a write up on how to change a Pull Request, and the different ways you can do that. 41 | 42 | 43 | [1]:https://msdn.microsoft.com/en-us/library/ff926074.aspx?f=255&MSPPError=-2147217396 44 | --------------------------------------------------------------------------------