Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am trying to use component based design in Unity3d v5. If I have 2 separate C# scripts attached to enemy ships like below:

  1. Script1.shipDead() - Remove game object and show explosion animation
  2. Script2.showPoints() - Destroyed ship shows points ex: +100 (later this will fade away)

How can I perform showPoints() function after shipDead() function has been performed, as a callback?

I can't put both actions in the same function, as some enemies will not have points. Some enemies will leave power ups/ small enemies/ bombs after being destroyed.

And I don't want to duplicated the same code in 4 functions.

Like :

  1. function 1: destroy ship (nothing more)
  2. function 2: destroy ship + show points
  3. function 3: destroy ship + spawn small enemies
  4. function 4: destroy ship + show points + spawn bomb

(As you can see above, there are many different possibilities / combinations I can come up with)

I need to separate functions and isolate them to do individual tasks. As shipDead() will not do anything related to showPoints() or showPowerUp() functions.

My question is how can I perform functions sequentially? One after another, like a callback function?

Like this:

  1. run Script1.DestroyShip() first;
  2. after that run Script2.ShowPoints();
  3. and finally run Script3.SpawnBomb();

Please provide a solution that will not violate the following:

  1. Components needs to be reusable (I can drag and drop the scrip in to other enemies/ships)
  2. Code shouldn't be duplicated
  3. Loosely coupled (Lesser dependancies)

Please help me on this, Thanks in advance!

share|improve this question
    
Why not use a virtual method? Override it to add extensions. Although, I guess that violates the dependency thing. I think your components are too small. I know splitting a game object up into little reusable functionality like this sounds appealing, but in practice I've found it's much more trouble than it's worth, especially when game objects with multiple states and animations are involved. The fact that all these things need to be executed in a sequence upon a specific event is enough to tell you they have some sort of dependency on something. –  Ben Mar 27 at 12:05
    
Thanks for the quick reply ben, with your experience do you encourage to use standard OOP, inheritance and etc over this "component based design". Do you find OOP more easier to implement in practice? –  NeverBeenToSchool Mar 27 at 14:22
    
I think it certainly is a great way to go about things, just not in this way. Trying to completely decouple tiny functionality like this is very difficult and probably not worth the time. For the approach I'd recommend, look at Unity's example components( there's a heap in the Unity 5 demos ) or at the examples in Unreal 4( there's a heap here too ). Really, components in this sense should provide one complete package, that's more than a single method. Think of transform, RigidBody, Renderer, etc. They can be huge pieces of code, but are still very reusable. –  Ben Mar 27 at 15:02

1 Answer 1

I see two solutions to your questions.

1) Use the SendMessage(string methodName) function. It will call the given method on every components of the gameObject. (More info here: http://docs.unity3d.com/ScriptReference/Component.SendMessage.html).

Here is an example:

public class Script1 : MonoBehavior
{
    public void DestroyShip()
    {
        /* Destroy the ship here. */
        SendMessage("OnShipDestroyed");
    }
}

public class Script2 : MonoBehavior
{
    public void OnShipDestroyed()
    {
        this.ShowPoints();
    }

    public void ShowPoint()
    {
        /* Show points here. */
    }
}

2) Use .Net events. Receiver registers to an event triggered when the ship is destroyed. Here is an example as well:

public class Script1 : MonoBehavior
{
    public event System.EventHandler OnShipDestroyed;

    public void DestroyShip()
    {
        if (this.OnShipDestroyed != null)
        {
            this.OnShipDestroyed.Invoke(this, new System.EventArgs());
        }
    }
}

public class Script2 : MonoBehavior
{
    void Awake()
    {
        this.GetComponent<Script1>().OnShipDestroyed += OnShipDestroyed;
    }

    private void OnShipDestroyed
    {
        this.ShowPoint();
    }

    public void ShowPoint()
    {
        /* Show points here. */
    }
}

Note that this solution creates a dependency of Script2 to Script1.

Hope it helps.

share|improve this answer
1  
Not much point using events in Unity for the purpose of decoupling components if you're going to keep the dependency. You should definitely mitigate as much dependency as possible by instead just even using a single EventManager Singleton class etc. You'll quickly run into spagetti code adding listeners to individual scripts etc. –  DanoThom Mar 27 at 13:12
    
Thanks! It seems "component based design" is not the best approach ever. Do u think for big projects this "component based design" is not a good idea? As it seems to be creating more problems for me. –  NeverBeenToSchool Mar 27 at 14:27
    
I totally agree with DanoThom that the second solution leads to dependencies and puzzle-programming. The first solution is more suitable for the component design you are trying to achieve as the SendMessage function does not require a recipient, and do not require to know the type of the script that invoke it. –  Hef Mar 27 at 16:58
    
@Hef You just have to know the EXACT name of the message in order to respond to it. Sounds like a dependency to me. Just a very poorly expressed one. –  Ben Mar 27 at 17:22

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.