- Home /
How to use struct-variable as return-value
With Unity-JavaScript, I builded a struct-variable like this:
class axesvar extends System.ValueType{
var X : float;
var Y : float;
var Z : float;
var no : int;
}
private var regaxes : axesvar;
...so the selfmade variable is called regaxes and the new type is axesvar. When I declare a function now, I get a compiler-error in unity:
BCE0101: Return type 'axesvar' cannot be used on a generator. Did you mean 'IEnumerator'? You can also use 'System.Collections.IEnumerable' or 'object'.
The function was declared like this:
function funcname (inputvar : axesvar) : axesvar {}
What does the error-message mean? How do I correct the error?
I looked around a bit and found out a view things:
-ins$$anonymous$$d of struct some people seem to use classes. That seems to be the same attempt they are doing in above posted link. However, I don't undertand what the function inside the class is for, as well as all the other stuff they diskuss in that post.
-here, someone suggests usage of selfmade objects ins$$anonymous$$d of structs.
Both (or all three) attempts don't seem to work as variable-types. I can't use them as return-type in functions.
$$anonymous$$y knowledge of classes and objects is pretty limited. Is there some way to make real custom variable-types possible nevertheless?
This didn't work too:
var axesvar = new Object();
axesvar.X = new float();
axesvar.X = new float();
axesvar.Z = new float();
axesvar.intno = new int();
var somevariable : axesvar;
The compiler-output is:
"BCE0018: The name 'axesvar' does not denote a valid type ('not found')."
I'm sorry. $$anonymous$$y previous answer probably made this more complicated than it had to be.
A custom class is declared like so-
class axesvar {
var x : float;
var y : float;
var z : float;
var intno : int;
}
Then, just use it like you would use any other class. Be aware that you will need to assign values to all of the items in the object!
Just out of interest, how are you planning to use the function that is giving you these compile errors? It's possible that you can just reword it so that the compiler doesn't have a problem with it.
Sorry, I don't get it. It's a class and it also is an object? How is this example different than the one in the question? I used capital letters for x,y and z, since they are reserved keywords. There should be no problem with na$$anonymous$$g anymore. What does the error-message mean?..."Return type 'axesvar' cannot be used on a generator". What the hell is a generator?
x y and z aren't reserved keywords. In any case, the object and the class are two different things- the class defines what an object will look like, and an object of a given class will have the attributes defined in that class.
A generator is a function that returns a complete, 'generated' object. I really don't understand why the compiler has a problem with this kind of thing- it's a pretty straightforward process! I'm afraid it's a problem I've never come across, since I don't do much JS coding. What I don't undestand, is why it thinks you are trying to use that function like a Coroutine. Are you calling it from a 'StartCoroutine' function somewhere?
You neglected to mention that you were using coroutines...... You must return an IEnumerator because that's how the yield statement works in .Net. yield return IEnumerator;
creates a function that returns multiple times. Its also used to iterate through generic collections. And, same as in C#, you can't return a value (or a reference) in a yield function because that's not their intended design.
Its designed to let you loop through an array getting all the values. If you were to spit out other return values, you would mess a lot of things up.
Answer by syclamoth · Jan 09, 2012 at 11:55 AM
Well, from the looks of things we've gotten to the bottom of this one.
Basically, you can't have a function that is to be used in a Coroutine return a value that isn't an IEnumerator. The reasons for this are a little opaque in JavaScript- because the compiler automatically adds in all the things about Coroutines that make them obviously different from other functions (for example, the 'StartCoroutine' command and the requirement for the coroutines to return type 'IEnumerator'), it's not immediately obvious why you can't do this.
Written out fully, a coroutine-running setup looks like this-
function WaitForSomething() : IEnumerator { yield WaitForSeconds(5); Debug.Log("I waited, now what?"); }
function Start() { StartCoroutine(WaitForSomething()); }
As you can see, the function to be run as a coroutine returns an 'IEnumerator'- this allows the function to be 'paused' and 'restarted' at the yield statements. The StartCoroutine part cannot take a return value, because it is almost guaranteed not to finish within the same frame that it was started- and so would cause a massive hang if it were run then. The entire point, remember, of making it a Coroutine, is so that the rest of the program can get on with whatever it is doing while the coroutine executes!
As for your other question about the 'imprecise' wait time- the reason why 'WaitForSeconds' isn't exact is because it still only gets polled once per frame- there's no way of telling it to execute at an exact moment, because it doesn't get any say in when there will be time available on the processor. You'd need to use true multithreading as well as an external timing library to achieve that.
I should mention that this confusion is completely nonexistent in the C# implementation of these functions- because the correct syntax is required, it is immediately obvious why what you are trying to do can never work.
I begin to understand...the problem seems to be caused by UnityScript adding invisible StartCoroutine-Blocks around usual functions, when WaitforSeconds is used inside them. Did I get that right? When a function is holding a WaitForSeconds-call it is "infected" and can't return anything else than IEnumerator because of this!
As pointed out in the other threat meanwhile, the framrate is not the reason for the delays. The measured time in worst case would be waitingtime + 0.042 seconds. And no, it is not almost guaranteed, a called yield-function won't return within the same frame.
It seems for my fast function I indeed need a coroutine, running always in background and producing values (maybe storing in some global variable). The main-script then has to catch these values when needed during its slower 24frames-per-second-execution. Did you mean something like this with multithreading? What kind of external ti$$anonymous$$g-libraries you mentioned do exist? I just realize this all belongs to the other threat. Please post there for answers.
According to this threat, I just assume classes can be used ins$$anonymous$$d of structs - even though I still don't get why they used System.ValueType rather than a usual class to simulate structs in the other threat.
class axesvar extends System.ValueType{
However, this question seems to be ansered now.
In your case, a struct would appear to make sense. $$anonymous$$ost of the time, they can be used relatively interchangeably as far as functionality is concerned, but they are managed in memory differently.
A struct contains all the data inside of it. When you try to access a struct, you are directly accessing its memory. When you pass it into a function, you are passing a copy of the struct to the function. Changes made to the copy won't have any effect on the original. This is called passing a value by value. You can modify the original if you add a ref
keyword. Then changes inside the function will affect the actual variable This is referred to as passing a value by reference.
When you create a class, you are creating a reference type. When you create a new variable for a class, you are really creating a reference to it. Then when you access the object itself, you go to the memory address that the reference is pointing to access the object.
This let's you create large objects then pass them to functions easily. If you have a large object, you don't want to make a copy of it when you pass it to a function, it'd take up too much space on the heap, ins$$anonymous$$d, you pass a reference to the object which only takes up about the size of an int. This is called passing a reference by value. Changes you make to the object itself will affect the original object, but if you point the pointer at a different object, then the changes won't carry over (ex. calling new ()
)
Or you can pass a reference by reference. That means that if you direct the reference at a different object, then the original pointer will also change what its referencing and the old object will go out of scope and hopefully get garbage collected.
Your answer
![](https://koobas.hobune.stream/wayback/20220613062753im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Function Parameter, array / random type 1 Answer
Help with UnityException Error 1 Answer
Problem with increasing a variable 1 Answer