Comments 24
public class GameStatus : MonoBehaviour
{
...
// State variables
[SerializeField] private int _currentScore = 0;
void Awake()
{
int objectsCount = FindObjectsOfType<GameStatus>().Length;
if (objectsCount > 1)
{
gameObject.SetActive(false);
Destroy(gameObject);
}
else
{
DontDestroyOnLoad(gameObject );
}
}
...
public void ResetGame()
{
Destroy(gameObject);
}
}
Вообще нужно посчитать, что будет затратнее по ресурсам, они дороги, так как проект ориентирован на мобильные. Меня учили, что на сцене лучше лишних объектов не держать, но буду рада если расскажете почему решение с синглтоном лучше.
Данная статья будет полезна начинающим разработчикам игр.)))
Статик, мягко говоря, так себе решение. Представьте ситуацию, когда вам надо ресетнуться, полоностью перезапустить игру, а у вас в статике 100500+ полей. Будете ручками все это дефолтить? Статик для констант удобен. Хотя если аккуратно, то имеет право на жизнь, например в качестве контейнеров.
эм, но в таком случае в статик кладется объект а-ля AllStaticData
и обнуляется только он.
Но да, полезная ремарка, если начинающий разработчик вдруг решит туда напихать гораздо больше.
Попыталась намекнуть на это словами «простых игр» в названии, буду аккуратнее.
Советую посмотреть на Dependency Injection и DI / IoC фреймворки вроде ZenJect (линк).
Знаю, что для новичка это не простая концепция, но она имеет большое количество преимуществ перед синглтонами/статик классами/DontDestroyOnLoad.
Данный подход позволит сделать единую точку входа в приложение, а для хранения данных пользователя вместо singleton объекта можно использовать сервис (который потом можно заинъектить в необходимые вам скрипты):
public interface IGameDataService
{
public int DifficultyLevel { get; set; }
}
public class EnemyInstaller : MonoInstaller
{
public override void InstallBindings()
{
// IGameDataService будет автоматически инъекцировано в зависимые классы
// включая другие сцены, если использован Scene Container Parenting
Container.Bind<IGameDataService>().To<GameDataService>().AsSingleton();
}
}
public class EnemyFactory : IEnemyFactory
{
private readonly IGameDataService _gameDataService;
// Зависимость будет добавлена в конструктор автоматически при резолвинге EnemyFactory
// Для инъекции в MonoBehavior, можно добавить специальный компонент ZenjectBinding и аттрибут [Inject]
public EnemyFactory(IGameDataService gameDataService)
{
_gameDataService = gameDataService;
}
public void SpawnEnemy(string enemyName)
{
var level = _gameDataService.DifficultyLevel;
...
var enemy = GameObject.Instantiate(...).GetComponent<IEnemy>();
enemy.SetLevel(level);
}
}
В идеале, GameObject'ы и MonoBehavior'ы — для объектов игрового мира. Для всего остального есть обычный C#.
Я вот прикрутил вот такой вот скрипт к видеоплееру. По завершении видео управление передается следующей сцене, задаваемой прямо в инспекторе. Чекбоксами контролируется видимость указателя мышки во время воспроизведения и после. Немного оффтоп, но может пригодится кому =))
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Video;
using UnityEngine.SceneManagement;
public class Intro : MonoBehaviour
{
[SerializeField]
private int sceneNext;
[SerializeField]
private bool cursorVisible;
[SerializeField]
private bool cursorVisibleSceneNext;
VideoPlayer _videoPlayer;
void Start()
{
Cursor.visible = cursorVisible;
_videoPlayer = GetComponent<VideoPlayer>();
_videoPlayer.Prepare();
_videoPlayer.loopPointReached += _videoPlayer_loopPointReached;
Invoke("play", 3);
}
private void _videoPlayer_loopPointReached(VideoPlayer source)
{
Cursor.visible = cursorVisibleSceneNext;
SceneManager.LoadScene(sceneNext);
}
private void play()
{
_videoPlayer.Play();
}
void Update()
{
if (Input.GetKeyUp(KeyCode.Escape) | Input.GetKeyUp(KeyCode.Return))
{
Cursor.visible = cursorVisibleSceneNext;
SceneManager.LoadScene(sceneNext);
}
}
}
Передача данных между сценами в Unity — применение мультисценности в разработке простых игр