您现在的位置是:首页 >学无止境 >【Unity研究】进程、线程、对象池的关系网站首页学无止境

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

浮动指针 2024-09-25 12:01:12
简介【Unity研究】进程、线程、对象池的关系

目录

简要概括

名词解释

实例

进程

线程

对象池

实际使用

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

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

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

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


简要概括

正在运行的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()
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。