【Unity研究】进程、线程、对象池的关系

文章介绍了Unity游戏开发中进程和线程的概念,一个进程可包含多个线程,Unity的更新默认在主线程执行。对象池用于优化内存管理,减少对象的频繁创建和销毁。文章还提供了对象池的实现代码示例,并讨论了如何在Unity中创建额外线程以及线程与主线程的生命周期。
摘要由CSDN通过智能技术生成

目录

简要概括

名词解释

实例

进程

线程

对象池

实际使用

对象池实际操作(含代码)

建立主线程以外的线程方法

在主线程中运行的生命周期

在副线程中运行的生命周期


简要概括

正在运行的Unity游戏就可以看做一个进程的实例,线程是进程内的执行单元(一个进程可以拥有多个线程),Unity游戏中的详细操作是在同一个进程里的中执行的。

名词解释

实例

“实例”指具体的实际存在的单个对象或者事物。在计算机中,进程就是程序的实例,也就是指程序在某个时间段内的运行过程。

进程

进程(Process)是计算机中正在运行的一个程序或任务的实例。在操作系统中,进程是资源分配的基本单位,每个进程都拥有自己独立的内存空间和系统资源,包括CPU、内存、文件、网络连接等。进程的出现是为了解决多道程序同时运行的冲突问题,通过将系统资源分配给多个进程,提高了计算机系统的效率和可用性。

每个进程都有自己的地址空间,包括代码段、数据段、堆和栈。堆和栈是两种不同的内存分配方式,堆用于动态分配内存,而栈则用于管理函数调用和变量分配。进程之间是相互独立的,可以并行运行,并且通过IPC和共享内存等方式进行通信和数据交换。

操作系统通过进程调度算法决定何时和如何切换进程,以保证每个进程都能得到足够的运行时间和系统资源,并且根据进程的优先级和状态等进行调度。进程的状态通常包括运行态、就绪态、等待态和终止态等。操作系统通过进程管理来保证系统的稳定性和安全性,防止进程之间的冲突和竞争,提高了计算机系统的效率和可靠性。

线程

线程是进程内的执行单元,一个进程可以拥有多个线程,每个线程都是独立的执行流。在Unity的代码中,update是在主线程中被执行的,不是在单独的线程中,而销毁物品等操作也是在主线程中执行的。

对象池

为了减少线程压力而创造的方法。

实际使用

对象池实际操作(含代码)

简单来说,对象池就是个含有list的类,而list也就是所谓的对象池的“池子”。

将需要操作的物品放在list中,然后隐藏。

需要使用对象的时候从对象池拿出对象,也就是显示物品。

不需要的时候放回,也就是隐藏物品。

彻底不需要时销毁(destroy),释放内存,并将对象从池子中移除。

对象池:

public class EnemyPool
{
    private List<GameObject> enemyPool;
    private GameObject enemyPrefab;
    private int poolSize;

//创建对象池;更新对象池对象
    public EnemyPool(GameObject prefab, int size)
    {
        enemyPrefab = prefab;
        poolSize = size;
        enemyPool = new List<GameObject> ();

        for (int i = 0; i < poolSize; i++) {
            GameObject enemy = GameObject.Instantiate(enemyPrefab) as GameObject;
            enemy.SetActive(false);
            enemyPool.Add(enemy);
        }
    }
//从对象池中拿出对象
    public GameObject GetEnemy()
    {
        foreach (GameObject enemy in enemyPool) {
            if (!enemy.activeInHierarchy) {
                enemy.SetActive(true);
                return enemy;
            }
        }

        GameObject newEnemy = GameObject.Instantiate(enemyPrefab) as GameObject;
        newEnemy.SetActive(true);
        enemyPool.Add(newEnemy);

        return newEnemy;
    }
//放回对象
    public void ReleaseEnemy(GameObject enemy)
    {
        enemy.SetActive(false);
    }
}

实际使用:

public class GameManager : MonoBehaviour
{
    public GameObject enemyPrefab;
    public int enemyPoolSize;

    private EnemyPool enemyPool;

    private void Start ()
    {
        enemyPool = new EnemyPool(enemyPrefab, enemyPoolSize);
    }

    private void Update () 
    {
        //从对象池中获取敌人对象
        GameObject enemy = enemyPool.GetEnemy();

        //对敌人对象进行操作
        enemy.transform.position += Vector3.forward * Time.deltaTime;

        //将敌人对象放回对象池中
        enemyPool.ReleaseEnemy(enemy);
    }
}

为什么要用对象池?

对象池可以使应用程序更高效地利用有限的线程资源,相比起“在编辑器里就把所有物品放到场景中”和“在游戏开始时实例化所有物品(这个方法会让游戏卡顿)”,对象池能动态操控物品的出现和隐藏。

线程效率受内存限制,而物体的实例化、销毁、隐藏显示都在线程中进行,为了节省资源,我们要尽量减少一次性的操作数量。

使用对象池,需要考虑的东西:物品创建和销毁的时机

物品创建时机:可以在游戏加载时一次性创建所有需要的物品对象,或者等到玩家进入游戏世界后,根据需要动态创建。

物品销毁时机:当物品离开玩家的视野范围时,可以将其销毁,或者等到玩家不再需要该物品时再销毁。

对象池的大小:需要考虑在游戏中最大需要创建的物品数量,确定对象池的大小。对象池的大小应该不要过小,否则可能会频繁地创建和销毁物品对象,造成性能损失。(不过用list就不用考虑这一点了,使用数组才需要考虑,用list只需要在不需要物品时及时把物品移出对象池)

对象池的回收和重复利用:一旦物品被销毁,其所占用的资源应该被释放,并将该物品对象重新放回对象池中,以便下次重复利用。

建立主线程以外的线程方法

1.Thread类

示例:

using System;
using System.Threading;

public class Program
{
    static void Main(string[] args)
    {
        // 创建一个新线程
        Thread newThread = new Thread(Compute);

        // 启动线程
        newThread.Start();

        // 在主线程中执行一些其他操作
        for (int i = 0; i < 10; i++)
        {
            Console.WriteLine("Main thread is running.");
            Thread.Sleep(100);
        }
    }

    static void Compute()
    {
        // 在新线程中执行一些计算密集型的操作
        for (int i = 0; i < 10; i++)
        {
            Console.WriteLine("New thread is running.");
            Thread.Sleep(100);
        }
    }
}

2.异步

3.协程(Coroutine类)

4.Job System

Job System是Unity自带的,可以使游戏逻辑转移到多线程中执行。使用Job、JobHandle和JobQueue等组件来管理和调度任务。

5.Entity Component System (ECS)

ECS是Unity中的一种数据驱动的编程模式,可以将游戏逻辑从主线程转移到其他线程中执行,并行处理大量数据。

6.Native Plugin

使用Native Plugin可以在C++或其他编程语言中编写独立于Unity的多线程代码,然后将其集成到Unity中。使用该方法可以获得更高的性能和更灵活的控制。

在主线程中运行的生命周期

  1. Awake()
  2. Start()
  3. Update()
  4. FixedUpdate()
  5. LateUpdate()
  6. OnGUI()
  7. OnDisable()
  8. OnEnable()
  9. OnDestroy()

在副线程中运行的生命周期

  1. OnApplicationFocus()
  2. OnApplicationPause()
  3. OnApplicationQuit()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值