2016-09-05 2 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, который загружает спрайты, чтобы играть один за другим. Как узнать, где загрузить изображения? Я набираю имя папки в редакторе, у меня есть только необходимые изображения. Таким образом, как вы сказали ранее, эти изображения загружаются много раз, но теперь в один массив. Чтобы обойти это, я хотел бы загрузить эти значения 'string' в массив' string' и дать скрипту 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. 
} 

EDIT:

Сценарий синглтон не должен присутствовать в сцене на более чем одного объекта. Создайте пустой объект и прикрепите singleton-скрипт. Если у вас есть другие общие функции (например, spritesheet), переместите этот код в singleton.make, убедитесь, что у вас нет кода загрузки спрайтов в другом скрипте, который вы применяете ко всем объектам.

+0

Я думал только о ** загрузках **, чтобы быть одиночными, думаю, я был неправ. Я прочитал немного об этом, и я подумал, что ** singleton есть только один из них **. У меня есть этот скрипт на нескольких 'prefabs', около 4-5 типов, всего 20. поэтому 4-5 спрайтов. Если я получаю то, что вам нужно, мы делаем уникальную часть только из спрайта и используем все остальное, что используется? – agiro

+1

обновил мой ответ –

+0

Ваш отредактирован немного прояснен.Итак, 'singleton' = ** есть только один **, как видно из названия: D Я планирую создавать синглтонные массивы и загружать их с использованием одноэлементного материала. игрок последовательности, у которого будет 20 экземпляров, будет только сообщать боссу, что загружать, и он загружает его ** только один раз **. Спасибо за помощь, я многому научился: D – agiro

Смежные вопросы