如何为视差脚本增加池大小来解决Unity3d编辑器滞后问题?

问题描述 投票:0回答:1

我正在创建2D Platformer游戏。

当附加到我的预制件上的视差脚本的池大小增加时,Unity3D应用程序将滞后并冻结更大的池大小。此事件以前在其他具有较大池大小的项目中不存在。不论游戏方面如何,事件似乎都将持续。

附有预制件的Parallaxer脚本池大小:10(开始滞后的位置)换挡速度:-1产生率:1

Y产生范围:最小Y:0最大值Y:2.72默认生成位置X:12.81Y:-0.03 Z:0立即生成:未选中即时生成位置X:0 Y:0 Z:0目标宽高比:X:10 Y:16

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

public class Parallaxer : MonoBehaviour {

    class PoolObject {
        public Transform transform;
        public bool inUse;
        public PoolObject(Transform t) { transform = t; }
        public void Use() { inUse = true; }
        public void Dispose() { inUse = false; }
    }

    [System.Serializable]
    public struct YSpawnRange {
        public float minY;
        public float maxY;
    }

    public GameObject Prefab;
    public int poolSize;
    public float shiftSpeed;
    public float spawnRate;

    public YSpawnRange ySpawnRange;
    public Vector3 defaultSpawnPos;
    public bool spawnImmediate;
    public Vector3 immediateSpawnPos;
    public Vector2 targetAspectRatio;

    float spawnTimer;
    PoolObject[] poolObjects;
    float targetAspect;
    GameManager game;

    void Awake() {
        Configure();
    }

    void Start() {
        game = GameManager.Instance;
    }

    void OnEnable() {
        GameManager.OnGameOverConfirmed += OnGameOverConfirmed;
    }

    void OnDisable() {
        GameManager.OnGameOverConfirmed -= OnGameOverConfirmed;
    }

    void OnGameOverConfirmed() {
        for (int i = 0; i < poolObjects.Length; i++) {
            poolObjects[i].Dispose();
            poolObjects[i].transform.position = Vector3.one * 1000;
        }
        Configure();
    }

    void Update() {
        if (game.GameOver) return;

        Shift();
        spawnTimer += Time.deltaTime;
        if (spawnTimer > spawnRate) {
            Spawn();
            spawnTimer = 0;
        }
    }

    void Configure() {
        //spawning pool objects
        targetAspect = targetAspectRatio.x / targetAspectRatio.y;
        poolObjects = new PoolObject[poolSize];
        for (int i = 0; i < poolObjects.Length; i++) {
            GameObject go = Instantiate(Prefab) as GameObject;
            Transform t = go.transform;
            t.SetParent(transform);
            t.position = Vector3.one * 1000;
            poolObjects[i] = new PoolObject(t);
        }

        if (spawnImmediate) {
            SpawnImmediate();
        }
    }

    void Spawn() {
        //moving pool objects into place
        Transform t = GetPoolObject();
        if (t == null) return;
        Vector3 pos = Vector3.zero;
        pos.y = Random.Range(ySpawnRange.minY, ySpawnRange.maxY);
        pos.x = (defaultSpawnPos.x * Camera.main.aspect) / targetAspect;
        t.position = pos;
    }

    void SpawnImmediate() {
        Transform t = GetPoolObject();
        if (t==null) return;
        Vector3 pos = Vector3.zero;
        pos.y = Random.Range(ySpawnRange.minY, ySpawnRange.maxY);
        pos.x = (immediateSpawnPos.x * Camera.main.aspect) / targetAspect;
        t.position = pos; 
        Spawn();
    }

    void Shift() {
        //loop through pool objects 
        //moving them
        //discarding them as they go off screen
        for (int i = 0; i < poolObjects.Length; i++) {
            poolObjects[i].transform.position += Vector3.right * shiftSpeed * Time.deltaTime;
            CheckDisposeObject(poolObjects[i]);
        }
    }

    void CheckDisposeObject(PoolObject poolObject) {
        //place objects off screen
        if (poolObject.transform.position.x < (-defaultSpawnPos.x * Camera.main.aspect) / targetAspect) {
            poolObject.Dispose();
            poolObject.transform.position = Vector3.one * 1000;
        }
    }

    Transform GetPoolObject() {
        //retrieving first available pool object
        for (int i = 0; i < poolObjects.Length; i++) {
            if (!poolObjects[i].inUse) {
                poolObjects[i].Use();
                return poolObjects[i].transform;
            }
        }
        return null;
    }

}
c# unity3d 2d parallax lag
1个回答
0
投票

当您更改对象的transform.position时,如果该对象嵌套在游戏层次结构中的其他对象中,则可能是一个昂贵的过程。不用更改对象的变换,而是考虑在不使用GameObject时将其设置为非活动状态。另外,可以考虑创建一个未使用对象队列,而不是每次需要GetPoolObject()时都要遍历PoolObjects列表。这有两个目的:

  1. 您不再需要通过属性跟踪对象是否在使用中
  2. 您不需要遍历所有对象来找到可用的对象。

队列示例:

Queue<PoolObject> availableObjects = new Queue<PoolObject>();

class PoolObject 
{
    public Transform transform;
    public bool inUse;
    public PoolObject(Transform t) { transform = t; }
    public void Use() { inUse = true; }
    public void Dispose() { inUse = false; }
}

void CheckDisposeObject(PoolObject poolObject) 
{
    //place objects off screen
    if (poolObject.transform.position.x < (-defaultSpawnPos.x * Camera.main.aspect) / targetAspect) 
    {
        availableObjects.Enqueue(poolObject);
        poolObject.transform.gameObject.SetActive(false);
    }
}

Transform GetPooledObject()
{
    if(availableObjects.Count > 0)
        Transform poolObj = availableObjects.Dequeue();
        poolObj.gameObject.SetActive(true);
        return poolObj;
    else
        return null;
}
© www.soinside.com 2019 - 2024. All rights reserved.