将引用(以及Unity';s WWW.progress)传递给Coroutines/IE分子
本文关键字:Coroutines 分子 IE progress WWW 以及 引用 Unity | 更新日期: 2023-09-27 18:19:57
我已经使用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
从函数参数中删除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参数传递给interator。
考虑
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
参数的语法糖。
因此,您的方法不仅不起作用(由于yield
占用了大量编码,C#不会为您做这件事),而且也不起作用。
您需要以某种方式框住float,无论您持有对同一float的object
引用,该引用类型可以由迭代器更新,还是像这样的类型框
private class TypedBox<T> where T : struct
{
public T Value { get; set; }
public TypedBox(T value)
{
Value = value;
}
}
这再次允许您通过引用类型访问值,但不需要铸造成本。
通常情况下,根据传入的任何值迭代值更有用。