├── .gitignore ├── GetComponentAttribute.cs ├── GetComponentFrom.cs ├── GetComponentInjection.cs ├── InjectEvent.cs ├── MonoHolder.cs └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/unity 2 | # Edit at https://www.gitignore.io/?templates=unity 3 | 4 | ### Unity ### 5 | [Ll]ibrary/ 6 | [Tt]emp/ 7 | [Oo]bj/ 8 | [Bb]uild/ 9 | [Bb]uilds/ 10 | [Ll]ogs/ 11 | [Aa]ssets/AssetStoreTools* 12 | 13 | # Visual Studio cache directory 14 | .vs/ 15 | 16 | # Gradle cache directory 17 | .gradle/ 18 | 19 | # Autogenerated VS/MD/Consulo solution and project files 20 | ExportedObj/ 21 | .consulo/ 22 | *.csproj 23 | *.unityproj 24 | *.sln 25 | *.suo 26 | *.tmp 27 | *.user 28 | *.userprefs 29 | *.pidb 30 | *.booproj 31 | *.svd 32 | *.pdb 33 | *.opendb 34 | *.VC.db 35 | *.meta 36 | 37 | # Unity3D generated meta files 38 | *.pidb.meta 39 | *.pdb.meta 40 | 41 | # Unity3D generated file on crash reports 42 | sysinfo.txt 43 | 44 | # Builds 45 | *.apk 46 | 47 | # Crashlytics generated file 48 | Assets/StreamingAssets/crashlytics-build.properties 49 | 50 | 51 | # End of https://www.gitignore.io/api/unity -------------------------------------------------------------------------------- /GetComponentAttribute.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using System; 5 | 6 | 7 | [AttributeUsage(AttributeTargets.Field)] 8 | public class GetComponentAttribute : Attribute 9 | { 10 | public GetComponentFrom ComponentAddress { get; } 11 | public string TargetName { get; } 12 | 13 | public GetComponentAttribute(GetComponentFrom address = GetComponentFrom.Self, string objectName = "") 14 | { 15 | ComponentAddress = address; 16 | TargetName = objectName; 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /GetComponentFrom.cs: -------------------------------------------------------------------------------- 1 | public enum GetComponentFrom 2 | { 3 | Self, 4 | SceneObject, 5 | TargetGameObject 6 | } -------------------------------------------------------------------------------- /GetComponentInjection.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System; 3 | using UnityEngine; 4 | public static class GetComponentInjection 5 | { 6 | public static InjectEvent SingleObjectClassifier; 7 | public static InjectEvent> MultipleObjectClassifier; 8 | 9 | 10 | [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] 11 | static void InjectScriptReferences() 12 | { 13 | SingleObjectClassifier += (attr, field, obj) => 14 | { 15 | switch (attr.ComponentAddress) 16 | { 17 | case GetComponentFrom.Self: 18 | field.SetValue(obj, obj.GetComponent(field.FieldType)); 19 | break; 20 | case GetComponentFrom.SceneObject: 21 | field.SetValue(obj, MonoBehaviour.FindObjectOfType(field.FieldType)); 22 | break; 23 | } 24 | }; 25 | Inject(); 26 | } 27 | 28 | [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] 29 | static void InjectGameObjectReferences() 30 | { 31 | MultipleObjectClassifier += (attr, field, monoHolder) => 32 | { 33 | if (attr.ComponentAddress != GetComponentFrom.TargetGameObject) 34 | return; 35 | GameObject targetObj = GameObject.Find(attr.TargetName); 36 | field.SetValue(monoHolder.t, targetObj.GetComponent(field.GetValue(monoHolder.t).GetType())); 37 | }; 38 | Inject(); 39 | } 40 | 41 | 42 | private static void Inject() 43 | { 44 | MonoBehaviour[] objs = MonoBehaviour.FindObjectsOfType(); 45 | foreach (var obj in objs) 46 | { 47 | Type type = obj.GetType(); 48 | FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); 49 | GetComponentAttribute attr; 50 | foreach (var field in fields) 51 | { 52 | if (field.IsDefined(typeof(GetComponentAttribute), false)) 53 | { 54 | attr = field.GetCustomAttribute(); 55 | SingleObjectClassifier?.Invoke(attr, field, obj); 56 | MultipleObjectClassifier?.Invoke(attr, field, new MonoHolder(obj, objs)); 57 | } 58 | } 59 | } 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /InjectEvent.cs: -------------------------------------------------------------------------------- 1 | public delegate void InjectEvent(T t, J j, K k); 2 | -------------------------------------------------------------------------------- /MonoHolder.cs: -------------------------------------------------------------------------------- 1 | public class MonoHolder 2 | { 3 | public T t; 4 | public J j; 5 | 6 | public MonoHolder(T t, J j) 7 | { 8 | this.t = t; 9 | this.j = j; 10 | } 11 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Get Component Attribute 2 | A little attribute that makes Awake/Start GetComponent calls redundant. 3 | 4 | Generally in unity, we need to fill fields like this as follows: 5 | ```c# 6 | private Rigidbody rigidbody; 7 | void Start(){ 8 | rigidbody = GetComponent(); 9 | } 10 | ``` 11 | 12 | But especially while working with teams, if you DI through Scene objects from inspector, 13 | Scene merge conflicts become inevitable. But we shouldn't dirty our code base with those get component methods in various fields. 14 | It will reduce readability. 15 | **This plugin, removes this requirement and takes care of it with an attribute in background before scene begins.** 16 | 17 | ## Example Usage 18 | ```c# 19 | [GetComponent] //Get from same gameobject 20 | private Rigidbody rigidbody; 21 | 22 | [GetComponent(GetComponentFrom.SceneObject)] //Scan the scene and get from first object. 23 | private Rigidbody rigidbody; 24 | 25 | [GetComponent(GetComponentFrom.TargetGameObject,"MyAwesomeTargetObjectName")] //Get from a target object at scene 26 | private Rigidbody rigidbody; 27 | ``` 28 | 29 | ## Installation 30 | Just clone the repo and copy the folder into your project. 31 | 32 | ## Note 33 | **[!]GetComponentFrom.TargetGameObject currently runs between awake and start methods.** 34 | 35 | ## TO-DO 36 | - Editor time component fetching 37 | - On-demand(non awake based) runtime component fetching 38 | - Fetch signals(Event driven fetch on runtime) 39 | 40 | ## Contributing 41 | Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. 42 | 43 | ## License 44 | [MIT](https://choosealicense.com/licenses/mit/) 45 | 46 | --------------------------------------------------------------------------------