2016-09-05 46 views
1

我有一個ImageSequencePlayer腳本,它具有字符串輸入以選擇從哪裏加載圖像。圖像的Sprite[]數組現在是靜態的,但我仍然將它們多次加載到相同的數組中。我有更多使用此工具的預製件,例如一個角色,敵人,一些陷阱,火焰等等。如何使用Singletons創建一個體面的設計?使它一旦prefab使用這個腳本有一個不同的位置,遊戲管理器尋找它並加載精靈,然後給所有需要的?如果不是這樣的話怎麼樣?使用單例爲單位設計初始化

using UnityEngine; 
using System.Collections; 

public class ImageSequencePlayer : MonoBehaviour 
{ 
    private int currentImageIndex; 
    private SpriteRenderer spriteRenderer; 
    private static Sprite[] spriteSheet; 
    [Tooltip("The location of your main spritesheet.")] 
    public string spritesLocation; 
    public float frameRate = 24.0f; 
    public enum PlayMode 
    { 
     order, random, uponNeeded 
    } 
    public PlayMode playMode = PlayMode.order; 
    private bool updateEnabled = true; 
    [Tooltip("Decides if the random playback can iterate. If no, it doesn't play, it is frozen.")] 
    public bool canIterate = true; //if the random playback can iterate. if no, it doesn't play. 
    [Tooltip("Is there some non looping animation before the loop? If so, right after it's done, it starts looping.")] 
    public bool warmUp = false; 
    [Tooltip("If you have a warmup sheet location, put it here.")] 
    public string warmUpLocation = ""; 
    private static Sprite[] warmUpSprites; 

void Start() 
{ 
    try 
    { 
     spriteSheet = null; 
     spriteSheet = Resources.LoadAll<Sprite>(spritesLocation); 
    } 
    catch(MissingSpriteSheetException ex) 
    { 
     Debug.Log(ex.Message); 
    } 

    try 
    { 
     spriteRenderer = GetComponent<SpriteRenderer>(); 
    }catch 
    { 
     spriteRenderer = GetComponentInChildren<SpriteRenderer>(); 
    } 

    if(warmUp) 
    { 
     switch (this.gameObject.tag) 
     { 
      case "candleLight": 
       warmUpSprites = null; 
       warmUpSprites = Resources.LoadAll<Sprite>("warmUpFlames"); 
       break; 
      default: 
       warmUpSprites = null; 
       warmUpSprites = Resources.LoadAll<Sprite>(warmUpLocation); 
       break; 
     } 
     //meaning we do have something to warm up 
    }else 
    { 
     //so if we did want some warmup, we load it, 
     //if we didn't, we just free the memory. 
     warmUpSprites = null; 
     warmUpLocation = null; 
    } 
    if(playMode == PlayMode.uponNeeded) 
    { 
     //if we need it occasionally, we just disable everything else. 
     warmUp = false; 
     updateEnabled = false; 
     warmUpLocation = null; 
     warmUpSprites = null; 
    } 
} 
void LateUpdate() 
{ 
    if (warmUp) 
    { 
     currentImageIndex = Mathf.RoundToInt(Time.time * frameRate); 
     currentImageIndex = currentImageIndex % warmUpSprites.Length; 
     spriteRenderer.sprite = warmUpSprites[currentImageIndex]; 
     if(currentImageIndex >= warmUpSprites.Length-1) 
     { 
      currentImageIndex = 0; 
      warmUp = false; 
      //now easing on the memory, not another warmup will happen of course: 
      warmUpLocation = null; 
      warmUpSprites = null; 
     } 
    } 
    if (updateEnabled && !warmUp) 
    { 
     switch (playMode) 
     { 
      case PlayMode.order: 
       currentImageIndex = Mathf.RoundToInt(Time.time * frameRate); 
       currentImageIndex = currentImageIndex % spriteSheet.Length; 
       spriteRenderer.sprite = spriteSheet[currentImageIndex]; 
       break; 
      case PlayMode.random: 
       updateEnabled = false; 
       StartCoroutine(RandomizedPlay()); 
       break; 
     } 
    } 

} 
IEnumerator RandomizedPlay() 
{ 
    int oldIndex = 0; 
    int currentIndex; 
    int iterNumber = 0; 
    while (canIterate) 
    { 
     currentIndex = Random.Range(0, spriteSheet.Length - 1); 
     if(currentIndex == oldIndex) 
     { 
      while((currentIndex == oldIndex) && (iterNumber < 8)) 
      { 
       currentIndex = Random.Range(0, spriteSheet.Length - 1); 
       iterNumber++; 
      } 
     } 
     spriteRenderer.sprite = spriteSheet[currentIndex]; 

     oldIndex = currentIndex; 
     iterNumber = 0; 
     yield return new WaitForSeconds(1.0f/frameRate); 
    } 
} 
public void OccasionalAnimation(bool backWardsNeeded) 
{ 
    StartCoroutine(OccasionalAnimEnum(backWardsNeeded)); 
} 
public IEnumerator OccasionalAnimEnum(bool backWardsNeeded) 
{ 
    currentImageIndex = 0; 
    while (currentImageIndex < spriteSheet.Length) 
    { 
     //meaning while we do have anything to play 
     spriteRenderer.sprite = spriteSheet[currentImageIndex]; 
     currentImageIndex++; 
     yield return new WaitForSeconds(1.0f/frameRate); 
    } 
    if (backWardsNeeded) 
    { 
     //so we need to play the shit backwards as well, like in the book 
     currentImageIndex = spriteSheet.Length - 2;//so we won't repeat the last again. 

     while (currentImageIndex >= 0) 
     { 
      //meaning while we do have anything to play 
      spriteRenderer.sprite = spriteSheet[currentImageIndex]; 
      currentImageIndex--; 
      yield return new WaitForSeconds(1.0f/frameRate); 
     } 
    } 
    //at the end it should be at the starting sprite. 
    currentImageIndex = 0; 
} 
} 
+1

很高興看到你不急於這次,並願意改變你的設計。你可以解釋一下這個問題:**這樣做,只要使用這個腳本的預製具有不同的位置,遊戲管理器就會查找它並加載這些小精靈,然後給出所有需要這些的**。並請添加您當前的代碼以及 –

+0

是的,我看到了原因,並意識到繼續錯誤的設計將花費更多的時間比重寫它。 我在一秒鐘內包含了圖像序列播放器。 – agiro

+0

所以這個想法是,我有腳本,使用一個靜態的spriteSheet數組加載的精靈一個接一個地播放。 如何知道從哪裏加載圖像?我在編輯器中鍵入文件夾的名稱,在那裏只有必要的圖像。 就像你之前說的那樣,這些圖像會被加載很多次,但現在已經加載到一個數組中。 爲了解決這個問題,我想將這些字符串值加載到字符串數組中,並讓Manager腳本知道它必須從這些數組中加載。 – agiro

回答

1

在腳本的開始添加以下代碼,使其單:

private static ImageSequencePlayer _instance; 
public static ImageSequencePlayer Instance 
{ 
    get 
    { 
     if (_instance == null) 
     { 
      _instance = FindObjectOfType<ImageSequencePlayer>(); 
      if (_instance == null) 
      { 
       Debug.LogError("ImageSequencePlayer Instance is null"); 
      } 
     } 
     return _instance; 
    } 
} 

現在你不需要做任何事情static

可以從任何地方像這樣的非靜態精靈陣列:

ImageSequencePlayer.Instance.spriteSheet 

和所有其他屬性/以同樣的方式領域。

使用Awake()方法從資源載入圖像:

void Awake() 
{ 
    // populate sprites array here. 
} 

編輯:

的單腳本應該不會出現在場景上的多個對象。創建一個空對象並附加單例腳本。如果您有任何其他常見功能(如spritesheet),請將該代碼移到singleton.make,確保您沒有在您應用於所有對象的其他腳本中加載精靈。

+0

我認爲只有**加載**自己是單身人士,猜測我錯了。 我讀了一點,我認爲**單身人士是隻有一個**。 我在多個'prefabs'上有這個腳本,大約有4-5個類型,總共20個。所以4-5個spritesheets。 如果我得到你以後的東西,我們只能從spritesheet中創建一個獨特的部分,並使用其他所有的東西來用? – agiro

+1

更新了我的回答 –

+0

您的編輯清理了一下。所以'singleton' = **只有一個**,如名稱所示:D我打算製作單身數組並使用單例東西加載它們。將有20個實例的序列播放器只會告訴老闆要加載的內容,並且只會加載**一次**。謝謝你的幫助,我學到了很多:D – agiro