我使用Unity 5在C#中创建了一个协程,我想传递一个对它的引用。它似乎没有用,所以我制作了一个测试脚本,试图找出以下错误
error CS1623: Iterators cannot have ref or out parameters
这是测试脚本:
using UnityEngine;
using System.Collections;
public class TEMP : MonoBehaviour {
// Use this for initialization
void Start () {
float var = 3.141f;
StartCoroutine ( test (ref var) );
}
IEnumerator test (ref float value) {
for (int i = 1; i <= 10; i++) {
Debug.Log (value);
yield return null;
}
}
}
另外,在我的实际脚本中,我使用Unity的WWW类下载了一些东西,当我通过www.progress作为参考时,我也收到了这个错误:
A property or indexer 'UnityEngine.WWW.progress' may not be passed as 'ref' or 'out' parameter
答案 0 :(得分:1)
从函数参数中删除ref。
// Use this for initialization
void Start () {
float var = 3.141f;
StartCoroutine ( test (var) );
}
IEnumerator test (float value) {
for (int i = 1; i <= 10; i++) {
Debug.Log (value);
yield return null;
}
}
根据您的要求,您可以使用out参数执行类似下面的操作。我不确定你打算如何使用这些方法,但我认为你对ref参数及其工作方式有错误的想法。
class Program
{
static void Main(string[] args)
{
float var = 3.14f;
StartCoroutine(test(var), out var);
}
static IEnumerator test(float value)
{
for (int i = 1; i <= 10; i++)
{
Console.WriteLine(value);
yield return value + 1;
}
}
static void StartCoroutine(IEnumerator test, out float update)
{
update = 0;
while (test.MoveNext())
{
update++;
Console.WriteLine("Executing..." + update);
}
}
}
但是,您永远无法将ref或out参数传递给交互器。
答案 1 :(得分:0)
考虑一下
IEnumerator test (float value)
{
for (int i = 1; i <= 10; i++)
{
Debug.Log(value);
yield return null;
}
}
语法糖类似于:
private class Iterator : IEnumerable<object>, IEnumerator<object>
{
private int _state;
private int _threadId = Environment.CurrentManagedThreadId;
private object _current;
private float _value;
int i;
public Iterator(float value)
{
_value = value;
}
public object Current
{
get { return _current; }
}
object IEnumerator.Current
{
get { return _current; }
}
public IEnumerator<object> GetEnumerator()
{
// If we're on the same thread and its the first call, reuse this object as the enumerator
// otherwise create a fresh one for new call (so we don't have buggy overlaps) or a different
// thread (to avoid a race on that first call).
Iterator iter = _state == 0 && _threadId == Environment.CurrentManagedThreadId ? this : new Iterator(_value);
iter._state = 1;
return iter;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public bool MoveNext()
{
switch(_state)
{
case 1:
i = 1;
_state = 2;
goto case 2;
case 2:
if (i <= 10)
{
Debug.Log(_value);
_current = null;
++i;
return true;
}
_state = -1;
break;
}
return false;
}
public void Dispose()
{
}
public void Reset()
{
throw new NotSupportedException();
}
}
private IEnumerator test(float value)
{
return new Iterator(value);
}
现在,请考虑您的float
参数已成为实施中的float
字段。由于您不能拥有ref
字段,因此无法将其视为ref
参数的语法糖。
因此,您的方法不仅不起作用(C#不会为yield
取消大量编码而为您执行此操作)但无法正常工作。
你需要以某种方式对float进行封装,无论你是保持对同一个float的object
引用,还是迭代器可以更新引用类型,或者类似的类型框:
private class TypedBox<T> where T : struct
{
public T Value { get; set; }
public TypedBox(T value)
{
Value = value;
}
}
这又允许您通过引用类型访问该值,但不需要转换成本。
更常见的是,根据传入的任何值迭代值会更有用。