Skip to content

Commit 20e2145

Browse files
author
github-action
committed
Automatically copied the original REPO files (README, CHANGELOG, LICENSE and ThirdPartyNotice) to the upm package.
1 parent 1740479 commit 20e2145

File tree

8 files changed

+162
-0
lines changed

8 files changed

+162
-0
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

CHANGELOG.md.meta

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

LICENSE.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2020 Daniel Dyrda
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

LICENSE.md.meta

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# Singleton Mono Behaviour
2+
3+
> Another Singleton ```MonoBehaviour``` implementation for Unity.
4+
5+
> 🧪 **EXPERIMENTAL** This project is experimental. It is still under development. It may be unstable. It is not optimized and largely untested . Do **not** use this project in critical projects.
6+
7+
This package for Unity provides an implementation of the Singleton pattern for ```MonoBehaviour``` instances. The package introduces the ```SingletonMonoBehaviour``` class. With this class, we can create concrete ```MonoBehaviour``` components that can be added to game objects in the scene and behave in the same way as classic ```MonoBehaviour``` components – just as a singleton.
8+
9+
The class implements the most common features described for ```MonoBehaviour``` singletons, such as persistence, handling of multiple instances and performance optimizations. Check out the [Features](#features) section for a complete overview of the features.
10+
11+
> 💭 **A short comment of Daniel on the Singleton pattern:** At this point we do not want to enter the discussion about whether the Singleton pattern is good or bad. Whether it is more good than bad, or vice versa, depends on the concrete use case. This should be evaluated on a case-by-case basis. So don't get discouraged if somebody says that Singleton is an antipattern. In this radical statement, I do not think this is true. I know many situations in which a Singleton offers a beautiful solution. At the same time, however, it is true that one can easily drift into a suboptimal code structure. So use the pattern very consciously and be aware of the consequences. Make yourself fully aware of what you are doing. If you are unsure, a singleton will probably lead to suboptimal code. If you are looking for a good alternative to Singletons, **"Dependency Injection"** seems to be a good approach. There are some solutions of "Dependency Injection" available for Unity.
12+
13+
If you want to read more about the singleton pattern, check out [Game Programming Patterns - Singleton](http://gameprogrammingpatterns.com/singleton.html) by Robert Nystrom.
14+
15+
## Quick Start
16+
17+
Install the package as described [below](#install-the-package). Now you may find yourself in the following situation: You have a class that currently inherits from ```MonoBehaviour``` and you want it to be a Singleton. Then follow these steps:
18+
19+
1. **Preparation:** Open the script of the class which should be a singleton. To use the class ```SingletonMonoBehaviour``` in your script, you have to include the "DyrdaDev.Singleton" using directive. At the beginning of your script, insert the following line: ```using DyrdaDev.Singleton;```.
20+
2. **Implementation of the concrete Singleton:** Change the superclass from which the class in question inherits from ```MonoBehaviour``` to ```SingletonMonoBehaviour<T>```. ```T``` is the type of your original class in question that will be the concrete ```SingletonMonoBehaviour```.
21+
3. **Accessing the Singleton from everywhere:** Done. Now you can access the Singleton via the ```Instance``` property of the concrete Singleton class.
22+
23+
**Example:** Here is an example for a ```GameData``` class with a ```Score``` property. The ```GameData``` class is supposed to be a singleton. The result of the steps as described above looks like this:
24+
25+
```C#
26+
using UnityEngine;
27+
using DyrdaDev.Singleton;
28+
29+
public class GameData : SingletonMonoBehaviour<GameData>
30+
{
31+
public int Score;
32+
33+
// ...
34+
}
35+
```
36+
37+
Now, you can access the ```Score``` property via ```GameData.Instance.Score``` from any script in your project that has access to the ```GameData``` class.
38+
39+
## Features
40+
41+
Our Singleton implementation offers the following features:
42+
43+
#### Event Functions
44+
```SingletonMonoBehaviour``` inherits from ```MonoBehaviour```. This means, we work with concrete ```MonoBehaviour``` components on objects in the scene – just as a singleton. As consequence of the inheritance of ```MonoBehaviour```, the derived classes of ```SingletonMonoBehaviour``` have access to all Unity event functions such as ```Awake```, ```Start```, ```Update``` or ```FixedUpdate```. Please note: ```Awake``` and ```OnDestroy``` are used by the base singleton class. When using these classes, use the ```overwrite``` keyword and make sure to call the base method. For example:
45+
46+
```C#
47+
using System;
48+
using UnityEngine;
49+
using DyrdaDev.Singleton;
50+
51+
public class SingletonTest : SingletonMonoBehaviour<SingletonTest>
52+
{
53+
protected override void Awake()
54+
{
55+
base.Awake();
56+
// ...
57+
}
58+
}
59+
```
60+
61+
#### Persistence
62+
We work with real ```MonoBehaviour``` components and ```GameObjects``` – in other words, with components and objects in the scene. Singletons should usually be persistent for the runtime of an application, even between scene loads. Our code will take care of this for you if you like. You can control the behavior with the ```PersistOnSceneLoad``` property. If ```PersistOnSceneLoad``` is true, we do not destroy the instance when loading scenes with the ```DontDestroyOnLoad``` functionality. Our implementation also takes care of some preparations for this. The default value for ```PersistOnSceneLoad``` is ```true```. You can set the static field ``PersistOnSceneLoad`` in the implementation of your concrete ``SingletonMonoBehaviour`` class so that everything behaves according to your requirements.
63+
64+
#### Exactly one Singleton, not more
65+
We make sure that there is always only one instance of the singleton in the scene. Further instances of a singleton are automatically destroyed.
66+
67+
#### Exactly one Singleton, not less
68+
There should always be an instance of a Singleton class. Our implementation can automatically create one for you. The ```CreateInstanceIfNotPresent``` property states whether we create a new object if there is no instance in the scene. The defaut value for ```CreateInstanceIfNotPresent``` is ```true```. You can set the static field ```CreateInstanceIfNotPresent``` in the implementation of your concrete ```SingletonMonoBehaviour``` class so that everything behaves according to your requirements.
69+
70+
#### Inactive Singletons
71+
When looking for instances in the scene, we can include inactive objects or ignore them. If the ```ConsiderInactiveInstances``` property is ```true```, we also consider inactive instances in the scene when we search for an instance. The default value for ```ConsiderInactiveInstances``` is ```false```. You can set the static field ```ConsiderInactiveInstances``` in the implementation of your concrete ```SingletonMonoBehaviour``` class so that everything behaves according to your requirements.
72+
73+
#### Thread Safety
74+
This implementation is (/ should be) thread-safe. It uses a lock object for instance access and implements some other optimizations. Please note: There are other solutions out there with different approaches that may better suit your needs. (Compare for example [this article by Jon Skeet](https://csharpindepth.com/Articles/Singleton)) Also note that accessing Unity's internal features from parallel threads can lead to errors and inconsistencies. You should be clear about what you are doing if you want to work with threads and ```MonoBehaviour```.
75+
76+
#### Loading on Demand
77+
With the ```Singleton-MonoBehaviour``` we work with ```GameObjects``` in the scene. So we have to find the one instance that is our current singleton instance. With the property ```LoadOnDemand``` you can decide whether we should find the correct instance at ```Awake``` or later on demand when a script tries to access the instance. If ```LoadOnDemand``` is true, we wait to find the instance until a script tries to access the instance. The default value for ```LoadOnDemand``` is ```false```. You can set the static field ```CreateInstanceIfNotPresent``` in the implementation of your concrete ```SingletonMonoBehaviour``` class so that everything behaves according to your requirements. Keep in mind that initialization requires resources and may result in some frame drops if the "onDemand" scenario occurs during performance-critical situations.
78+
79+
#### Performance
80+
Every access to the current instance requires some checks. These checks are a bottleneck because they are executed every time any piece of code accesses the singleton. Our implementation uses a flag to check if an instance already exists. This is better performing than a common approach used in many implementations based on the ```==``` operators. This is the case because Unity overloads the ```==``` operator. Unity's overloaded ```==``` operator is quite slow. You can read more about this topic in [this Unity blog article](http://blogs.unity3d.com/2014/05/16/custom-operator-should-we-keep-it/).
81+
82+
#### Logging
83+
The solution outputs debug logs whenever something "interesting" happens. The "OnDestroy" warning can be muted by setting the ```MuteOnDestroyWarning``` property to true.
84+
85+
86+
## Install the Package
87+
88+
You can install this package with unity's [package manager](https://docs.unity3d.com/Manual/PackagesList.html). Simply add a new package with the git-HTTPS URL to the version you want to install in the form ```https://github.com/DyrdaDev/singleton-mono-behaviour.git#{version}```, where ```{version}``` is the actual version of the release you want to install. For example, if you want to install version ```0.0.8``` of this package, you can refer to ```https://github.com/DyrdaDev/singleton-mono-behaviour.git#0.0.8```.
89+
90+
You can do this by using the Package Manager window or the manifest.json directly:
91+
92+
1. **Installing from a Git URL using the Package Manager window.** Open the Package Manager window. Click "+", then "Add package from git URL" and enter the git URL from above. You can find more information [here](https://docs.unity3d.com/Manual/upm-ui-giturl.html).
93+
2. **Installing from a Git URL using the manifest.json.** You can add a new entry to the manifest.json file in the ``Packages`` folder of your unity project: ```"dev.dyrda.singleton.singleton-mono-behaviour": "https://github.com/dyrdadev/singleton-mono-behaviour.git#upm"```. You can find more information [here](https://docs.unity3d.com/Manual/upm-git.html).
94+
95+
## License
96+
97+
This package is licensed under a MIT license. See the [LICENSE](/LICENSE.md) file for details.
98+
99+
## Contribute
100+
101+
This project was created by [Daniel Dyrda](https://dyrda.digital).
102+
103+
> Daniel: _If you want to support me and my projects, you can follow me on [github (DyrdaDev)](https://github.com/DyrdaDev) and [twitter (@daniel_dyrda)](https://twitter.com/daniel_dyrda). Just come by and say hello, I would love to hear how you use the project._
104+
105+
If you want to contribute to this project, you are welcome to do so. Just write me and we will find a way to collaborate.
106+

README.md.meta

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ThirdPartyContent.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This package contains third-party content governed by the license(s) indicated below:

ThirdPartyContent.md.meta

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)