unity對象池之引用技術

推薦閱讀:

專門寫一篇文章來和大家分享一下引用技術,爲什麼呢?因爲第一次聽說這麼名詞,覺得高大上,不要害怕,其實道理挺簡單的,待我細細來說明。

最近在做一個資源複用的功能,對於資源複用,一般能想到的解決辦法就是使用對象池,需要的時候去池子裏取。但是考慮效率消耗問題,想到了一個更優的方法:再引入一個對象池,共兩個對象池,一個用來做資源對象池objPool,一個是將實例化資源的所在的父類所用到的所有的對象作爲另一個池itemPool。

用文字描述可能聽不太懂,給大家舉個例子吧:

玩家時裝展示榜單:該榜單是個循環列表,大致5個item的樣子。首先判斷需要顯示的時裝是否存在objPool,不存在,則實例化並保存在objPool裏。存在則取出對象,SetParent到需要顯示的item上。但是,使用這種方式會出現一個問題:

當同一頁面的兩個及以上玩家時裝相同時,會導致穿戴該時裝的只有最後一個玩家時裝時存在的,同一界面其他玩家沒有時裝,這就是SetParent的結果,因爲資源只有一個,但是卻有幾個地方SetParent了。沒有實例化,僅僅SetParent,當然結果會停留在最後一次SetParent。

對於上面的問題,對象池裏面的對象都是唯一的,如果某個對象會同時在兩個及以上的的地方同時使用時,又該怎麼辦呢?這時候就要用到引用技術了。

引用技術:當某個對象需要被同時在多處使用時,爲了保證每個地方都能使用,它支持去對象池去取該對象,如果存在則直接拿出來使用,不存在則按照:對象的名字+序號來區分該對象,名字如下:
cat_1,cat_2,dog_1,等等。現在我們的目標很清晰了,重點是計算序號(count):

local count = 0 
for 對象池 do
	 if 對象顯示在面板 then
		count = count +1
	end
end

在unity中,判斷是否顯示在面板上的方法:

activeInHierarchy

功能實現方法:

 newsid = 1001 + index--TODO
    if args[1] and args[1] == newsid then
        --一樣
    else
        if args[2] then
            SetActive(objPool[tonumber(args[1])][tonumber(args[2])], false)
        end
        local count = 0
        for k, v in pairs(objPool[newsid] or {}) do
            if v.activeInHierarchy then
                count = count + 1
            end
        end
        local data = { sid = newsid, star = 5 }
        local obj = objPool[newsid] and objPool[newsid][count] or herobase.SetHeroRes(data, go, 0.5)
        obj.transform:SetParent(render.mold.transform)
        obj.transform.localPosition = Vector3.New(0, -280, 0)
        if objPool[newsid] == nil then
            objPool[newsid] = {}
        end
        objPool[newsid][count] = obj
        renderObj[go] = newsid .. "|" .. count
        SetActive(obj, true)
    end
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章