TL;DR: You don't need to duplicate a bunch of code to do the same things to a
So that's pretty easy right, one way of doing it is with a
It is simple, right?
But what happens when you want to do the same thing to a UI element? Like a
Well that's easy too: we can just do the same thing we did for sprites and build a
The only difference between the two classes is that one works with
So how can we avoid this duplication? We could use Reflection, or if we were using a later version of C# we might use the dynamic keyword. The answer that I want to talk about is the Adapter Pattern.
We can add other functionalities to our adapter class, such as access to underlying
Beyond that, its easy to extend this to work with other components. We can define a
One catch we do need to watch out for here: Where do we construct the
The good news is that in practice this is (usually) a non-issue. This is because (usually) there will be an attached component which references your
Image
and a SpriteRenderer
, or RectTransform
and Transform
, etc. You can use a simple pattern called the Adapter Pattern. If you've never used it before, this post explains how.The Problem: Image vs SpriteRenderer
Lets say you want to make a sprite fade out, maybe its a dead monster or a collectible, but in either case you want it to gracefully depart from the screen rather than blink out of existence. Kinda like this eyeball monster from Beastly:So that's pretty easy right, one way of doing it is with a
MonoBehaviour
that modifies the sprites alpha value via SpriteRenderer.color
. Your class might look something like this: public class AlphaFaderSprite : MonoBehaviour { public SpriteRenderer spr; public float fade_percentage; void Update() { spr.color = new Color(spr.color.r, spr.color.g, spr.color.b, fade_percentage); } }Now, anyone who's used Unity for more than an hour is now screaming internally at how inefficient the above class is. You'd never write code like this in reality, but for the sake of this tutorial lets ignore the specifics and keep things simple.
It is simple, right?
But what happens when you want to do the same thing to a UI element? Like a
UI.Image
?
Well that's easy too: we can just do the same thing we did for sprites and build a
AlphaFaderUI
:
public class AlphaFaderUI : MonoBehaviour { public Image img; public float fade_percentage; void Update() { img.color = new Color(img.color.r, img.color.g, img.color.b, fade_percentage); } }Great, but now alarm bells are ringing all up in your brain because you just wrote the same class twice.
The only difference between the two classes is that one works with
Image
and the other works with SpriteRenderer
. Usually, this is where something like Polymorphism would come in handy, but unfortunately Image and SpriteRenderer meet in the class tree at Component
, which doesn't provide a color member.So how can we avoid this duplication? We could use Reflection, or if we were using a later version of C# we might use the dynamic keyword. The answer that I want to talk about is the Adapter Pattern.
The Adapter Pattern
First we define the adapter abstract base class,ColorAdapter
, this promises to give us a way of modifying the color. This is what our generic components will use instead of SpriteRenderer
or Image
public abstract class ColorAdapter { public abstract Color color { get; set; } }Next we subclass
ColorAdapter
for both Image
and SpriteRenderer
, these each simply delegate color modifications to their "adaptee" member variables.
public class AdaptedImage : ColorAdapter { Image adaptee; public AdaptedImage(Image adaptee) { this.adaptee = adaptee; } public override Color color { get { return adaptee.color; } set { adaptee.color = value; } } } public class AdaptedSpriteRenderer : ColorAdapter { SpriteRenderer adaptee; public AdaptedSpriteRenderer(SpriteRenderer adaptee) { this.adaptee = adaptee; } public override Color color { get { return adaptee.color; } set { adaptee.color = value; } } }Now, in our alpha fade component we simply define
AlphaFader
to use a ColorAdapter
.public class AlphaFader : MonoBehaviour { public ColorAdapter ca; public float fade_percentage; void Update() { ca.color = new Color(ca.color.r, ca.color.g, ca.color.b, fade_percentage); } }And now we can write Alpha Fading logic once and use it for both component types. Mission accomplished.
Pros and Cons
You might be thinking"We've ended up writing more lines of boilerplate code than we duplicated in the first place!"... and you'd be right, but remember that this is a toy example. This class could also be used for any color manipulation (for example: flashing a sprite red when taking damage and "greying out"a shop item to signify that the player has insufficient funds could be the same component). If you've got a more complex series of color transformations the benefits are even greater.
We can add other functionalities to our adapter class, such as access to underlying
Sprite
or Material
for even more flexibility. This might limit the number of Unity Components that can make use of the adapter, but that's only because its an abstract class. ColorAdapter
doesn't actually need to be abstract, it can be an interface. Which means that you can create a myriad of different adapter types which something like a AdaptedImage
can implement, further increasing coverage. An AdaptedImage
could be an IColorAdapter
, an ISpriteAdapter
and an IMaterialAdapter
all at once.
Beyond that, its easy to extend this to work with other components. We can define a
Adapted3DRenderer
for GetComponent<Renderer>().material.color
manipulation and reuse our AlphaFade
component for 3D objects, we can define a AdaptedText
and fiddle with UI.Text
colors.
One catch we do need to watch out for here: Where do we construct the
ColorAdapter
s in the first place? For a simple Image/Sprite adapter it might be okay to have a couple of GetComponent<T>()
calls in the Start()
method of our alpha fading class:
ColorAdapter ca; public void Start() { SpriteRenderer spr = GetComponent<SpriteRenderer>(); Image img = GetComponent<Image>(); if (spr != null) { ca = new AdaptedSpriteRenderer(spr); } else if (img != null) { ca = new AdaptedImage(img); } }but it's easy to see that this might get annoying or complicated as we expand the range of possible adapters. We could try and do this in some kind of baseclass for classes that use the color adapters, but that would limit our ability to use multiple different types of adapter (e.g. some kind of
TransformAdapter
for RectTransform
and Transform
manipulation). Its clear that this would be a band-aid and not a solution.
The good news is that in practice this is (usually) a non-issue. This is because (usually) there will be an attached component which references your
ColorAdapter
holding component. In our first example, the dying monster, this would be the Monster
class, which would be working with AlphaFade
, we can pass responsibility for initialization to Monster.Start()
instead, where we already know that we're dealing with a SpriteRenderer
.
Wrapping Up
So, not bad right? The Adapter pattern is very simple, the type of thing that many of you might have already used without knowing it. I'm highlighting it here because I feel like small patterns like this are often overlooked in favor of more fancy techniques. There are larger versions of this problem where one might be tempted to use Reflection to facilitate a Duck Typing solution but, bar some minor issues, you're probably better off writing a little boiler plate and saving yourself the headache.
~Charles
Nice way of expressing your ideas with us.thanks for sharing with us and please add more information's.
ReplyDeleteJAVA Training in Chennai
Java training institute in chennai
Python Training in Chennai
SEO training in chennai
Big data training in chennai
Selenium Training in Chennai
JAVA training in Annanagar
Java courses in chennai anna nagar
Thanks for sharing informative post. Soulblu is a leading vape store Melbourne offering wide range of e liquids, e electronic cigarette, vape supplies, DIY mixing tools, etc.
ReplyDeleteGood job! Fruitful article. I like this very much. It is very useful for my research. It shows your interest in this topic very well. I hope you will post some more information about the software. Please keep sharing!!
ReplyDeleteSEO Training in Chennai
SEO Training in Bangalore
SEO Training in Coimbatore
SEO Training in Madurai
SEO Course in Chennai
SEO Course in Chennai
SEO Course in Bangalore
SEO Course in Coimbatore
Admire this blog. Keep sharing more updates like this
ReplyDeleteTally Course in Chennai
Tally Training in Chennai
Tally training in coimbatore
Tally course in madurai
Tally Course in Hyderabad
Tally Training in Bangalore
Tally classes in coimbatore
Tally coaching centre in coimbatore
Tally course in marathahalli
German Classes in Bangalore
Aw, this was a really nice post. Finding the time and actual effort to produce a really good article… but what can I say… I procrastinate a lot and don't seem to get anything done.
ReplyDeleteClick here to getMoreinformation.
This post is really nice and informative. The explanation given is really comprehensive and informative..
ReplyDeleteBig Data Hadoop Training In Chennai | Big Data Hadoop Training In anna nagar | Big Data Hadoop Training In omr | Big Data Hadoop Training In porur | Big Data Hadoop Training In tambaram | Big Data Hadoop Training In velachery
this is a very informative https://techgadgetguru.com
ReplyDeleteExcellent, this is one of the amazing blog thanks for sharing with us. Visit Ogen Infosystem for professional website designing and SEO Services in Delhi.
ReplyDeleteWebsite Designing Company in Delhi
It is good post! Will you share it on facebook? I always do it for my good posts because I have many fb followers. If you want to get it too, just visit this site https://soclikes.com/buy-facebook-followers and get
ReplyDeleteเว็บแทงบอล
ReplyDeleteufabet
ufa
พวงหรีด
โควิด
บาคาร่า
ReplyDeleteคาสิโนออนไลน์
ufabet
ufa
เว็บบอล
Movie-watching websites that are more than movie-watching websites Because we are the number 1 free movie site in Thailand for a long time, including new movies, Thai movies, Western movies, Asian movies, we have all kinds of ways for you Including new series Full of all stories without interstitial ads to keep annoying anymore. One place sa-movie.com.
ReplyDeleteAndroid and IOS operating systems. Watch online movies, Thai movies, Western movies, Asian movies, Cartoon movies, Netflix Movie, Action Movies, Comedy Movies, Crime Movies, Drama Movies, Horror Movies, Adventure Movies, Crash Movies and still have many new movies to watch. You can watch for free anytime, anywhere 24 hours a day at see4k.com.
GangManga read manga, read manga, read manga online for free, fast loading, clear images in HD quality, all titles, anywhere, anytime, on mobile, tablet, computer. Android and IOS operating systems. Read top comics, action dramas, comedy, adventure, horror and manga. New coming every day to watch many more. Can be read for free anytime anywhere 24 hours a day at gangmanga.com..
It is no secret that football is among the most popular and widely watched sports. Everybody who likes football tries to find the best platform for free soccer streaming. So, what are the best free sports streaming sites? We are going to answer this question. On this page, you can find a detailed overview of the most widespread soccer streaming websites. Keep on reading and make the best choice for you live24th.me.