2
\$\begingroup\$

What is best practice when wanting to add to GameObject class?

I would like all GameObject to be able to change color IF they have a renderer. Ive tried using a helper class that takes a GameObject and lerps the color value but if i want it to have an update method it must inherit MonoBehaviour, and if it does inherit it then i cant instanciate that helper class.

Now im thinking about creating a new class that manages a GameObject and inherits from Monobehavoiur. It would have one GameObject as a member that it can manipulate. But then i would have to instanciate it from somewhere.

Hmmm unity has its logic but i havent found it yet. Is it clear what i am having problems with? Otherwise please ask.

\$\endgroup\$

2 Answers 2

4
\$\begingroup\$

Unity uses a Component Base Object Management approach. There's a famous article about it in Game Programming Gems 5.

In a few words suchs systems put the accent on Composition over Inheritance. Any object or type (in this case GameObject) is defined as a collection of Components, each one responsible for a specific domain. When you want to add functionality to an object, you'll add a Component instead of extending it. (a full exposition of CBOM is beyond the purpose of this thread, but search for it on the web)

So for what concern your question and unity patterns in general:

Unity Extending Game Object best practice

The sentence above makes no sense. In fact you never extends GameObjects, but eventually MonoBehaviors that are Components (actually they inheritance chains is MonoBehavior->Behavior-Component).

I would like all GameObject to be able to change color IF they have a renderer

I'd say you want to change the color dispkayed by every Render Component that has a Material that allows that.

Ive tried using a helper class that takes a GameObject and lerps the color value but if i want it to have an update method it must inherit MonoBehaviour, and if it does inherit it then i cant instanciate that helper class.

Here you are on the right way. The only thing you are missing is how to extend an operation (color lerp) over multiple frames. In fact you don't need to rely on the Update callback (in a certain way it would even be wrong or at least inefficient). You should use a coroutine for that.

So you helper class simply becomes a method (for this I usually put a collection of static methods like this in a static class that act as my helper class):

IEnumerator LerpColorInSeconds(float sec, Material m, Color newCol)
{
  float t = Time.deltaTime;
  Color startColor = m.color;
  while (t < sec)
  {
    material.color = Color.Lerp (startColor, newCol, sec / t);
    yield return null;
    t += Time.deltaTime;
  }
  material.color = newCol;

}

when you need to lerp a color of a Material from inside a given MonoBehavior:

StartCoroutine(LerpColorInSeconds(1f, renderer.material,Color.black));

For more details on coroutines have a look here.

EDIT

Sorry for the mistake. StartCoroutine isn't a GameObject method but belongs to MonoBehavior. So for what concern your question on extension methods: in order to use StartCoroutine method you need a reference to a MonoBehavior. I don't think use an extension method is a particularly good idea here, btw you can't add an extension method to GameObject because it's not a behavior itself. If you want to extend MonoBehavior:

public static class Extension
{
    public static void LerpColor(this MonoBehaviour g, Color col, float lerpTime)
    {
        if (g.renderer != null)
        {
            g.StartCoroutine(LerpColor(lerpTime,g.renderer.material,col)); 
        }

    }

}
\$\endgroup\$
6
  • \$\begingroup\$ Thanks! I see what you are saying, it seems that i have to learn a whole new approach to programming. Very interesting and it makes sense. So if i understood you correctly there are 2 things i need to catch up on so i dont try to program a way Unity is not intended for. 1. Coroutines instead of using update methods to do stuf that take longer time then should be done in one cycle. 2. Dont extend GameObjects, rather make my own components and add them to GameoObjects. Is that correct? \$\endgroup\$
    – Daarwin
    Commented Oct 13, 2013 at 18:00
  • \$\begingroup\$ basically yes. Let's say that from a certain point of view everything you can do in update you can do it also inside a coroutine. But update will be called every frame, meanwhile coroutine will be destroyed after the job is done. So for operations that last a limited amount of time coroutines are cheaper in terms of amount of cpu cycles. \$\endgroup\$
    – Heisenbug
    Commented Oct 13, 2013 at 18:33
  • \$\begingroup\$ Great! Im checking it out. But it does not seem to be possible to have an extension method that starts a coroutine. Id like to have an extension method for the GameObject that checks if the object has a material and then lerps the color to a target color. \$\endgroup\$
    – Daarwin
    Commented Oct 13, 2013 at 20:29
  • \$\begingroup\$ @Lautaro: I've fix the answer. \$\endgroup\$
    – Heisenbug
    Commented Oct 13, 2013 at 20:55
  • \$\begingroup\$ Thanks! Great to know about the Monobehaviour instead of GameObject. However i dont get your exmample. Its just looping is it not? \$\endgroup\$
    – Daarwin
    Commented Oct 13, 2013 at 22:42
0
\$\begingroup\$

Two things that come to issues like this where what you want is essentially a base MonoBehaviour class with extra functions is to either:

  1. Write extension methods for the MonoBehaviour class itself and use those to implement the color change effect. There is a very good explanation of such methods up on Gamasutra, so here's the link.(http://www.gamasutra.com/blogs/JoshSutphin/20131007/201829/Adding_to_Unitys_BuiltIn_Classes_Using_Extension_Methods.php).

    Essentially what you would be doing is creating 'extra' methods that a MonoBehaviour could use, and those functions could be called just like any other class function (placed in update or wherever you would want to call them). Such methods require that they are in a static class and then use a static method with a special reference parameter that refers to the class you're modifying.

  2. Create a class that inherits from MonoBehaviour with a ChangeColor() method, and then inherit from that class for all of your other classes. Then you can call that function in Update or where you'd like. Probably the simplest to do.

As far as what you're having problems with, it seems like you don't quite have a grasp on the context of MonoBehaviours as far as their place in the Unity engine. Keep in mind that unless you're doing something that is completely data-specific that does not require any use of the MonoBehaviour functions like Start, Awake, Update, etc... (which means most GameObjects in any scene), you'll be deriving from it. If you're writing in javascript (unityscript) all of your scripts automatically derive from it and the large majority of your c# scripts will also.

http://docs.unity3d.com/Documentation/ScriptReference/MonoBehaviour.html

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .