代码之家  ›  专栏  ›  技术社区  ›  bjy0212

协同程序运行时Unity游戏停止

  •  1
  • bjy0212  · 技术社区  · 2 年前

    Unity(当前游戏场景中的角色移动和所有内容)在从web url下载纹理时停止。 我正在使用 Socket.IO 用于在线多人游戏。

    1. 使用套接字请求“地图信息”。在中发射 void Start()
    2. 获取“地图信息”并使用创建地图实体 Instantiate()
    3. 从url获取纵断面图像(纹理)并更改贴图实体的纹理
    IEnumerator DownloadImage(string MediaUrl, SpriteRenderer spr) {
        // check if url is malformed
        if (MediaUrl == null || MediaUrl.Contains("Null")) {
            yield break;
        }
    
        UnityWebRequest request = UnityWebRequestTexture.GetTexture(MediaUrl);
        yield return request.SendWebRequest();
    
        if (request.result == UnityWebRequest.Result.ConnectionError || request.result == UnityWebRequest.Result.DataProcessingError || request.result == UnityWebRequest.Result.ProtocolError)
            Debug.Log(request.error);
        else {
            Texture2D tex = ((DownloadHandlerTexture)request.downloadHandler).texture;
    
            spr.sprite = Sprite.Create(tex, new Rect(0.0f, 0.0f, tex.width, tex.height), new Vector2(0.5f, 0.5f), tex.width / 2f);
        }
    }
    

    在下载纹理时,有没有办法通过用户交互(角色移动或按钮动作)保持游戏运行?

    1 回复  |  直到 2 年前
        1
  •  0
  •   Deleted    2 年前

    Unity co例程(CR)是一种入门级的、有时是危险的工作形式,它在 主统一线程 . 它们对于本质上是逻辑的 lerp 跨越一系列框架,如 衰落,5秒后引爆我的宇宙飞船 推迟驾驶舱显示更新 .

    CR在主线程上被分割和多路复用,因此游戏中最慢的部分将是单帧中时间需求最大的CR。在一次 yield 每帧都会减慢游戏速度,尤其是 输入/输出操作 .

    备选方案-Unity作业

    相反,考虑使用Unity 'IJob' 它允许在工作线程上执行操作,从而释放Unity线程来做它最擅长的事情 输入/输出操作不长 .

    统一性:

    使用IJob调度与其他作业和主线程并行运行的单个作业。调度作业时,将在工作线程上调用作业的Execute方法。 More...

    现在,浪费一个可能花费一生等待I/O完成的整个线程可以说是浪费了一个非常好的线程,但这肯定比阻塞主线程要好。

    协同路由。。。他们是龙

    我之前提到过 “危险” 关于CRs,原因有三个方面:

    1. 在每秒调用多次的方法中触发CR时,例如 Update() 确保你 充分防护 这个 StartCoroutine() 否则,您最终可能会遇到无数的内存不足的情况。这种情况在堆栈溢出时很常见
    2. 不要错误地认为它们是某种工作线程或其他不会减慢主线程速度的魔法
    3. 在许多方面,CRs就像 DoEvents , Application.DoEvents 在里面 Visual Basic .净额 分别导致了一起严重的 重新进入 (就像在多线程应用程序中一样,状态混乱且不可预测 没有螺纹 )

    还有整个 团结促进了对 IEnumerator 产量 ? 辩论

    我的另一个建议是,如果您需要一些lerped或延迟的内容,并且没有进行I/O,请考虑创建一个类并使用 Time .

    例如 in my flight sim ,我只想每100ms左右更新一次驾驶舱显示。为此,我定义了 Delay 类别:

    public class Delay
    {
        private float _lastInterval;
    
        /// <summary>
        ///     The timeout in seconds
        /// </summary>
        /// <param name="timeout"></param>
        private Delay(float timeout)
        {
            Timeout = timeout;
            _lastInterval = Time.time;
        }
    
        public float Timeout { get; }
    
        public bool IsTimedOut => Time.time> _lastInterval + Timeout;
    
        public void Reset()
        {
            _lastInterval = Time.time;
        }
    
        public static Delay StartNew(float delayInSeconds)
        {
            return new Delay(delayInSeconds);
        }
    }
    .
    .
    .
    private void Update()
    {
        if (!_delay.IsTimedOut)
        {
            return;
        }
    
        // Do something time consuming
     
        _delay.Reset();
    }