Unity对象池初识

Unity对象池初了解


前言

例如:随着对游戏设计的深入了解,本文就介绍了unity的对象池的基础内容。


一、对象池是什么?

对象池简单来说就好比一个池子,有一池子空物体,预制体,一开始就实例化这些物体,当我们需要使用时,便从其他将其拿出(SetActive(true)),当用完时,便将其放回池子中(SetActive(false)),以便下次使用。就如打羽毛球,如果我们每次打一个球只打一次便扔掉,然后又打新球,这样就造成了极大浪费,而对象池就是将打过的球放回其中,减少开支消耗。

二、代码实现对象池

——这里以制作冲刺残影为例子进行讲解

1.首先创建一个空物体,以作为我们的第一个预制体来使用对象池

如下图:在这里插入图片描述
并且创建挂载上一个脚本来进行获取玩家的数据坐标图像等:在这里插入图片描述
并且写入代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ShadowsScript : MonoBehaviour
{
    private Transform player;

    private SpriteRenderer thisSprite;
    private SpriteRenderer playerSprite;

    private Color color;//进行透明度调节

    [Header("时间控制参数")]
    public float activeTime;//显示时间
    public float activeStart;//开始显示的时间点

    [Header("不透明度控制")]
    private float alpha;
    public float alphaSet;//初始值
    public float alphaMultiplier;//乘以系数逐渐减小

    private void OnEnable()
    {
        //记得切换unity角色的Player标签
        player = GameObject.FindGameObjectWithTag("Player").transform;
        thisSprite = GetComponent<SpriteRenderer>();
        playerSprite = player.GetComponent<SpriteRenderer>();

        alpha = alphaSet;

        thisSprite.sprite = playerSprite.sprite;

        transform.position = player.position;
        transform.localScale = player.localScale;
        transform.rotation = player.rotation;

        activeStart = Time.time;
    }

    void Update()
    {
        alpha *= alphaMultiplier;

        color = new Color(1, 1, 1, alpha);

        thisSprite.color = color;

        if (Time.time >= activeStart + activeTime)
        {
        	PoolScript.instance.ReturnPool(gameObject);
            //返回对象池(写好对象池后添加)
        }
    }
}

接着回到unity中进行参数设置和制作预制体:
在这里插入图片描述
在这里插入图片描述
预制体中需要加上精灵组件:在这里插入图片描述

2.编写对象池!!!

首先在unity中创建空物体并命名为Pool:
在这里插入图片描述
接着创建脚本,并且命名为PoolScript:
在这里插入图片描述
然后进行编写代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PoolScript : MonoBehaviour
{
    public static PoolScript instance;

    public GameObject shadowPrefab;

    public int shadowCount;

    //创建队列(重点)
    private Queue<GameObject> availableObjects = new Queue<GameObject>();

    void Awake()
    {
        instance = this;

        //初始化对象池
        FillPool();
    }

    public void FillPool()
    {
        for(int i = 0; i < shadowCount; i++)
        {
            var newShadow = Instantiate(shadowPrefab);
            newShadow.transform.SetParent(transform);

            //生成之后,取消启用,返回对象池(进入队列)
            ReturnPool(newShadow);
        }
    }

    public void ReturnPool(GameObject gameObject)
    {
        gameObject.SetActive(false);

        availableObjects.Enqueue(gameObject);
    }

    public GameObject GetFromPool()
    {
        //如果数量不够,则再次进行填充
        if (availableObjects.Count == 0)
        {
            FillPool();
        }
        var outShadow = availableObjects.Dequeue();

        outShadow.SetActive(true);

        return outShadow;
    }
}

接着在unity中进行设置:
在这里插入图片描述

3.编写Dash脚本

using UnityEngine;
public class PlayerController : MonoBehaviour
{
	private float movementInputDirection;
    private Rigidbody2D rb;
    [Header("Dash参数")]
    public float dashTime;//dash时长
    private float dashTimeLeft;//dash剩余时间
    private float lastDash=-10;//上一次dash的时间点,赋初值,确保一开始可冲锋
    public float dashCoolDown;//UIcd时间(暂时未用到)
    public float dashSpeed;
    private bool isDashing;
    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
    }
    void Update()
    {
        CheckInput();
    }
    private void FixedUpdate()
    {
        Dash();
    }
    private void CheckInput()
    {
        movementInputDirection = Input.GetAxisRaw("Horizontal");
        if (Input.GetButtonDown("Jump"))
        {
            if (Time.time >= (lastDash + dashCoolDown))
            {
                isDashing = true;
                dashTimeLeft = dashTime;
                lastDash = Time.time;
            }
        }
    }
   	private void Dash()
    {
        if (isDashing)
        {
            if (dashTimeLeft > 0)
            {
                rb.velocity = new Vector2(dashSpeed * movementInputDirection, rb.velocity.y);
                dashTimeLeft -= Time.fixedDeltaTime;
                PoolScript.instance.GetFromPool(); 
            }
            if (dashTimeLeft <= 0)
            {
                isDashing = false;
            }
        }
    }
}

接着在unity中进行设置:在这里插入图片描述
最后在游戏进行测试:
首先游戏一开始,对象池中便生成了10个对象:在这里插入图片描述
然后进行冲刺测试:
在这里插入图片描述
最后完美成功,此次为使用对象池制作角色冲刺残影的例子了。

总结

在我们开发中,往往会遇见需要不断创建和销毁同一物体的情况。(如飞机大战,许多FPS游戏,三消类游戏等),这时我们系统不断的实例化资源和销毁资源对于内存以及性能的消耗是非常大的。对于这种我们可以使用对象池技术进行优化。效果十分明显。
对象池及时的原理:
适用范围:有大量的物体需要被不断的创建和销毁的时候。
关键点:
从对象池中放入对象。
从对象池中取出对象。
使用何种数据类型来对这些对象进行储存。
关键思想:
相比于Instantiate和Destroy,不断的实例化和销毁,对象池只是对它们实例化出的对象进行激活和失活的处理。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity 中的对象池是一种资源管理技术,用于在游戏运行过程中高效地创建、管理和回收对象。对象池的主要目的是减少频繁创建和销毁对象带来的性能开销,尤其是在有大量短期使用对象(如小敌人、项目等)的情况下。 下面是使用 Unity 对象池的基本步骤: 1. 创建对象池:首先,你需要创建一个包含所需对象类型的新对象池。这通常是一个静态类或专用脚本,负责管理对象的生命周期。 ```csharp public class ObjectPool<T> where T : Component { private List<T> poolObjects; private Stack<T> availableObjects; // 初始化方法 public ObjectPool(int initialSize) { poolObjects = new List<T>(); for (int i = 0; i < initialSize; i++) { T obj = Instantiate<T>(); obj.SetActive(false); // 设置对象为非活动状态,直到需要时才激活 poolObjects.Add(obj); } availableObjects = new Stack<T>(poolObjects); } // 获取对象 public T BorrowObject() { if (availableObjects.Count > 0) { T obj = availableObjects.Pop(); obj.SetActive(true); return obj; } else { T obj = Instantiate<T>(); return obj; } } // 归还对象 public void ReturnObject(T obj) { obj.SetActive(false); availableObjects.Push(obj); } } ``` 2. 使用对象池:当你需要一个新对象时,从池中借用一个,用完后记得归还。这样,当对象不再被使用时,它会被放回池而不是直接销毁,以便后续其他地方可能需要它。 ```csharp private ObjectPool<MyObject> objectPool; void Start() { objectPool = new ObjectPool<MyObject>(10); } void Update() { MyObject newObj = objectPool.BorrowObject(); // 使用 newObj ... newObj.gameObject.SetActive(false); // 当对象不再需要时,归还给池子 // 如果对象池已满,考虑创建更多对象 if (objectPool.availableObjects.Count == 0 && poolSize < MaxPoolSize) { // 添加新对象到池中 objectPool.poolObjects.Add(Instantiate<MyObject>()); } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值