- Home /
GetComponents array in C# error ?
Hello I was wondering if in C #, you can change the variables of each script from an array and not by GameObject.Find ("myobject"). GetComponent ()?
In Javascript I do it and it worked!
var tempScripts: Component [];
tempScripts = transform.Find ("Camera") GetComponents(MonoBehaviour);
tempScripts[0].blur=1;
tempScripts[1].intensity = 10;
tempScripts[2].CheckPosition ();
And when I do it in C #
public Component [] tempScript;
tempScript = transform.Find ("Camera") GetComponents ();
tempScript [0] = 1 .blur; // The mistake here.
UnityEngine.MonoBehaviour 'does not contain a definition for 'blur' and no extension method 'blur' of type UnityEngine.MonoBehaviour 'could be found (are you missing a using directive or an assembly reference?)
And as I have more than 300 objects and all with their own name and individual script (one different from the other), but they all have the the same variable: ex value.
Another example Java:
var tempScripts: Component [];
var ray:Ray=transform.Find("Camera")GetComponent(Camera).ViewportPointToRay(Vector3 (1,1,0));
var hit: RaycastHit;
if (Physics.Raycast (ray hit, 10)) {
tempScripts = hit.collider.gameObject.GetComponents(MonoBehaviour);
tempScripts[0].value = 10;
}
And when I do it in C #
public Component [] tempScript;
Ray ray=transform.Find("Camera").GetComponent<Camera>().ViewportPointToRay(new Vector3(1,1,0));
RaycastHit hit;
if (Physics.Raycast (ray, out hit 10, CameraRaycast)) {
tempScripts=hit.collider.gameObject.GetComponents<MonoBehaviour> ();
tempScripts[0].value = 10; // ERROR HERE
}
UnityEngine.MonoBehaviour 'does not contain a definition for 'value' and no extension method 'value' of type 'UnityEngine.MonoBehaviour 'could be found (are you missing a using directive or an assembly reference?)
So I was wondering is possible to do in C # which command should I use? Thank you, and sorry for my English.
Answer by Suddoha · Sep 29, 2015 at 01:01 PM
Well, you declare a Component array in the first example, and a MonoBehaviour in the second one.
That means, all the elements are known to be Component or MonoBehaviour respectively, that is, you can only access the members that a general Component (or MonoBehaviour) exposes even though the scripts that you've got in the array are more specific with your own variables and methods.
You said you've got 300 objects with different scripts, but all of them expose one variable with the same name. Well, than it makes sense to either use interfaces so that they offer the same methods or use a base class and GetComponents().yourMemberVariableorMethod in order to be able to access things they have in common.
you could show me an example using the command line to me better understand what I should do ? thank you.
First of all it would be helpful if you posted a few of your scripts. It seems that something is wrong with your approach if you have 300 different scripts which are somehow similar to each other.
Answer by RenanRL · Sep 30, 2015 at 02:21 PM
hello friend, I managed to make it work , using it!
public Component[] tempScript;
tempScript = transform.Find("Camera").GetComponents<MonoBehaviour>;
tempScript[0].GetType().GetField("blur").SetValue(tempScript[0],1);
tempScript[1].GetType().GetField("intensity ").SetValue(tempScript[1],10);
tempScript[2].SendMessage("CheckPosition");
I hope you don't use that frequently, because reflection can be highly inefficient. There are better solutions to your problem, the way to go in your case is using a hierarchy of classes /interfaces, using reflection serves other purposes. Just sayin' though. Good luck with it.
Answer by maccabbe · Oct 01, 2015 at 03:13 AM
You should learn about inheritance and interfaces as well as component systems. In Unity you can make classes inherit from MonoBehaviours, i.e.
public class DerivedMonoBehaviour : MonoBehaviour
{
public int blur;
public int intensity;
public void CheckPosition(){}
}
Then you access components using GameObject.GetComponent<T>()
The problem is that you are using GameObject.GetComponent<MonoBehaviour>()
which returns a MonoBehaviour. The base class MonoBehaviour does not define the variables you are trying to change The variables you are trying to change are defined here in the derived class DerivedMonoBehaviour . Therefore if you want to modify the variables of DerivedMonoBehaviour use GameObject.GetComponent<DerivedMonoBehaviour>()
. For instance
public DerivedMonoBehaviour [] tempScript;
tempScript = transform.Find ("Camera") GetComponent<DerivedMonoBehaviour> ();
tempScripts[0].blur=1;
tempScripts[1].intensity = 10;
tempScripts[2].CheckPosition ();
In response to your answer, GetType, GetField, and SetValue much slower than just GetComponent and make the purpose of your code unclear. Do not use them unless you have to and in this case you do not have to. In fact, this is one of the reasons I'd recommend C# over Javascript to new programmers. C# is better at making the wrong solution to a problem harder to use and look unwieldy. Javascript is great because in general all features are easier to get to but results in new programmers writing poor code, such as GetComponent<MonoBehaviour>().value
where they should be using GetComponent<ValueMonoBehaviour>().value
.
Answer by Garazbolg · Oct 02, 2015 at 10:45 AM
In C# you got to cast your components to manipulate their attribute.
The previously proposed solution works but reflection is slow. You should try and refactorize your components :
Make parent class for all the components that have a blur attribute, one for intensity attribute, one for those who implements CheckPosition()
And make all these classes derive from an another global class :
public class MyComponents : MonoBehaviour{
}
public class BlurComponent : MyComponents{
public int blur = 0;
}
public class IntensityComponent : MyComponents{
public int intensity = 0;
}
public class CheckComponent : MyComponents{
public void CheckPosition(){
//Your code here
}
}
And then in your function :
MyComponents tempScripts = transform.Find ("Camera").GetComponents(MyComponents);
((BlurComponent) tempScripts[0]).blur=1;
((IntensityComponent)tempScripts[1]).intensity = 10;
((CheckComponent)tempScripts[2]).CheckPosition ();
Your answer
Follow this Question
Related Questions
c# array size doesn't grow past 10 (bracket initialization) 2 Answers
C# array not behaving as expected 0 Answers
IndexOutOfRangeException help on debug 3 Answers
Help converting this to C# - a few issues 3 Answers
how can i check if index exists? 2 Answers