Search Unity

Question How to get component by using interface?

Discussion in 'Visual Scripting' started by Kichang-Kim, Jul 30, 2021.

  1. Kichang-Kim

    Kichang-Kim

    Joined:
    Oct 19, 2010
    Posts:
    1,011
    Hi. I created custom Unit for controlling my another custom monobehaviour.

    When I using concrete type for ValueInput, it works correctly. Here is code:
    Code (CSharp):
    1. public class MyMonoBehaviour : MonoBehaviour, IMyInterface {}
    2.  
    3. public abstract class MyUnit : Unit
    4. {
    5.     [DoNotSerialize]
    6.     [PortLabelHidden]
    7.     [NullMeansSelf]
    8.     public ValueInput Controller;
    9.  
    10.     protected override void Definition()
    11.     {
    12.         this.Controller = this.ValueInput<MyMonoBehaviour>(nameof(this.Controller), null).NullMeansSelf();
    13.     }
    14.  
    15.     protected MyMonoBehaviour GetController(Flow flow)
    16.     {
    17.         return flow.GetValue<MyMonoBehaviour>(this.Controller);
    18.     }
    19. }
    But when I changing type MyMonoBehaviour to interfeace IMyInterface, it always return null and graph editor shows GUI texture null warnings:

    Code (CSharp):
    1. public abstract class MyUnit : Unit
    2. {
    3.     [DoNotSerialize]
    4.     [PortLabelHidden]
    5.     [NullMeansSelf]
    6.     public ValueInput Controller;
    7.  
    8.     protected override void Definition()
    9.     {
    10.         this.Controller = this.ValueInput<IMyInterface>(nameof(this.Controller), null).NullMeansSelf();
    11.     }
    12.  
    13.     protected IMyInterface GetController(Flow flow)
    14.     {
    15.         return flow.GetValue<IMyInterface>(this.Controller);
    16.     }
    17. }

    How to get component via interface?

    Thanks.
     
  2. phreezie

    phreezie

    Joined:
    Oct 3, 2019
    Posts:
    119
    I have the same issue. Did you somehow manage to solve this?
     
  3. Trindenberg

    Trindenberg

    Joined:
    Dec 3, 2017
    Posts:
    398
    I have been learning Interfaces somewhat, they are a contract of methods, interfaces to class methods. So, if you have interface myInterface, it must have a get/set method for a particular variable. Then your class has to implement the getter/setter for the ValueInput. That's all I can say for now, not sure on actual coding. I assume in the interface you have:
    public ValueInput getValueInput();
    public void setValueInput(ValueInput value);

    then implement them in your class.
     
  4. Trindenberg

    Trindenberg

    Joined:
    Dec 3, 2017
    Posts:
    398
    Saying that I looked at it wrong, was thinking of when I put an Interface on a unit. But maybe that helps anyway!
     
  5. phreezie

    phreezie

    Joined:
    Oct 3, 2019
    Posts:
    119
    @Trindenberg I think you misunderstood the question. We're not asking what an interface is, rather than how to make a ValueInput that takes in any type implementing a given interface.

    I think I figured it out. You'll have to define your port type as Object and then customize the inspector to pull in only instances of your interface. In order to do that, you'll need a UnitWidget for your Unit that returns your own implementation of Inspector for your given port.

    You'd still be able to link all type of objects to your port, but you can make a nice selector in the inspector that only proposes instances of your interface. There might even be a way to validate correctly, I'm looking into that.

    I'll post some code once I've merged and fully tested everything.
     
  6. Trindenberg

    Trindenberg

    Joined:
    Dec 3, 2017
    Posts:
    398
    Yes that would be great and helpful, still learning!