unity笔记--协程StartCoroutine和yield return

StartCoroutine就是开启一个协程.
yield return 保存函数状态,迭代器块返回调用迭代的地方。等待下次调用继续从当前位置处理。

协程

  • 可以使用 StopCoroutineStopAllCoroutines 来停止协程。 当用 SetActive(false) 禁用某个协程所附加到的游戏对象时,该协程也将停止。调用 Destroy(example)(其中 example 是一个 MonoBehaviour 实例)会立即触发 OnDisable,并会处理协程,从而有效地停止协程。最后,在帧的末尾调用 OnDestroy
  • 通过在 MonoBehaviour 实例上将 enabled 设置为 false 来禁用 MonoBehaviour 时,协程不会停止。

  调用函数时,函数将运行到完成状态,然后返回。这实际上意味着在函数中发生的任何动作都必须在单帧更新内发生;函数调用不能用于包含程序性动画或随时间推移的一系列事件。例如,假设需要逐渐减少对象的 Alpha(不透明度)值,直至对象变得完全不可见。

  协程就像一个函数,能够暂停执行并将控制权返还给 Unity,然后在下一帧继续执行。在 C# 中,声明协程的方式如下:

IEnumerator Fade() 
{
    for (float ft = 1f; ft >= 0; ft -= 0.1f) 
    {
        Color c = renderer.material.color;
        c.a = ft;
        renderer.material.color = c;
        yield return null;
    }
}

  此协程本质上是一个用返回类型 IEnumerator 声明的函数,并在主体中的某个位置包含 yield return 语句。yield return null 行是暂停执行并随后在下一帧恢复的点。要将协程设置为运行状态,必须使用 StartCoroutine 函数:

void Update()
{
    if (Input.GetKeyDown("f")) 
    {
        StartCoroutine("Fade");
    }
}

  您会注意到 Fade 函数中的循环计数器能够在协程的生命周期内保持正确值。实际上,在 yield 语句之间可以正确保留任何变量或参数。

  默认情况下,协程将在执行 yield 后的帧上恢复,但也可以使用 WaitForSeconds 来引入时间延迟

IEnumerator Fade() 
{
    for (float ft = 1f; ft >= 0; ft -= 0.1f) 
    {
        Color c = renderer.material.color;
        c.a = ft;
        renderer.material.color = c;
        yield return new WaitForSeconds(.1f);
    }
}

  在附近有敌人时向玩家发出的警报,每十分之一秒调用一次:

IEnumerator DoCheck() 
{
    for(;;) 
    {
        ProximityCheck();
        yield return new WaitForSeconds(.1f);
    }
}

function ProximityCheck() 
{
    for (int i = 0; i < enemies.Length; i++)
    {
        if (Vector3.Distance(transform.position, enemies[i].transform.position) < dangerDistance) {
                return true;
        }
    }
    
    return false;
}

yield

  如果你在语句中使用 yield 上下文关键字,则意味着有它出现的方法、运算符或 get 访问器是迭代器。

  在为自定义集合类型实现IEnumerable和IEnumerator模式时,使用yield定义迭代器就不需要显式的额外类(包含枚举状态的类,请参阅IEnumerator )。

yield return <expression>;
yield break;

yield return的值

  一个协程的执行可以在任何地方用yield语句来暂停,yield return的值决定了什么时候协程恢复执行。

yield return的值含义
yield return null;暂停协同程序,下一帧再继续往下执行
yield new WaitForFixedUpdate ();暂停协同程序,等到下一次调用FixedUpdate方法时再继续往下执行
yield return new WaitForSeconds(2);暂停协同程序,2秒之后再继续往下执行
yield return StartCoroutine(“SomeCortoutineMethod”);暂停此协同程序,开启SomeCortoutineMethod协同程序,直到SomeCortoutineMethod执行完再继续往下执行。SomeCortoutineMethod用yield暂停不算执行完。
### 如何在 Unity 中使用数字孪生技术实现 GPS 定位功能 为了实现在Unity中的GPS定位功能,特别是结合数字孪生技术的应用场景下,需考虑几个关键技术点: #### 数据同步与转换 由于ROS的坐标系是右手坐标系,而Unity采用的是左手坐标系,在编写接收位置并使模型随之移动的脚本时,需要将两者之间的坐标系进行转换以正确模拟机器人运动轨迹[^1]。具体来说,可以通过调整Z轴的方向来完成这一变换。 #### 地理信息系统(GIS)集成 Cesium是一个非常适合带有GIS项目的工具,它能够很好地处理大型城市或园区级别的项目,并且支持北斗、GPS等定位系统的无缝对接[^2]。因此,如果计划开发具有高精度地理信息展示需求的应用程序,则可以考虑引入Cesium插件至Unity环境中,以便更好地呈现真实世界的地理位置信息并与虚拟物体互动。 #### 实现方案概述 要创建一个基于数字孪生概念下的GPS定位应用,建议按照如下方式操作: - **数据源接入**:确保可以从外部设备(如安装有GPS模块的小型无人车或其他物联网装置)获取实时经纬度数据流; - **坐标转换逻辑设计**:依据所选平台特性(例如上述提到的不同坐标体系差异),制定相应的算法用于解析接收到的信息并将之适配给目标环境内的对象显示; - **可视化表达**:借助于第三方库或者自定义Shader等方式增强最终效果的真实感表现力; 下面给出一段简单的代码片段用来说明如何读取来自串口连接设备传来的NMEA格式字符串形式的GPS信号并在Unity内部更新对应GameObject的位置属性: ```csharp using UnityEngine; using System.IO.Ports; public class GPSTracker : MonoBehaviour { private SerialPort _serialPort; void Start() { string portName = "COM3"; // Replace with your actual COM Port name. int baudRate = 9600; try{ _serialPort = new SerialPort(portName, baudRate); _serialPort.Open(); StartCoroutine(ProcessIncomingData()); } catch (Exception e){ Debug.LogError($"Failed to open serial port {portName}: {e.Message}"); } } IEnumerator ProcessIncomingData(){ while (_serialPort.IsOpen && Application.isPlaying){ yield return null; if(_serialPort.BytesToRead > 0){ var line = _serialPort.ReadLine(); ParseGPGGA(line); } } } void ParseGPGGA(string gpggaSentence){ // Implement parsing logic here according to NMEA standard. float latitude = ... ; float longitude = ... ; transform.position = ConvertGeoToLocal(latitude, longitude); } Vector3 ConvertGeoToLocal(float lat, float lon){ // Conversion from geographic coordinates to local space, // considering the difference between ROS/real-world coordinate systems and Unity's one. double earthRadiusInMeters = 6378137.0d; double latRad = Mathf.Deg2Rad * lat; double lonRad = Mathf.Deg2Rad * lon; double x = earthRadiusInMeters * Mathf.Cos((float)latRad) * Mathf.Sin((float)lonRad); double z = earthRadiusInMeters * Mathf.Sin((float)latRad); // Assuming origin point is set at some known location on map. const double OriginLatitude = 0.0f; const double OriginLongitude = 0.0f; // Calculate offset relative to this origin... // Note that we flip Y axis because of different handedness conventions mentioned earlier. return new Vector3( -(float)(earthRadiusInMeters * Mathf.Cos(Mathf.Deg2Rad * OriginLatitude) * (Mathf.Sin(lonRad) - Mathf.Sin(Mathf.Deg2Rad * OriginLongitude))), 0F, (float)((earthRadiusInMeters*(Mathf.Sin(latRad)-Mathf.Sin(Mathf.Deg2Rad*OriginLatitude)))) ); } } ``` 此段代码展示了基本框架,实际部署过程中可能还需要针对特定硬件做出适当修改优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值