Search Unity

Inheritance problems

Discussion in 'Scripting' started by roBurky_legacy, Nov 7, 2009.

  1. roBurky_legacy

    roBurky_legacy

    Joined:
    Nov 7, 2009
    Posts:
    17
    Hello,
    I have a little problem I'm hoping someone can give me some advice on. I'll also probably use this thread for any future questions I have.

    The first is with using inheritance in javascript in Unity. I've used inheritance a little bit in Flash actionscript, but I'm not a very experienced programmer.

    I want to have a class called Event that handles checking when an event happens. Then I would have a series of classes that inherit from Event that have different specifics for what happens when a particular overridden function is used, such as EventAcceleration that would increase the acceleration of the player's avatar.

    I did a search on these forums, and found this thread which helped a lot.

    So I have a javascript file for Event which begins
    Code (csharp):
    1. class Event extends MonoBehaviour {
    and a file for EventAcceleration which begins
    Code (csharp):
    1. class EventAcceleration extends Event {
    But when I try to add EventAcceleration as a component to an object, I get the error:
    Code (csharp):
    1. Can't add script behaviour EventAcceleration. The script needs to derive from MonoBehaviour!
    Can anyone tell me what I might be doing wrong?
     
  2. DMJ

    DMJ

    Joined:
    Nov 5, 2009
    Posts:
    83
    Hmm, what you tried looks alright to me from a normal standpoint (even if my C# is really rusty), but Unity has a few extra restrictions.

    According to the documentation every class must explicitly derive from Monobehaviour. Even plain old C# also doesn't do multiple inheritance, so that's out too.

    Perhaps this page might offer some help:

    http://www.c-sharpcorner.com/Upload...ance11082005004843AM/MultipleInheritance.aspx

    However, I haven't tried C# in Unity, I'm using Unity as an excuse to learn javascript!
     
  3. Der Dude

    Der Dude

    Joined:
    Aug 7, 2006
    Posts:
    213
  4. roBurky_legacy

    roBurky_legacy

    Joined:
    Nov 7, 2009
    Posts:
    17
    Thanks for the replies.

    That doesn't seem to be the answer, Der Dude. I tried renaming the Event class, and the extends line in EventAcceleration, but I still got the same error.

    It sounds like DMJ is saying that what I am trying to do is not possible in Unity. Is this right? I'm going to either have to put code for all of my different Events into the same script, or duplicate code across multiple scripts?
     
  5. Der Dude

    Der Dude

    Joined:
    Aug 7, 2006
    Posts:
    213
    No, I use inheritance all the time with C#, just like you are doing here.

    I never use JavaScript, so I can't tell you if it possible or not with that.

    @DMJ: Not every class must inherit from MonoBehaviour, just the base-class.
     
  6. Der Dude

    Der Dude

    Joined:
    Aug 7, 2006
    Posts:
    213
    I just tried to reproduce the problem, but it works for me!

    I attatched the Scripts here.

    I added a simple OnGUI function to the extended event to see if Unity works right with the event. It does ;)
     

    Attached Files:

  7. DMJ

    DMJ

    Joined:
    Nov 5, 2009
    Posts:
    83
    I am always happy to be proven wrong when it makes my life (or someone else's life) easier for me to be wrong :D
     
  8. Der Dude

    Der Dude

    Joined:
    Aug 7, 2006
    Posts:
    213
    Thats a healthy attitude you've got there ;)
     
  9. roBurky_legacy

    roBurky_legacy

    Joined:
    Nov 7, 2009
    Posts:
    17
    Well, using your scripts doesn't give me any errors.

    I'll start adding in the functionality of my old scripts and see where it goes wrong.

    Thanks Der Dude.
     
  10. Der Dude

    Der Dude

    Joined:
    Aug 7, 2006
    Posts:
    213
    No problem.

    Something that might be causing your problems are the filenames. Are they all named like the class that are in them?
     
  11. roBurky_legacy

    roBurky_legacy

    Joined:
    Nov 7, 2009
    Posts:
    17
    Yes, they all had the same filename as their class name.

    I've got all of the old Event functionality working in your MyEvent, so I don't know what the problem was.

    I'm now at the point of trying to override a function from the base class in the extended class. But I'm not sure how to do this in Unity javascript. The only search results I've found say that 'override' doesn't work in Unity javascript.

    The aim is for the Update() function in the MyEvent class to check common conditions, and then use a function called PerformEvent(), which would be different for each extended version of the class.
     
  12. tonyd

    tonyd

    Joined:
    Jun 2, 2009
    Posts:
    1,224
    When overriding, you simply call the parent function from the child and add any additional functionality beneath it. I'll post an example if I can find my notes...
     
  13. roBurky_legacy

    roBurky_legacy

    Joined:
    Nov 7, 2009
    Posts:
    17
    Thanks, tonyd. An example would be helpful.
     
  14. Der Dude

    Der Dude

    Joined:
    Aug 7, 2006
    Posts:
    213
    May I ask why you don't use C# instead of JavaScript?

    When using inheritance and other Object-Oriented techniques I find C# to be much more transparent (and better documented!) than JavaScript.
     
  15. roBurky_legacy

    roBurky_legacy

    Joined:
    Nov 7, 2009
    Posts:
    17
    The only reason would be that the tutorials and examples I've used so far have all used javascript. I've had no experience with either language before.
     
  16. Der Dude

    Der Dude

    Joined:
    Aug 7, 2006
    Posts:
    213
    I would recommend you switch to C# if you continue using Object-Oriented techniques such as this. This is just my opinion, but I think it is just inherently clearer what the code means when you have such a strongly typed language.
    It gets rather confusing in JavaScript.

    Converting JavaScript to C# isn't too hard. But it is a pain in the neck to convert a whole project. So if you want to switch, do so soon ;)
    I learned that the hard way a few years back...

    If you need help with the C# specifics, you can PM me if I don't see your thread. I'll be glad to help.
     
  17. tonyd

    tonyd

    Joined:
    Jun 2, 2009
    Posts:
    1,224
    Here you go. No reason to switch to C#, you can do most everything you need in javascript and type a whole lot less!

    Code (csharp):
    1. class MyParentClass{
    2.     function MyParentClass(){ //constructor
    3.         //place initialization routines here if needed
    4.     }
    5.     function MyFunction(){
    6.         Debug.Log("Original function called");
    7.     }
    8. }
    9.  
    10. class MyChildClass extends MyParentClass{
    11.     function MyChildClass(){ //constructor
    12.         super(); // calls MyParentClass constructor
    13.         //add additional functionality here
    14.     }
    15.     function MyFunction(){
    16.           super.MyFunction(); //calls original MyParentClass function
    17.          //add additional functionality here
    18.         Debug.Log("New function called");
    19.     }
    20. }
     
  18. tonyd

    tonyd

    Joined:
    Jun 2, 2009
    Posts:
    1,224
    Code (csharp):
    1. test = MyChildClass();
    2. test.MyFunction();
    The console should show that both functions, the original parent and extended child were accessed.
     
  19. roBurky_legacy

    roBurky_legacy

    Joined:
    Nov 7, 2009
    Posts:
    17
    Hmm. Thanks tonyd. I'm not sure that applies to what I'm trying to do, though.

    What I have is something along the lines of this:

    Code (csharp):
    1. class TimelineEvent extends MonoBehaviour {
    2.  
    3.     function Update() {
    4.         // If conditions go here
    5.         PerformEvent();
    6.     }
    7.  
    8.     function PerformEvent() {
    9.         // This function remains empty
    10.     }
    11. }
    Code (csharp):
    1. class TimelineEventAcceleration extends TimelineEvent {
    2.  
    3.     function PerformEvent() {
    4.         // Stuff happens here
    5.     }
    6. }
    7.  
    The update function in the parent class is the one that calls the PerformEvent function. But I want it to use the functionality in the PerformEvent function of the child class.

    My previous experience with inheritance is with Flash Actionscript 3, where I did something very similar to what I describe above.

    Der Dude, would you be able to give me an example of how to do this in C#? If it is easier, I might switch to it now.
     
  20. tonyd

    tonyd

    Joined:
    Jun 2, 2009
    Posts:
    1,224
    Use the super keyword to access the parent class functions and properties from the child class. You can't access children from their parents.
     
  21. Der Dude

    Der Dude

    Joined:
    Aug 7, 2006
    Posts:
    213
    Sure:

    Code (csharp):
    1.  
    2. public abstract class MyEvent : MonoBehaviour
    3. {
    4.     public void Update()
    5.     {
    6.         // If Conditions here
    7.         PerformEvent();
    8.     }
    9.    
    10.     public abstract void PerformEvent();
    11.    
    12. }
    13.  
    Code (csharp):
    1.  
    2. public class MyExtendedEvent : MyEvent
    3. {
    4.     public override void PerformEvent()
    5.     {
    6.         // Perform!
    7.     }
    8. }
    9.  
    You can prevent other scripts from calling PerformEvent by making it protected (instead of public). Then only subclasses of event can call this method.
    This is another advantage of using a properly object-oriented language like C#.
     
  22. roBurky_legacy

    roBurky_legacy

    Joined:
    Nov 7, 2009
    Posts:
    17
    I think I've got this working now.

    This is what I've ended up with:

    Code (csharp):
    1. class TimelineEvent extends MonoBehaviour {
    2.     function EventTimeIsNow() {
    3.         If (conditions == true) {
    4.             return true
    5.         }
    6.         else {
    7.             return false
    8.         }
    9.     }
    10. }
    Code (csharp):
    1. class TimelineEventAcceleration extends TimelineEvent {
    2.     function Update() {
    3.         if (super.EventTimeIsNow()) {
    4.             PerformEvent();
    5.         }
    6.     }
    7.  
    8.     function PerformEvent() {
    9.         // Stuff!
    10.     }
    11. }
    It's not ideal - I was trying to make it as easy as possible for the other members of my group to add new types of event, without having to do anything other than make a script with a new PerformEvent() function. But I think this will do.

    I've got a better idea about how all this works in both javascript and C# now, anyway - I did an experiment into converting the project into C# as well.

    Thanks, everyone.
     
  23. Der Dude

    Der Dude

    Joined:
    Aug 7, 2006
    Posts:
    213
    This is totally possible using a properly object-oriented language like C# and I would recommend this kind of code-design as you save yourself work. Checkout my example, it should do what you want.

    When working in a team C# has another nice feature: you can split up one class onto many files. Just add the modifier "partial" in your class header. Like this:

    FileA.cs

    Code (csharp):
    1. public partial class MyClass
    2. {}
    FileB.cs

    Code (csharp):
    1. public partial class MyClass
    2. {}
    When compiled the parts of the class are put together again. It behaves just like a single class, except you can work independantly on the files.
     
  24. roBurky_legacy

    roBurky_legacy

    Joined:
    Nov 7, 2009
    Posts:
    17
    Actually, I've just figured out what I was doing wrong in my converted C# version of the project, so I might do as you suggest and carry on in C#. Thanks.
     
  25. HanulTech

    HanulTech

    Joined:
    Apr 5, 2009
    Posts:
    312
    roBurky,

    You can do as you intended in javascript, much more simply. No C# required:

    Code (csharp):
    1.  
    2. class TimelineEvent extends MonoBehaviour {
    3.  
    4.   virtual function PerformEvent() {}
    5.  
    6. }
    7.  
    8. class TimelineEventAcceleration extends TimelineEvent {
    9.  
    10.    function PerformEvent() {
    11.      
    12.       // If the PerformEvent method of TimelineEvent has an implementation, uncomment this line to call it.
    13.       //super.PerformEvent();
    14.  
    15.       // Implement TimelineEventAcceleration-specific PerformEvent behavior here:
    16.  
    17.  
    18.  
    19.      return;  
    20.    }
    21. }
    22.  
    Note that if you use Unitron, the virtual keyword will not show up as a known keyword. Neither will super. Both are supported by Unity, however.

    Now you can take object instances of all sorts of derived events, explicitly or implicitly cast them to your TimelineEvent base class, and call their respective PerformEvent methods polymorphically. No downcasting or knowledge of the specific child class type is necessary. For example, let's say you wanted to implement an event handler to which these events would be passed. You can just do this:

    Code (csharp):
    1.  
    2. function ProcessEvent(event: TimelineEvent) {
    3.  
    4.    event.PerformEvent();
    5.  
    6.    return;
    7. }
    8.  
    You can pass any event object instance to this method, regardless of its class type, as long as that class (or a parent) extends your TimelineEvent class.

    Note also that the PerformEvent function in the parent class must be defined with empty brackets, but it will treated as purely virtual unless you call it via the super identifier as noted in the example above, or your child class overrides the method. In the later case, as noted, you have to call the parent's PerformEvent method from within the child's method via super if you want both to be called. Frankly, I don't like the ambiguity between virtual methods and purely virtual methods in the way this was implemented in javascript. Incidentally, C# addresses this clearly through the override keyword.

    Unfortunately, there is a lot of misinformation on the forum regarding inheritance and polymorphism in javascript. This may be because virtual methods/functions weren't always supported in Unity javascript (I haven't been around long enough to know for sure) and because of the dearth of information in the documentation. I love C# as much as much as the next guy, but if you choose to switch, you should do so based on correct information. There are many things you can do in C# and can't do in javascript, but this is not one of them.