Unity中如何獲取動態生成的物體的數據?
首先在unity中創建一個預製件Box,然後將一個腳本掛在該預製件上。腳本中定義一個int weight,weight的值會在預製件實例化後被賦值。
請問如何在場景運行過程中獲取所有Box的weight值?
--------
一個比較簡單的辦法是,等weight賦值完畢後,將weight的值傳給一個靜態欄位,等有需要的時候直接讀取該靜態欄位的值就行了。
但這個方法也有以下問題:
- 無法知道每個Box的weight值是多少,只知道他們的和。
2. 如果以後Box又需要新增其他的數據類型,無論這些數據是否會被用到,都要分配內存空間給這些數據,導致了內存的浪費。
--------
可以通過foreach (Transform Box in parent)來獲取Box的引用,但是不知道該如何通過這些引用訪問他們的weight值
這個需求本身是合理的,有普遍性。要解決也很簡單,就是「管理器」。
用Unity做小遊戲的時候,初學者會習慣於創建各種組件和物體,然後每個物體管好自己就行了,不需要統一的地方管理這些創建出來的對象。
通過取巧的設計確實可以一直湊合很久,但是總有一天你會發現需要反覆訪問已經已經創建好的對象。
對於有一定規模的項目來說,不用管理器幾乎是不可能的。
簡單來說,一個管理器就是一個全局唯一的對象,內含至少一個容器(List或字典)。
你每次創建gameObject的時候,就把新的gameObject存進去。之後你就可以隨意取裡面的對象來用了。
添加、查找、修改物體都要設計專門的方法,不要在管理器之外直接操作容器,容易寫錯。就是這麼簡單。
關鍵是查找之前加進去的物體的時候,你準備怎麼查?還是隻需要遍歷所有物體就行?
其實題主提到的「foreach (Transform Box in parent)」,也算是一種管理器的思想,就是把所有物體放在同一個父物體下面,遍歷也很方便。取到Box之後,Box.GetComponent&().weight,就可以獲得腳本組件中的weight了。
用Unity時,是否用到容器來管理對象,可以說是區分菜鳥和入門者的一個標誌。
卸腰。
出現這個問題的原因不在問題本身,而在於設計思想的問題。在正規的項目開發中,絕對不應該出現創建了一個GameObject,然後需要通過GameObject.Find,或是在初始化過後再去GetComponent這樣的做法。正確的做法是脫離Unity的Component系統,自己用數據結構去管理,這樣才能保證邏輯的獨立性和完整性。
比如這裡,很顯然Box被創建以後,是應該有個數據結構始終儲存著這些Box的信息的,需要用的時候從這個數據結構中獲取,而不是去考慮如何GetComponent。缺乏編程經驗的開發者尤其要注意。
@MaxwellGeng 的答案說的很好,本質問題是設計思路不對。但是如果你非要這樣做也不是不可以,直接使用
GameObject.FindObjectsOfType&()
方法即可,其中泛型參數T就是腳本的類。但是考慮到這樣會遍歷場景中所有組件和對象,效率堪憂。
幾種方式:
1. 場景建立父節點,所有的box創建到該父節點下。找到父節點遍歷所有children。
2. 自己設計數據結構保存所有box的transform或者gameobject的引用,並自行設計實現訪問介面。
3. 把所有的box放到單獨的layer裏。
有點感想,就多說幾句:在我看來,寫自己的獨立系統也好,利用unity的原生系統也好,其實並沒有絕對的事,在時間和空間上找到平衡,選擇適合自己目前需要的就可以了。實現時注意保持松耦合度,做到重構代價低。
如果你能拿得到Transform,那就可以直接GetCompontent獲取你那個腳本裡面的公共變數了
上面的答主都已經說的差不多了。。我就補充一點(
在gameobject實例化的重載函數中,剛好是可以指定父節點的。另外從在站在場景資源管理的角度上來說,大量相同對象通過一個父節點來管理也很必要。
此時只需要緩存一個父節點就行了,通過GetComponentInChildrens&來動態獲取的效率也不低。
最後你需要權衡的只是,是否需要緩存所有的Box來達到空間換時間的效果。
自己用的方法
gameObject.Ins什麼什麼(就那個實例化的方法)本身會返回實例化的物體的gameObject
所以只需要一個新的gameObject 然後給他賦值這個函數的返回值就行 然後再getComponet
這應該是最簡單的方法 不考慮別的需求
你在生成的時候存下來不行嗎?
這個問題應該歸納到組件生命週期的管理上吧,用一個boxmanager控制所有box的生成銷毀如果關心box的weight就在生成的時候回調一下OnInit()。將該box中weight的值記錄下來。
推薦閱讀: