首页 > 其他分享 >【unity】 Loom实现多线程

【unity】 Loom实现多线程

时间:2024-10-23 09:32:54浏览次数:1  
标签:Loom int void param unity 线程 多线程 public


通常情况下,unity中在子线程中改变变量的值,但是子线程尚未结束时,主线程无法使用该变量。

因此使用Loom作为中介,子线程调用并传值给Loom,Loom调用主线程的API。

实现步骤
创建Loom空物体,并挂载Loom脚本

//Loom.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class Loom : MonoBehaviour
{
    static bool isInitialized;

    private static Loom instance;
    public static Loom Instance
    {
        get
        {
            Initialize();
            return instance;
        }
    }

    public static void Initialize()
    {
        if (!isInitialized)
        {
            if (!Application.isPlaying)
                return;
            isInitialized = true;
            var obj = new GameObject("Loom");
            instance = obj.AddComponent<Loom>();

            DontDestroyOnLoad(obj);
        }
    }

    private void Awake()
    {
        instance = this;
        isInitialized = true;
    }

    struct NoDelayQueueItem
    {
        public Action<int> action;
        public int param;
    }

    List<NoDelayQueueItem> listNoDelayActions = new List<NoDelayQueueItem>();

    struct DelayQueueItem
    {
        public Action<int> action;
        public int param;
        public float time;
    }

    List<DelayQueueItem> listDelayedActions = new List<DelayQueueItem>();

    public static void QueueOnMainThread(Action<int> taction, int param)
    {
        QueueOnMainThread(taction, param, 0f);
    }

    public static void QueueOnMainThread(Action<int> action, int param, float time)
    {
        if (time != 0)
        {
            lock (Instance.listDelayedActions)
            {
                Instance.listDelayedActions.Add(new DelayQueueItem { time = Time.time + time, action = action, param = param });
            }
        }
        else
        {
            lock (Instance.listNoDelayActions)
            {
                Instance.listNoDelayActions.Add(new NoDelayQueueItem { action = action, param = param });
            }
        }
    }

    List<NoDelayQueueItem> currentActions = new List<NoDelayQueueItem>();
    List<DelayQueueItem> currentDelayed = new List<DelayQueueItem>();

    private void Update()
    {
        //无延迟的执行队列中存在任务
        if (listNoDelayActions.Count > 0)
        {
            lock (listNoDelayActions)
            {
                //把所有任务放入当前执行队列
                currentActions.Clear();
                currentActions.AddRange(listNoDelayActions);
                listNoDelayActions.Clear();
            }
            //挨个执行完任务
            for (int i = 0; i < currentActions.Count; i++)
            {
                currentActions[i].action(currentActions[i].param);
            }
        }
        //有延迟的执行队列中存在任务
        if (listDelayedActions.Count > 0)
        {
            lock (listDelayedActions)
            {
                //将此刻之前的所有未完成的任务放入当前执行队列
                currentDelayed.Clear();
                currentDelayed.AddRange(listDelayedActions.Where(d => Time.time >= d.time));
                for (int i = 0; i < currentDelayed.Count; i++)
                {
                    listDelayedActions.Remove(currentDelayed[i]);
                }
            }

            for (int i = 0; i < currentDelayed.Count; i++)
            {
                currentDelayed[i].action(currentDelayed[i].param);
            }
        }
    }
    private void OnDisable()
    {
        if (instance == this)
        {
            instance = null;
        }
    }
}

子线程中调用Loom类,Loom中执行主线程API

private void Awake()
{
    button.GetComponent<UnityEngine.UI.Button>().onClick.AddListener(OnPointClick);
    onPositionChangedEvent += onPositionChanged;
    onPositionChanged();
}

public UnityEngine.UI.Button button;

public Action onPositionChangedEvent;

//子线程会改变此变量,此变量发生变化时,会执行委托(主线程API)
private int _position = 10;
public int Position
{
    get { return _position; }
    set
    {
        _position = value;
        if (onPositionChangedEvent != null)
        {
            onPositionChangedEvent();
        }
    }
}

Thread thread = null;
int direct = 1;
// button开启子线程,此线程一直开启
public void OnPointClick()
{
    if (thread == null)
    {
        thread = new Thread(() =>
        {
            while (true)
            {
                if (Position < -100)
                {
                    direct = 1;
                }
                else if (Position > 100)
                {
                    direct = -1;
                }
				//子线程更改的变量,此变量每次发生改变时需要在主线程中使用
                Position += 1 * direct;

                Thread.Sleep(100);
            }
        });
        thread.IsBackground = true;
        thread.Start();
    }

}

//Position发生变化时,就会调用该方法
private void onPositionChanged()
{
    //Loom会在子线程执行,但是可以调用主线程API
    Loom.QueueOnMainThread((Position) =>
    {
        transform.position = new Vector3(Position, 0, 0);
    }, Position);
}

标签:Loom,int,void,param,unity,线程,多线程,public
From: https://www.cnblogs.com/sitarblogs/p/18494467

相关文章

  • selenium单例模式下 docker-chrome 多线程并发代码
    最近需要写爬虫,在解决docker-standalone-chrome发现只能有一个chrome被执行。所以写了这个多线程并发控制类来管理。当模板记录下。#!/usr/bin/envpython3importthreadingimporttracebackfromloguruimportloggerfromseleniumimportwebdriverfromselenium.comm......
  • TriLib2:Unity运行时运行时加载模型
    概述本文基于此版本TriLib2是Unity的一款强大的3D模型运行时导入工具包,可以在游戏运行期间或编辑器中动态加载多种格式的模型,笔者也只是简单使用了从文件路径加载模型一种用法,旨在帮助你快速入门.它支持的格式包括FBX、OBJ、GLTF2、STL、PLY、3MF、DAE和ZIP等,......
  • unity克隆出的游戏对象在超过范围之后不销毁
    源代码:usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;publicclassDestroyOutOfBound:MonoBehaviour{//StartiscalledbeforethefirstframeupdateprivatefloattopBound=40;privatefloatlowerBound=-4......
  • Unity Shader深度图的应用,手把手教你写出可以正确计算并且渲染出二次元角色边缘光的着
    梦开始的地方相信大家看番的时候,都注意到了,很多时候,在角色周围有一圈光晕旧版《魔术快斗》剧照《新蔷薇少女》剧照 我们将这种光晕,称之为边缘光边缘光是描边的一种,动画师之所以加入边缘光,是为了凸现角色轮廓,使得角色区别于背景不少游戏也有着这种边缘光游戏《鸣潮》......
  • 11-案例:多线程版用户聊天程序
    1.多线程版用户群聊程序的_多用户聊天运行结果2.多线程版用户群聊程序的_服务端代码3.多线程版用户群聊程序的_客户端代码4.多线程版用户群聊程序的_双用户聊天运行结果5.多线程版用户群聊程序的_双用户聊天运行服务端代码6.多线程版用户群聊程序的_双用户聊天运行客户端代码......
  • 升级Unity后产生的Objects内存泄露现象
    1)升级Unity后产生的Objects内存泄露现象2)能否使用OnDemandRenderingAPI来显示帧率3)Unity闪退问题4)配置表堆内存如何优化这是第405篇UWA技术知识分享的推送,精选了UWA社区的热门话题,涵盖了UWA问答、社区帖子等技术知识点,助力大家更全面地掌握和学习。UWA社区主页:community.uwa4d......
  • 【Linux线程】Linux多线程实践:深入生产者消费者模型
    ......
  • Unity 切换UI坐标和世界坐标
    usingUnityEngine;//这个脚本实现了,本脚本所在的游戏物体能够被拖拽publicclassDragObjectT:MonoBehaviour{privateVector3screenPoint;//存储物体在屏幕上的位置privateVector3offset;//存储鼠标点击位置与物体实际位置的偏移量privatebool......
  • 【JavaEE】【多线程】单例模式
    目录一、设计模式1.1单例模式1.1.1饿汉模式1.1.2懒汉模式1.2线程安全问题1.3懒汉模式线程安全问题的解决方法1.3.1原子性问题解决1.3.2解决效率问题1.3.3解决内存可见性问题和指令重排序问题一、设计模式在讲解案例前,先介绍一个概念设计模式:就是大佬们......
  • Jenkins打包Unity游戏环境变量配置
    Jenkins打包Unity游戏失败,通过报错日志会查找到sdk环境有问题,解决sdk的环境问题后会出现ndk环境有问题,为了解决这两个问题导致的打包失败需要在Jenkins中配置环境变量打开Jenkins首页,选中ManagerJenkins,再点击System选项找到全局属性,勾选Environmentvariables选项点击......