• Как заставить отработать событие OnTriggerExit?

    @Ente
    Unity developer
    Можно перед отключением объекта сдвинуть его на большие координаты, вроде (-99999, 0, 0), тогда функция отработает, как надо. Костыль, но работает.
    Ответ написан
    Комментировать
  • Как исправить ошибку в коде C#?

    @Ente
    Unity developer
    WheelCollider убери
    Ответ написан
    Комментировать
  • Как сделать чтобы Player наносил урон Enemy?

    @Ente
    Unity developer
    Сделай себе два скрипта, первый будет для всех объектов в игре, которые обладают здоровьем, это могут быть персонажи (твой игрок, враги), предметы (двери, стены и т.п.)

    У этих объектов будет скрипт, назовем его Health.cs

    [SerializedField] private int hitpoints = 100;
    public Action<int, int> OnChange;
    
    public void Change(int amount)
    {
               hitpoints += amount;
               OnChange?.Invoke(hitpoints, amount);
    }


    В этом скрипте можно будет менять здоровье через функцию Change, причем в любую сторону, может проходить и урон, так и лечение, все зависит от знака в переданной переменной amount. Также скрипт бросает событие, что здоровье изменилось, чтобы другие скрипты могли подписаться и отреагировать. Например, скрипт, который рисует полосу здоровья или скрипт, который отвечает за смерть персонажа.

    Второй скрипт - Damage.cs. Он будет работать на триггерах в Unity, и когда объекты пересекаются между собой, то происходит вызов функции урона, например, если персонаж встанет в огонь, его затронет пуля или меч. Само собой нужно проставить им триггеры нужного размера, как объекту с уроном, так и тому, кому наносится урон + поставить правильно матрицу коллизий, чтобы OnTriggerEnter2D не затрагивал другие объекты, которые не являются его целью.

    [SerializedField] private int amount = -10;
    public Action<int> OnDamage;
    
    private void OnTriggerEnter2D(Collider2D collider)
    {
          collider.gameObject.GetComponent<Health>().Change(amount);
          OnDamage?.Invoke(amount);
    }
    Ответ написан
    21 комментарий
  • Почему не работает вкладка анимации и аниматора н Unity?

    @Ente
    Unity developer
    Чтобы заработали анимации, нужно создать AnimatorController в папке с проектом, затем перекинуть его на объект, который будет анимирован, выбрать его, затем во вкладке аниматора закинуть анимации.
    Ответ написан
    3 комментария
  • Объект не двигается, что делать?

    @Ente
    Unity developer
    Сделай это все на триггерах, сделай один скрипт Runner.cs

    1) повесь на каждого участника SphereCollider.
    2) поставь галочку IsTrigger на нем.
    3) добавь им rigidbody и сделай его кинематик.
    4) в поле target впиши его цель, тот трансформ, до которого ему бежать.
    5) поставь isReadyToRun галочку в инспектор на первого бегуна.

    [SerializedField] private Transform target;
    [SerializedField] private bool isReadyToRun;
    
    private void OnTriggerEnter()
    {
             isReadyToRun = !isReadyToRun;
    }
    
    private void Update()
    {
          if (!isReadyToRun) return;
          transform.position = Vector3.MoveTowards(transform.position, target, Time.deltaTime * 2f);
    }
    Ответ написан
    Комментировать
  • Почему освещение оставляет на текстурах полосы?

    @Ente
    Unity developer
    Выглядит так, как будто текстуру затайлили по Y, и сама текстура градиентна, отсюда этот эффект
    Ответ написан
    Комментировать
  • Как сделать управление RTS камеры на смартфонах?

    @Ente
    Unity developer
    1) Сделай такую конструкцию из gameobject'ов

    -NodeMove
    --NodeZoom
    ---NodeRotate
    ----Camera

    Затем сделай три скрипта, каждый из которых управляет только свои gameobjectом, т.е. NodeZoom может только управлять координатой Z. А NodeRotate крутить по Z. Таким образом у тебя никогда не получится ситуация, что при зуме начнет меняться координата X или Y на этом объекте. Само-собой, NodeMove только Х и Y.

    2) Далее в каждом скрипте делай проверку. Например, на зум можно игнорировать все ситуации, когда тачей != 2, а для передвижения != 1.
    Ответ написан
  • Почему при переходе на другую сцену она становится темной?

    @Ente
    Unity developer
    Сгенерируй лайтмапы для каждой сцены, тогда они будут с нормальным светом.
    Ответ написан
    1 комментарий
  • Как сделать чтобы спрайты не менялись во всех дубликатах сразу?

    @Ente
    Unity developer
    Не должно быть менеджеров никаких. Сделай два скрипта, один назови Health.cs, а второй HealthView.cs. Оба повесь на врага. В Health сделай поле здоровья, функцию на изменение и событие.

    Health.cs
    [SerializedField] private int hitpoints = 100;
    public Action<int, int> OnChange;
    
    public void Change(int amount)
    {
               hitpoints += amount;
               OnChange?.Invoke(hitpoints, amount);
    }


    HealthView.cs
    private void OnEnable()
    {
        GetComponent<Health>().OnChange += OnChange;
    }
    private void OnDisable()
    {
       GetComponent<Health>().OnChange -= OnChange;
    }
    
    private void OnChange(int hitpoints, int amount)
    {
        //здесь уже делай всю визуальную часть, основанную на значениях выше.
    }


    Если в дальнейшем будет лечение, то этот скрипт также поможет, так как можно передать положительное значение для лечения, отрицательное для удара. Для проверки гибели также заведи отдельный скрипт и также подписывайся на него, как в случае с HealthView, аналогично для выпадения лута. Каждое уникальное действие - отдельный скрипт и пусть подписываются, так их можно будет легко добавлять и убирать.
    Ответ написан
    Комментировать
  • Есть ли смысл в проверке activeInHierarchy?

    @Ente
    Unity developer
    Есть одно хорошее правило для любых популярных фреймворков: не пытайся быть умнее их. Unity не просаживается по скорости, если ты будешь включать включенный объект или выключать выключенный, все проверки уже включены внутри этих функций. А в примерах выше только засорение кода лишними проверками.
    Ответ написан
    Комментировать
  • Не устанавливается юнити из юнити хаба, что делать?

    @Ente
    Unity developer
    Выбери папку с латинскими именами, для установки и для самого установщика
    Ответ написан
  • Как изменять массово свойства элементам?

    @Ente
    Unity developer
    Создаешь скрипт AlphaChanger.cs, в нем такой код

    private SpriteRenderer spriteRenderer; //Кэшируем компонент
    [SerializeField] private float speed = 1; //Скорость фейдинга
            
    private void Awake()
    {
    	spriteRenderer = GetComponent<SpriteRenderer>();
    }
    
    public void Show()
    {
    	StartCoroutine(SetVisibility(1));
    }
    
    public void Hide()
    {
    	StartCoroutine(SetVisibility(0));
    }
    
    private IEnumerator SetVisibility(float finish)
    {
    	var color = spriteRenderer.color;
    	while (true)
    	{
    		color.a = Mathf.MoveTowards(color.a, finish, speed * Time.deltaTime);
    		spriteRenderer.color = color;
    		if (color.a == finish) break;
    		yield return null;
    	}
    }


    Вешаешь этот скрипт на все спрайты, которые будут фейдится. Если нужно вызвать его у детей gameobjecta, заводишь еще один скрипт AlphaChangerManager, в нем пишешь такие функции.

    private AlphaChanger[] alphaChangers; //Кэшируем компоненты детей
    private void Awake()
    {
    	alphaChangers = GetComponentsInChildren<AlphaChanger>();
    }
    
    public void ShowAll()
    {
    	alphaChangers.ForEach(a => a.Show());
    }
    
    public void HideAll()
    {
    	alphaChangers.ForEach(a => a.Hide());
    }


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

    @Ente
    Unity developer
    Создаешь два gameobjecta - один с кнопкой, второй со слайдером. У слайдера выключаешь возможность управлять через мышь и убираешь лишние элементы, чтобы получился слайдер с заполнением. Выставляешь MinMax = 0, 1;

    Затем заводишь скрипт ProgressBar.cs и вешаешь на Slider.

    [SerializeField] private Button activationButton;
    [SerializeField] private Slider progressSlider;
    [SerializeField] private float speed = 1;
    
    private void OnEnable()
    {
         activationButton.onClick.AddListener(Press);
    }
    
    private void OnDisable()
    {
         activationButton.onClick.RemoveListener(Press);
    }
    
    private void Press()
    {
        activationButton.onClick.RemoveListener(Press);
        StartCoroutine(Loop());
        IEnumerator Loop()
        {
            for (var i=progressSlider.value; i<1f; i+= Time.deltaTime * speed)
            {
                 progressSlider.value = i;
                 yield return null;
            }
        }
    }
    Ответ написан
    7 комментариев
  • Как передать позицию объекта скрипту, который висит на другом объекте без занесения в инспектор?

    @Ente
    Unity developer
    Сделай себе скрипт MovementSyncer.cs и пропиши в нем такой код
    [SerializedField] private bool isLeader; //переменная указывает, что данный объект лидер, а остальные повторяют
    [SerializedField] private string category; //переменная для разделения объектов на категории, например категория "синие", "красные"
    private MovementSyncer leader; //переменная для кеширования лидера на старте
    
    private void Awake() 
    {
        //найди объект-лидер для данной категории
        leader= FindObjectsOfType<MovementSyncer>().First(ms => ms.category == category && ms.isLeader);
    }
    
    private void Update()
    {
        if (isLeader) return; //пропускаем себя, еcли лидер
        transform.position = leader.transform.position;
    }
    Ответ написан
    2 комментария