У меня есть сценарий 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;
}
}
Приятно видеть, что вы не спешите на этот раз и хотите изменить свой дизайн. Не могли бы вы объяснить это следующим образом: ** сделать так, чтобы, как только сборник, использующий этот скрипт, имеет другое место, диспетчер игр ищет его и загружает спрайты, а затем дает всем, кому это нужно **. И, пожалуйста, добавьте свой текущий код –
Да, я видел причину и понял, что продолжение неправильного дизайна будет стоить больше времени, чем переписывать его. Включая этот проигрыватель изображений в секунду. – agiro
Итак, идея состоит в том, что у меня есть скрипт, используя статический массив spriteSheet, который загружает спрайты, чтобы играть один за другим. Как узнать, где загрузить изображения? Я набираю имя папки в редакторе, у меня есть только необходимые изображения. Таким образом, как вы сказали ранее, эти изображения загружаются много раз, но теперь в один массив. Чтобы обойти это, я хотел бы загрузить эти значения 'string' в массив' string' и дать скрипту Manager знать, что он должен загружаться из них. – agiro