Проблема с изменением цвета объекта игрока - PullRequest
1 голос
/ 27 апреля 2020

Я делаю небольшую платформенную игру, и в этом я создал сцену, где вы можете изменить цвет своего игрока. Я сделал 3 кнопки, которые меняют цвет при нажатии на них. Я также сделал два файла кода, но они не работают. Я также не вижу ошибок в консоли. PS Код и кнопки для изменения цвета находятся на другой сцене, нежели игровой объект.

Это код для кнопок, которые меняют цвет:

using System;              
using System.Collections;                                
using System.Collections.Generic;
using UnityEngine;

public class ColourManager : MonoBehaviour
{
    public static int colour;

    public void DefaultBlue()
    {
        colour = 0;
    }

    public void Green()
    {
        colour = 1;
    }

    public void Red()
    {
        colour = 2;
    }

}

Это код на Сам игровой объект:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ColourTarget : MonoBehaviour
{
    void Start()
    {
        rend = GetComponent<Renderer>();

        rend.sharedMaterial = materials[0];

        rend.enabled = true;
    }

    private Renderer rend;

    public int lcolour = ColourManager.colour;
    public Material[] materials;

    private void Update()
    {
        if (lcolour == 0)
        {
            rend.sharedMaterial = materials[0];
        }

        if (lcolour == 1)
        {
            rend.sharedMaterial = materials[1];
        }

        if (lcolour == 2)
        {
            rend.sharedMaterial = materials[2];
        }
    }
}

1 Ответ

2 голосов
/ 27 апреля 2020
  1. Обратите внимание, что изменение sharedMaterial может быть не тем, что вы хотите сделать здесь.

    Если вы хотите изменить материал рендерера вместо этого используйте материал.

    , поэтому лучше использовать material. Особенно, если, например, цвет был изменен, и вы имеете дело с инстансированными материалами, впоследствии изменение общего материала не имеет никакого эффекта.

  2. Тогда не делайте этого в Update! Это очень избыточная и неэффективная установка этого каждого кадра !

  3. Наконец, обратите внимание, что этому

    public int lcolour = ColourManager.colour;
    

    назначается только ONCE в тот момент, когда этот объект инициализируется, а затем уже никогда не изменяется ... int является типом VALUE , а не ссылкой!

    Я бы предпочел использовать и event и сделать Ваша цель прослушивает любые изменения.

Так что ваш код может выглядеть как

public class ColourManager : MonoBehaviour
{
    public static int colour;

    // we will invoke this event everytime the color index is changed
    // and directly pass the according new index in
    public static event Action<int> OnColourIndexChanged;

    public void DefaultBlue()
    {
        colour = 0;

        // The ? is a null check and only 
        // calls Invoke if there is at least one listener to this event
        OnColourIndexChanged?.Invoke(colour);
    }

    public void Green()
    {
        colour = 1;

        OnColourIndexChanged?.Invoke(colour);
    }

    public void Red()
    {
        colour = 2;

        OnColourIndexChanged?.Invoke(colour);
    }
}

, а затем

public class ColourTarget : MonoBehaviour
{
    [SerializeField] private Renderer _renderer;
    public Material[] materials;

    private void Awake()
    {
        if(!_renderer) _renderer = GetComponent<Renderer>();

        _renderer.enabled = true;

        // Add a callback to the event
        // Removing it first is save also if it wasn't added so far
        // This just makes sure it is always added only exactly once
        ColourManager.OnColourIndexChanged -= UpdateMaterial;
        ColourManager.OnColourIndexChanged += UpdateMaterial;

        // do the first update now with the current state
        UpdateMaterial(ColourManager.colour);
    }

    // Now this is called only when the value is changed in the manager
    // script and once at the beginning with the initial state
    private void UpdateMaterial(int index)
    {
        // check for validity
        if(index < 0 || index >= materials.Length) return;

        _renderer.material = materials[index];
    }

    private void OnDestroy()
    {
        // Always make sure to clean up listeners once not needed anymore
        // otherwise you get NullReferencExceptions
        ColourManager.OnColourIndexChanged -= UpdateMaterial;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...