Related Posts Plugin for WordPress, Blogger...

5-21 Integrate All FindObjectOfType Into One Class

本章要介紹大家一個我覺得很方便的方法,主要因為最近遇到了要尋找某些Component時遇到困難,隨著專案的規模越來越大,我忘記了早期寫的一些Component要用FindObjectOfType來呼叫,該特定的Component在場景中僅會有一個。考量到使用這類型的Component時每次都用使用FindObjectOfType應該滿耗效能的,所以我就統一將這類型的Component集合在一個Class中。

首先我用Search/Find in Files的功能,尋找一下專案中有哪些地方使用到FindObjectOfType。

在輸入框中輸入FindObjectOfType,按下Find。

下列就會列出有用到FindObjectOfType的地方,如我的遊戲專案中有PlayerMovement、CameraRaycaster、InventorySystem。

再來我建立一個新的Script名為Game.cs,然後依照需要撰寫相關的FindObjectOfType,使用一個依賴MonoBehaviour的單例模式,寫起來很簡單。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using RPG.Character;
using RPG.Inventory;
using RPG.CameraUI;

namespace RPG.Core{
 public class Game : MonoBehaviour {
  public static Game Instance;

  [HideInInspector] public PlayerMovement playerMovement;
  [HideInInspector] public InventorySystem inventorySystem;
  [HideInInspector] public CameraRaycaster cameraRaycaster;

  WeaponSystem playerWeaponSystem;

  void Awake(){
   Instance = this;

   playerMovement = FindObjectOfType ();
   inventorySystem = FindObjectOfType ();
   cameraRaycaster = FindObjectOfType ();

   playerWeaponSystem = playerMovement.gameObject.GetComponent ();
  }

  public WeaponSystem GetPlayerWeaponSystem(){
   return playerWeaponSystem;
  }
 }
}

程式碼中的[HideInInspector]可以避免public屬性的變數出現在Inspector視窗中,畢竟我已經用FindObjectOfType抓到Component了,不希望讓設計師在Inspector視窗中指定到錯誤的物件。

再來只要把Game這個Component放進場景中的一個GameObject之中即可,如圖我放在EventSystem之中。

完成上述的步驟就可以正確抓到Component了,接著我們需要把舊的程式碼改成新的寫法。如原本在更換武器時,會需要抓到Player的WeaponSystem的地方。

現在則是要改成從Game取得WeaponSystem,由於Game是單例模式,所以取得物件的寫法
非常簡單。統一管理的好處是以後有需要用FindObjectOfType的Component,直接到Game裡面去找就好了,這類型的Component都是場景內唯一存在的Component。


留言