• Как исправить ошибку nullreferenceexception: object reference not set to an instance of an object?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Вы серьёзно улучшите свой код, просто вынеся ссылки на Rigidbody2D и SpriteRenderer в инспектор, как вы сделали это со спрайтами выше. Вопрос не только в повышении читаемости кода, а ещё в том, что сама операция GetComponent имеет слишком большие накладные расходы, чтобы каждый апдейт её использовать. В примере вашей игры вы разницы не увидите, но лучше начать писать сейчас, чем потом переучиваться.

    Сама же ошибка от того, что скрипту не удаётся найти самому ссылку на Rigidbody2D объекта вот в этой строке:
    if (_rigidbody.velocity.y >= 0) // вот тут, '_rigidbody'
                {
                    gameObject.GetComponent<SpriteRenderer>().sprite = _raisingSprite;
                }
                else
                {
                    gameObject.GetComponent<SpriteRenderer>().sprite = _fallSprite;
                }


    А ну и ПС. между gameObject.GetComponent и GetComponent нет разницы - это одно и то же, просто во втором случае gameObject, можно сказать, вызывается неявно.
    Ответ написан
    Комментировать
  • Как реализовать смену спрайта игрока при его взлете и падении?

    @Ezekiel4
    Охотник на пиратов и сборщик монолитов
    Если вы делаете персонажа через Rigidbody 2D, то можете использовать его velocity:
    using UnityEngine;
    
    public class FlappyBirdGraphics : MonoBehaviour {
    
    	[SerializeField] private Rigidbody2D _rigidbody;
    	[Space]
    	[SerializeField] private SpriteRenderer _spriteRenderer;
    	[SerializeField] private Sprite _raisingSprite;
    	[SerializeField] private Sprite _fallSprite;
    
    	private void Update() {
    		if (_rigidbody.velocity.y >= 0) {
    			_spriteRenderer.sprite = _raisingSprite;
    		} else {
    			_spriteRenderer.sprite = _fallSprite;
    		}
    	}
    }


    Вектор _rigidbody.velocity это что-то типа скорости, а свойство y (_rigidbody.velocity.y) это его вертикальная часть. Ну и дальше просто смотрите на её знак.

    Можно ещё сделать через аниматор или трансформ, но через Rigidbody эту игру делать проще всего. Если захотите добавить промежуточное "начальное состояние", когда персонаж смотрит ровно, то можно взять значение 0 и близкие к нему и по такому же принципу туда вставлять соответствующую картинку.
    Ответ написан
    Комментировать
  • Основа основ: какие инструменты нужны и что надо знать чтобы написать программу?

    ThunderCat
    @ThunderCat
    {PHP, MySql, HTML, JS, CSS} developer
    Тут в коментах понакидали, я немного разложу для понимания.
    Сегодня программирование это не 1 область, типа " - хочу в программирование - вам вот в эту дверь".
    Условно ее можно разделить на несколько подвидов, переход из которых в смежную будет сопровождаться некоторыми трудностями, особенно для новичка, по этому с направлением нужно определиться на берегу, или по крайней мере вовремя остановиться если увидели что это направление - не ваше.

    1) Веб разработка. В свою очередь делится на 2 поднаправления: фронтенд - все что отрисовывается и обрабатывается на клиенте (то есть проще говоря в браузере), и бэкенд - все что относится к работе со стороны сервера. Фронтенд, как это ни странно, ограничен в языках более всего, тут только яваскрипт или что-то типа тайпскрипта, которое по итогоу в яваскрипт "компилируется". Бэк в этом плане более разношерстный, тут можно практически все использовать, но мэйнстрим это пхп, питон, ява, сишарп, руби-рельсы. Первые два в основном используют студии вебразработки, вторые два - в основном энтерпрайз, последний уже больше экзотика.
    2) Геймдев. Как ни странно, тоже делится на 2 поднаправления: казуалки/мобилы и большие триплА проекты. В первом случае это сишарп + юнити (да, это не язык, а инструмент, но без него стек не полный), в редком случае что-то экзотическое. Во втором это скорее всего си++ и какой-то фреймворк, а-ля анриал или вулкан.
    3) Энтерпрайз. Тут стандарт де факто - ява. Как вариант Сишарп, но гораздо реже.
    4) Десктоп приложения. Простенькие консольные можно писать практически на чем угодно, более-менее обладающее интерфейсом тербует соответствующих gui библиотек, по типу Qt, gtk, ну и соответственно языков типа ява, си++, сишарп... Хочу заметить, что направление это весьма дохлое, в плане того что именно приложения для широких масс в последнее время практически не выпускаются, уступая место вебсервисам или мобильным приложениям, которые тоже не ахти какие рынки занимают...
    5) Мобильная разработка. Зверь редкий, так как под мобилы больше игры делают. Именно разработка приложений достаточно узкий сегмент, ну и опять же - делится на разработку под андроид и под айфон. В первом случае языком разработки будет Котлин(в девичестве Ява), под айфон соответственно будет Свифт. Есть решения кроссплатформенные, по типу флаттера, но это не всегда подходит, так как некоторые функции под конкретную платформу будут недоступны.

    Короче, определяетесь с направлением, пробуете, не нравится - берете следующее, с языками так же. По тому "в чем писать" определяться стоит по запросу "среда разработки для %языкнейм%"
    Ответ написан
    2 комментария
  • Как остановить движение объекта после соприкосновения с коллайдером другого?

    @devmikhalev
    OnTriggerEnter2D вызывается один раз, при столкновении с триггером, когда как Update вызывается каждый кадр.
    Таким образом согласно Вашему коду при столкновении Вы один раз останавливаете движение Вашего препятствия, после чего тут же снова запускаете его в Update. Можно просто при столкновении установить скорость = 0.

    Также вместо сравнения с помощью оператора "==" лучше сравнивать тег с помощью CompareTag(). Работать будет и так и так, но лучше сразу приучать себя делать правильно (положительно повлияет на скорость выполнения кода).

    И обратите внимание, что если используете стандартные теги Unity, то тег игрока там не "player", а "Player". Заглавные буквы в данном случае критичны, и если у объекта тег "Player", то при сравнении по "player" код не отработает.

    Вот пример кода:

    public class Map : MonoBehaviour
            {
                public float speed;
                void Update()
                {
                    transform.Translate(Vector2.left * (speed * Time.deltaTime)); //Движение объекта
                }
                private void OnTriggerEnter2D(Collider2D collision)
                {
                    if (collision.CompareTag("Player"))
                    {
                        speed = 0;
                    }
                }
            }
    Ответ написан
    1 комментарий
  • Как заставить сцену перезапускаться при достижении игрока в определенную координату?

    @devmikhalev
    OnTriggerEnter2D вызывается один раз, при соприкосновении с триггером, т.е. из Вашего кода исходит, что if (transform.position.y.Equals(-3)) выполнится только тогда, когда позиция равна -3 в момент столкновения, а не после него.

    Если триггер включает в себя указанную Вами позицию (-3), т.е. при достижении этой позиции объект не перестает быть внутри триггера, то Вы можете использовать OnTriggerStay2D, который постоянно вызывается, пока объект находится внутри триггера. В него нужно вынести условие перезапуска сцены, а все остальное оставить внутри OnCollisionEnter2D.

    Однако правильнее будет не привязывать условие к триггеру. Например так:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEditor.U2D;
    using UnityEngine;
    using UnityEngine.SceneManagement;
    
    public class PlayerControl : MonoBehaviour
    {
        private bool _isAlive = true;  // введем булевую переменную указывающую на то, что персонаж жив
        public float force;
        public float speed;
        public Sprite astronaut_2;
        void Update()
        {
             if (Input.GetMouseButtonDown(0))
            {
                Jump();
            }
            // указываем, что если позиция равна -3, и персонаж не жив (_isAlive не равно true), то перезапускаем сцену
            if (!_isAlive && transform.position.y.Equals(-3))
            {                                                     
                    SceneManager.LoadScene("level_1");
            }
        }
        void Jump()
        { 
            GetComponent<Rigidbody2D>().velocity = new Vector2(speed, 0f);
            GetComponent<Rigidbody2D>().AddForce(Vector2.up * force);            //управление персонажа
        }
        private void OnTriggerEnter2D(Collider2D collision)
        {
            
            if (collision.tag == "Enemy")
            
            {
                GetComponent<Rigidbody2D>().velocity = new Vector2(-7f, 0f);
                GetComponent<Rigidbody2D>().AddForce(Vector2.up * 300);             //отбрасывание персонажа после соприкосновения с препятсвием
                gameObject.GetComponent<SpriteRenderer>().sprite = astronaut_2;     //смена спрайта игрока после соприкосновения с препятсвием
                _isAlive = false;  // после столкновения переключаем переменную в значение false, указывая на то, что персонаж погиб
    
            }
        }
    }


    Также можно проверять, что позиция не равна -3, а меньше или больше (в зависимости от того, в какую сторону отбрасывает Вашего персонажа), т.к. если персонаж пролетит заданную точку слишком быстро, то условие может не отработать. Это краткие рекомендации, остальной код оставлен исходным, советую постараться подробнее разобраться самостоятельно для лучшего понимания. Удачи!
    Ответ написан
    4 комментария