zoukankan      html  css  js  c++  java
  • Unity3D 对象池思想 在游戏开发中的运用

    分类:U3D

    1.在王者荣耀中,每30秒小兵会出现一波,出现之后会被敌方玩家或敌方小兵销毁,一局游戏下来,小兵会被创建多次,同时也会被销毁,在游戏中,这种频繁的创建和销毁游戏对象是很损耗性能的。在游戏开发过程中,我们会频繁的创建对象和销毁对象,为了提高游戏性能,我们就要用到对象池思想了。

    2.在射击游戏中,会频繁的销毁和创建子弹,这就可以用对象池思想了。

    什么是对象池?

    池,想到了水池,水池是水的集合。所以,对象池就是对象的集合,我们可以初步的按照这种想法来理解对象池。使用原理的话就是,我们在创建游戏对象时,我们就从对象池里取出来,并设置为可见(Obj.seAactive(true)),要销毁对象时又把对象放到对象池里再隐藏(Obj.setActive(false)),以备下次需要从对象池中取对象时使用。

    接下来就来看实现过程。

    先来说说要实现的效果,我们单机屏幕上的任意一点,然后就可以发射一个子弹(球),并利用对象池对子弹进行存储,达到优化性能的目标;

    首先创建一个脚本,这个脚本不用继承自Mono,并且用单例模式实现。

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class GameObjectManage
    {
        private List<GameObject> gameobjectlist;   // 保存对象的集合
        // 不再累述单例模式
        private GameObjectManage()
        {
            gameobjectlist=new List<GameObject>();
        }
    
        private static  GameObjectManage instance;
    
        public static GameObjectManage GetInstance
        {
            get
            {
                if (instance == null )
                {
                    instance=new GameObjectManage();
                }
                return instance;
            }
        }
        // 创建子弹的方法
        public GameObject Instance_obj(GameObject obj)
        {
            GameObject result;
            if (gameobjectlist.Count > 0)    // 假如集合不为空,就从集合中取出对象
            {
                result = gameobjectlist[0];   // 获得集合中的第一个对象
                result.SetActive(true);          // 并将其显示
                gameobjectlist.Remove(result); // 已获得对象,将这个对象从集合中移除
            }
            else    // 集合为空,无法从池中取对象,得直接创建
            {
                result= MonoBehaviour.Instantiate(obj) ;
            }
            return result;
        }
        // 销毁子弹的方法(其实是隐藏子弹)
        public void DestroryObj(GameObject obj)
        {
            obj.transform.position=new Vector3(0,0,0);    // 将这个子弹的位置归零
            obj.SetActive(false);     // 并设置不可见
            gameobjectlist.Add(obj);  // 加入到对象池中,为了下次创建对象时备用
        }
    
    }

    然后再创建一个脚本用来实现创建子弹,把这个脚本挂载再相机上

    using System.Collections;
    using System.Collections.Generic;
    using System.Threading;
    using UnityEngine;
    
    public class contro : MonoBehaviour
    {
        public GameObject obj;
        private Ray _ray;   // 射线
        void Update()
        {
            if (Input.GetMouseButtonDown(0))    
            {
                _ray = Camera.main.ScreenPointToRay(Input.mousePosition);//发射射线
               GameObject gb= GameObjectManage.GetInstance.Instance_obj(obj);
               obj.transform.position = transform.position;
               gb.GetComponent<Rigidbody>().velocity = _ray.direction *100;
            }
            
        }
    }

    为了可以实现子弹2秒钟后将其隐藏,我们还需要创建一个脚本来挂载在子弹预制体上,对了,预制体上还需要加刚体。

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class cube_contro : MonoBehaviour
    {
        private void OnEnable()    // 不可换成Start哦
        {
            StartCoroutine(WaitDestrory());
        }
    
        IEnumerator WaitDestrory()    // 协程实现2秒钟后隐藏
        {
            yield return new WaitForSeconds(2f);
            GameObjectManage.GetInstance.DestroryObj(gameObject);
        }
    
    }

    通过这几个脚本就可以通过对象池来实现子弹发射效果咯,蛮简单的,但很使用。

    多多思考,举一反三,将对象池思想用于自己的游戏中吧!

  • 相关阅读:
    数学基础之梯度
    背包九问心得
    如何判断机器是大端机还是小端机
    Matlab学习 2021年2月10日
    数字信号处理(超浓缩版)第一天
    matlab里的数据类型
    如何学习Matlab的帮助文档?& 如何去编写帮助文档
    fprintf 和 dlmwrite 在写数据时的区别
    lateinit 延迟初始化
    data class 在 Kotlin中的定义
  • 原文地址:https://www.cnblogs.com/spiderljx/p/10966931.html
Copyright © 2011-2022 走看看