Unity C # спрайт, постоянно меняющий цвет - PullRequest
0 голосов
/ 07 октября 2019

Поэтому я пытаюсь создать этот скрипт, который меняет цвет спрайта, когда я выполняю метод OnMouseDown (). Изменение цвета должно выполняться каждые 2 секунды. В приведенном ниже коде цвета меняются только один раз по какой-то причине.

Я уже пробовал сопрограммы. Но по какой-то причине они не сработали.

Пожалуйста, помогите, спасибо,

public bool startstop = false;
SpriteRenderer m_SpriteRenderer;

IEnumerator Changecolor() {
    yield return new WaitForSeconds(3);
    int random = Random.Range(1, 4);
    if (random == 1) {
        this.m_SpriteRenderer = this.GetComponent<SpriteRenderer>();
        this.m_SpriteRenderer.color = Color.blue;
    } else if (random == 2) {
        this.m_SpriteRenderer = this.GetComponent<SpriteRenderer>();
        this.m_SpriteRenderer.color = Color.red;
    } else if (random == 3) {
        this.m_SpriteRenderer = this.GetComponent<SpriteRenderer>();
        this.m_SpriteRenderer.color = Color.green;
    } else {
        this.m_SpriteRenderer = this.GetComponent<SpriteRenderer>();
        this.m_SpriteRenderer.color = Color.yellow;
    }

    this.StartCoroutine("Changecolor", 3f);
}

private void OnMouseDown() {
    if (this.startstop) {
        this.StartCoroutine("Changecolor", 3f);
        this.startstop = !this.startstop;
    } else {
        this.StopCoroutine("Changecolor");
        this.startstop = !this.startstop;
    }
}

Нет ошибок, просто не работает.

Ответы [ 4 ]

2 голосов
/ 07 октября 2019

Обратите внимание, что второй передаваемый вами параметр (3f)

StartCoroutine ("Changecolor", 3f);

ничего не делает, поскольку ваш Changecolor не принимает аргументов ...


Iфактически предложил бы вообще не использовать Coroutine, а скорее InvokeRepeating и CancelInvoke

void Changecolor()
{
    // Either in Awake or as lazy initialization
    if(!m_SpriteRenderer) m_SpriteRenderer = GetComponent<SpriteRenderer>();

    int random = Random.Range(1, 4);
    switch(random)
    {
        case 1:
            m_spriteRenderer.color = Color.blue;
            break;

        case 2:
            m_spriteRenderer.color = Color.red;
            break;

        case 3:
            m_spriteRenderer.color = Color.green;
            break;

        default:
            m_spriteRenderer.color = Color.yellow;
            break;
    }
}

private void OnMouseDown() 
{
    startstop = !startstop;
    if (this.startstop) 
    {
        InvokeRepeating(nameof(Changecolor), 0f, 2f);
    } 
    else 
    {
        CancelInvoke(nameof(Changecolor));
    }
}
2 голосов
/ 07 октября 2019

У вас есть Collider на объекте? Для запуска события OnMouseDown требуется Collider.

Код в основном работает, но далек от качества.
- Один раз вызовите GetComponent(), а затем кешируйте результат. Этот вызов очень дорогой.
- Изначально вам нужно щелкнуть два раза, так как сопрограмма будет остановлена ​​при первом щелчке.

Вот код с некоторыми улучшениями:

        public bool m_isRunning = false;
        public SpriteRenderer m_spriteRenderer;

        private void Start() {

            m_spriteRenderer = this.GetComponent<SpriteRenderer>();
        }

        private IEnumerator Changecolor() {

            yield return new WaitForSeconds(3);

            int random = Random.Range(1, 4);
            if (random == 1) {
                m_spriteRenderer.color = Color.blue;
            } else if (random == 2) {
                m_spriteRenderer.color = Color.red;
            } else if (random == 3) {
                m_spriteRenderer.color = Color.green;
            } else {
                m_spriteRenderer.color = Color.yellow;
            }

            this.StartCoroutine("Changecolor", 3f);
        }

        private void OnMouseDown() {
            m_isRunning = !m_isRunning;

            if (m_isRunning) {
                StartCoroutine("Changecolor", 3f);
            } else {
                StopCoroutine("Changecolor");
            }
        }
1 голос
/ 07 октября 2019

Код, который вы предоставили, работает очень хорошо, и грехи, вы говорите, цвет меняется только один раз, я предполагаю, что у вас есть коллайдер на объекте, к которому прикреплен скрипт, единственное, что вы должны изменить, это продолжение вызова GetComponent<SpriteRenderer>потому что это довольно дорого и должно вызываться только в Start или Awake другой вещи, которая не важна, и в этом нет ничего плохого, но это как-то меня теряет, это созданиеновая сопрограмма в конце старой, почему бы не сделать что-то вроде этого:

private Coroutine _colorChanger;

private SpriteRenderer _renderer;

void Start() //Can be Awake, whichever you choose
{
    _renderer = GetComponent<SpriteRenderer>();

    if (_renderer == null)
    {
        Debug.Log("No sprite found.");

        return;
    }
    //This is performed if OnMouseDown is implemented, if you implement the Update with Input.GetKeyDown, then this can be removed
    var collider = GetComponent<Collider>();

    if (collider == null)
    {
        collider = gameObject.AddComponent<BoxCollider>(); //or BoxCollider2D if you are applying the script to the sprite itself.
    }
    collider.isTrigger = true;

}

private void OnMouseDown() //this can be swapped out for what Saif wrote, a Update method which checks if the button is down, should be GetKeyDown instead of GetKey, having it that way will eliminate the need for a collider/UI element
{
    if (_colorChanger == null)
    {
        _colorChanger = StartCoroutine(ChangeColor(2f));
    }
    else
    {
        StopCoroutine(_colorChanger);

        _colorChanger = null;
    }
}

IEnumerator ChangeColor(float timeoutSec)
{
    while (true)
    {
        yield return new WaitForSeconds(timeoutSec);

        int random = Random.Range(1, 5); //Change max from 4 to 5

        if (random == 1)
        {
            _renderer.color = Color.blue;
        }
        else if (random == 2)
        {
            _renderer.color = Color.red;
        }
        else if (random == 3)
        {
            _renderer.color = Color.green;
        }
        else
        {
            _renderer.color = Color.yellow;
        }
    }
}

Обновление: только что заметил что-то, что другие пропустили, вы должны изменить Random.Range(1, 4) на Random.Range(1, 5) или желтыйцвет никогда не вступит в силу.

A preview of the color change using the above script, turn on and turn off

0 голосов
/ 07 октября 2019

Ваш код верен, никаких проблем с ним нет, за исключением того, что функция OnMouseDown() не будет вызываться, поскольку вы не нажимаете ни на триггеры блока, ни на элементы пользовательского интерфейса. Поэтому попробуйте использовать функцию обновления, как указано ниже:

void Update()
    {
        if (Input.GetKey(KeyCode.Mouse0))
        {
            if (startstop == false)
            {
                StartCoroutine("Changecolor", 3f);
                this.startstop = !this.startstop;
            }
            else
            {
                StopCoroutine("Changecolor");
                this.startstop = !this.startstop;
            }
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...