From java to c# how to use GetComponent?

This is my java code:

var OBJ_target : Transform; 

var Name_script_target = "";

var target ;



function Awake()

	{

	target = OBJ_target.GetComponent(Name_script_target);

	}



function OnMouseDown () 

	{

	target.my_var = true;

	target.my_interaction();

	}

With it I can have different script, with different "function my_interaction()"in it, in different objects and call exactly that I want using the unity inspector to indicate the contenent of “var OBJ_target”, “Name_script_target” and “target”.

How to make the same thing in c#?

var OBJ_target : Transform; 

var Name_script_target = "";

var target ;



function Awake()

	{

	target = OBJ_target.GetComponent<Name_script_target>();

	}

It don’w work: error CS0118: Name_script_target' is a field’ but a `type’ was expected

I’m sorry I didn’t notice Name_script_target was a string. You need to add ‘as Name_script_target’

For more information, Go here

I try this C#, but it don’t work neither:

public Transform OBJ_target; 
public string Name_script_target = "";
private Component target ;



function Awake()

	{

	target = OBJ_target.GetComponent<Name_script_target>() as Name_script_target;	

	}



function OnMouseDown () 

	{

	target.my_var = true;

	target.my_interaction();

	}

First of all, the problem is in javascript’s relaxed syntax. What you have in JS is not what you want at all. You have Name_script_target declared as a string. the GetComponent() takes a type (and in javascript, GetComponent(T) takes a type). a String is NOT a component, and Name_script_target is NOT a Type. whatever you are trying to do, you are doing it wrong no matter how you look at it. Can we get an idea of what you are trying to accomplish?

Actually there is a GetComponent(string) but it is rarely used for performance reasons. You cannot do what he is attempting in C# that I know of. (getting a component using a string variable). Not to mention there is very rarely a reason to do so.

If you know the name of the component, then just put it in the <> of GetComponent.

For example, if you initially had Name_script_target set to “ScriptName”, then just do

target = OBJ_target.GetComponent<ScriptName>() as ScriptName;

I’m trying to make a generic interactive button (not a GUI, but a 3d prefab) in game. When you click on it, it active a door or start an animation or other things in a different gameobject.

So I have maked different scripts in C# for exampre “Open_door.cs” or “star_animation.cs”. All this script have in it a public void called “my_interaction()” but whit different instruction in it.

I put a generic button prefab in scene and use unity inspector in order to indicate:
public Transform OBJ_target //what is the object thai I whant to control with the generic button prefab (I click and drag it form the scene in the inspector script of the button prefab )
public string Name_script_target = “”; //the name of the script in this object (example “Open_door”)

So when i click on the generic button prefab in the game, it call the “public void my_interaction()” in the script “Name_script_target” that is a component of “OBJ_target”

Ah, I see what you are trying to do. Well, in that case, I don’t think it is possible. If Unity allows Generic classes to be children of MonoBehaviour, then you might be able to do it that way.

Ok, thanks! I will thinking out a diverse solution.

Better way:
Implement an Interface for your interaction.
Than let your interaction Classes implement that interface.

Than you should be able to use GetComponent()

If you want to stay with your way:
GetComponent(Name_script_target);
Just make sure, that your “Name_script_target” is an acctuall class.

Neither of those methods will work for what he is trying to accomplish. He wants to be able to define which component to retrieve dynamically. Something that is not possible in C# that I can tell.

EDIT: Also, since Unity uses a pretty sophisticated form of component oriented programming, interfaces are rarely needed… That’s not how you do things in Unity… In a normal game engine, yes, interfaces are common practice, but not here… It’s weird to get out of that mind set, but once you do, things become infinitely easier.

you could use events in c# for this, make all your various script listen for this event(under certain condition)

that way you dont care about components, just who is listenning and fire your fct form that

.for example send an enum as argument with the event so you can check which of the script should act

This would do 1:1 what your JavaScript code does:

using UnityEngine;

public class MyGenericScript : MonoBehaviour
{
    public Transform OBJ_Target;
    public string Name_script_target;
    private Component target; 

    void Start()
    {
        target = OBJ_target.GetComponent(Name_script_target);
    }

    void OnMouseDown() 
    {
        SetFieldValue(target, "my_var", true);
        InvokeMethod(target, "my_interaction");
    }

    static void InvokeMethod(object target, string methodName, params object[] parameters)
    {
        var methodInfo = target.GetType().GetMethod(methodName);
        if (methodInfo != null)
            methodInfo.Invoke(target, null);
    }
  
    static void SetFieldValue(object target, string varName, object value)
    {
        var fieldInfo = target.GetType().GetField(varName);
        if (fieldInfo != null)
            fieldInfo.SetValue(target, value);
    }
}

MacGyver Style “ducktyping” :slight_smile: Similar to GameObject.SendMessage but restricted to only the given component.

But is this really what you want? I would use something that was mentioned here already:

MyScriptComponentBase .cs

using UnityEngine;

public abstract class MyScriptComponentBase : MonoBehaviour
{
    public bool my_var;
    public abstract void my_interaction();
}

Foo.cs

using UnityEngine;

public abstract class Foo : MyScriptComponentBase
{
    public bool my_var;
    public override void my_interaction()
    {
        // do something
    }
}

MyGenericScript.cs

using UnityEngine;

public class MyGenericScript : MonoBehaviour
{
    public Transform OBJ_Target;
    public string Name_script_target;
    private MyScriptComponentBase target; 

    void Start()
    {
        target = OBJ_target.GetComponent<MyScriptComponentBase>();
    }

    void OnMouseDown() 
    {
        target.my_var = true;
        target.my_interaction();
    }
}

Edit:

Or you can do something like this:
ComponentExtension.cs

using UnityEngine;

public static class ComponentExtension
{
  public static void my_interaction(this Component component)
  {
    var methodInfo = component.GetType().GetMethod("my_interaction");
    if (methodInfo != null)
      methodInfo.Invoke(component, null);
  }      
}

Now you can call my_interaction() on every Component but, oh boy… this is dark

Thank you :smile:

Oh, so C# DOES have a GetComponent(String) implementation? Interesting… Wasn’t aware of that.