![](/img/trans.png)
[英]Call a IEnumerator method from another script in Unity and get its return value
[英]How do I get a value from another script in Unity (with an IEnumerator)?
我想从不同的脚本中获取脚本中的值。 我有两个脚本:
public class CargarDatos : MonoBehaviour
{
public string[] fechas;
public string dia;
IEnumerator Start()
{
UnityWebRequest www = UnityWebRequest.Get("http://localhost/Linx/Fechas.php");
yield return www.SendWebRequest();
string fechasDatos = www.downloadHandler.text;
print(fechasDatos);
fechas = fechasDatos.Split(';');
dia = GetValorDatos(fechas[0], "Dia:");
//print(dia);
}
string GetValorDatos(string datos, string index)
{
string valor = datos.Substring(datos.IndexOf(index)+index.Length);
if(valor.Contains("|"))
{
valor = valor.Remove(valor.IndexOf("|"));
}
return valor;
}
}
在这里,如图所示,建立到数据库的连接并获取一个值 (dia)。 此脚本附加到主摄像机,因为我只希望它在游戏开始时连接。 在这里,function print(dia) 返回了正确的值,所以这个脚本有效。
问题是当我尝试获取此脚本中的值时:
public class BarraExperiencia : MonoBehaviour
{
void Start()
{
print(GameObject.Find("Main Camera").GetComponent<CargarDatos>().dia);
}
}
此脚本附加到 slider,我尝试打印它以查看它是否有效,但它不打印任何内容。 我做错了什么? 谢谢。
问题很可能是 BarraExperiencia 上的 Start 方法调用过早。
在这种情况下,您应该使用回调过程或事件。 有很多方法可以做到这一点,这是一种无需过多更改现有代码的方法。
我们首先需要修改 CargarDatos,我只保留相关部分,所以您需要保留所有其他成员和方法。
public class CargarDatos : MonoBehaviour
{
public event Action<string> RaiseDataComplete;
IEnumerator Start()
{
UnityWebRequest www = UnityWebRequest.Get("http://localhost/Linx/Fechas.php");
yield return www.SendWebRequest();
string fechasDatos = www.downloadHandler.text;
fechas = fechasDatos.Split(';');
dia = GetValorDatos(fechas[0], "Dia:");
RaiseDataComplete?.Invoke(dia);
}
}
这是另一个脚本:
public class BarraExperiencia : MonoBehaviour
{
void Start()
{
GameObject.Find("Main Camera").GetComponent<CargarDatos>().RaiseDataComplete += OnComplete;
}
void OnComplete(string data){ print(data); }
}
第二个脚本找到 CargarDatos 并为该事件分配一个侦听器。 当数据加载到 CargarDatos 时,它将通知任何将数据作为参数传递的侦听器。
编辑:如果需要更多数据,
创建一个容器类型来传递所有需要的数据
公共class存储{公共字符串直径{get; 私人套装; } 公共字符串 其他{ 获取; 私人套装; } 公共 int SomeValue{get; 私人套装; } 公共存储(字符串直径,字符串其他,int值){直径=直径; 其他=其他; SomeValue = 价值; } }
然后修改事件:
public event Action<Storage>RaiseDataComplete;
并通过新的 object:
RaiseDataComplete?.Invoke(new Storage(dia, "other string", 123));
然后监听器获取新的方法签名
void OnComplete(Storage data)
{
print($"{data.Dia} {data.Other} {data.SomeValue}");
}
最后,您可以将 CargarDatos 中的所有成员设为私有,外部需要的任何内容都通过事件传递。
我认为您正试图在协程完成之前获得“直径”值。 仅在协程完成后尝试打印该值。
此外,使用FindObjectOfType获取组件会更快。
该值尚不可用。 我强烈建议您不要使用公共变量,而是将对值的访问封装在一个属性中,例如:
private string dia = null;
public string Dia {
get {
if(dia != null) {
return dia;
}
UnityWebRequest www = UnityWebRequest.Get ("http://localhost/Linx/Fechas.php");
yield return www.SendWebRequest ();
string fechasDatos = www.downloadHandler.text;
print (fechasDatos);
fechas = fechasDatos.Split (';');
dia = GetValorDatos (fechas[0], "Dia:");
}
}
已更新请查看以下针对您的场景的示例架构。 由于 Unity UnityWebRequest
的异步性质,我们不能像我最初建议的那样将 yield 封装在属性中。
在下面,我们调用我们的服务并传入一个Action<User>
类型的回调以在服务完成时运行。 这个回调现在可以从你的消费组件中做任何需要的事情——在这个例子中,我们更新了一个Text
组件。
您可以将这些复制并粘贴到您的项目中,它们将从 Github 返回示例数据。
我的服务.cs
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
namespace MyCompany.MyGame {
public class User {
public string login;
}
public class MyService {
public IEnumerator GetUser (Action<User> callback) {
using (UnityWebRequest webRequest = UnityWebRequest.Get ("https://api.github.com/users/octocat")) {
yield return webRequest.SendWebRequest ();
callback (JsonUtility.FromJson<User> (webRequest.downloadHandler.text));
}
}
}
}
入口.cs
using UnityEngine;
using UnityEngine.UI;
namespace MyCompany.MyGame {
public class Entry : MonoBehaviour {
MyService myService;
[SerializeField]
Text playerName;
void Awake () {
myService = new MyService ();
}
void Start () {
StartCoroutine (myService.GetUser ((User result) => {
Debug.Log (result);
playerName.text = result.login;
}));
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.