Несколько True, если операторы для нескольких действий на одном GameObject? - PullRequest
0 голосов
/ 14 июня 2019

Я создаю небольшой игровой проект (впервые изучаю C #, поэтому кодирование довольно ужасное).

У меня есть желтый куб, который меняет цвет на зеленый после того, как выбран желтый и синий кубыпо bools.Я сделал этот код работающим и скопировал его в фиолетовый скрипт на синем кубе, чтобы изменить его на фиолетовый.Играя в игру, выполняется скрипт зеленого цвета, даже если щелкнуть красный куб, а ручная проверка bools в инспекторе игнорирует фиолетовую часть скрипта.

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

Синий скрипт на кубе (работает)

    public bool bluetopurple = false;
// Use this for initialization
void Start () {

}

// Update is called once per frame
void Update () {
    Renderer render = GetComponent<Renderer>();
    render.material.color = Color.blue;

    if (Input.GetMouseButtonDown (0)) {
        bluetopurple = true;

    }

Зеленый скрипт (работает)

public class greenscript : MonoBehaviour {
    public GameObject yellow;
    public yellowscript yellow1;
    public GameObject blue;
    public bluescript blue1;
    public bool green;


// Use this for initialization
void Start () {
    blue1 = GameObject.Find("blue").GetComponent<bluescript> ();
    blue1.bluetopurple = false;

    yellow1 = GameObject.Find("yellow").GetComponent<yellowscript> ();
    yellow1.yellowchange = false; 
    green = false;

}

// Update is called once per frame
void Update () {
    if (yellow1.yellowchange == true) {
        if (blue1.bluetopurple == true) {
            if (Input.GetMouseButtonDown (0)) {
                green = true; 
            }
            if (green == true) {
                Renderer render = GetComponent<Renderer> ();
                render.material.color = Color.green;
                Destroy ((blue), 0.0f);
            }

Фиолетовый скрипт (не работает, переменные были изменены правильно и неткоды ошибок появляются в отладчике):

public class purplescript : MonoBehaviour {
public GameObject red;
public redscript red1;
public GameObject blue;
public bluescript blue1;
public bool purple;


// Use this for initialization
void Start () {
    blue1 = GameObject.Find("blue").GetComponent<bluescript> ();
    blue1.bluetopurple = false;

    red1 = GameObject.Find("red").GetComponent<redscript> ();
    red1.redtopurple = false;
    purple = false;

}

// Update is called once per frame
void Update () {
    if (red1.redtopurple == true) {
        if (blue1.bluetopurple == true) {
            if (Input.GetMouseButtonDown (0)) {
                purple = true; 
            }
            if (purple == true) {
                Renderer render = GetComponent<Renderer> ();
                render.material.color = Color.magenta;
                Destroy ((red), 0.0f);
            }

Я ожидал, что скрипт зеленого куба будет легко модифицирован путем замены переменных на другие кубы, которые я хотел выбрать, но, очевидно, нет, и я не уверен, какисправить это.

Ответы [ 2 ]

0 голосов
/ 14 июня 2019

Прежде всего вместо

GameObject.Find("blue").GetComponent<bluescript>();

скорее используйте

FindObjectOfType<bluescript>();

это намного эффективнее. Или, если возможно, даже не используйте его вообще, а скорее ссылайтесь на соответствующие компоненты на сценарии, которые уже есть в Инспекторе.


Я не совсем понял, чего вы пытаетесь достичь, но учтите, что Input.GetMouseButtonDown(0) - это true на каждый GameObject ... не только тот, который вы в данный момент наводите мышкой!

Если вы хотите реализовать что-то, что должно произойти, когда вы щелкаете по определенному GameObject (с Collider или GUIElement), тогда лучше использовать OnMouseDown. Также вы делаете много ненужных вещей в Update, который называется каждый кадр, поэтому могут быть и некоторые проблемы.

Тогда в вашем коде много мелких проблем

  1. для вашего синего сценария

    Renderer render = GetComponent<Renderer>();
    render.material.color = Color.blue;
    

    Наличие этого в вашем Update методе не имеет смысла, потому что

    • крайне неэффективно вызывать GetComponent снова и снова, особенно каждый кадр
    • вы ничего не меняете этим ... так что устанавливайте цвет только один раз при запуске

    так что, скорее всего, он должен выглядеть примерно так:

    public class bluescript : MonoBehaviour
    {
        public bool bluetopurple = false;
    
        // Use this for initialization
        private void Start () 
        {
            Renderer render = GetComponent<Renderer>();
            render.material.color = Color.blue;
        } 
    
        // Catch the mousedown
        private void OnMouseDown()
        {
            bluetopurple = true;
        }
    }
    
  2. аналогичные проблемы также встречаются в гринскрипте. Вы вызываете один и тот же код снова и снова, каждый кадр в Update, blue может быть не установлен, поэтому он не может быть уничтожен, но выдает ошибку. Также

    Destroy(blue, 0.0f);
    

    Здесь вы уничтожаете Компонент , а не GameObject! Я думаю, вы хотели сделать Destroy(blue.gameObject); .. также пропуск 0.0f можно пропустить, потому что это все равно 0 по умолчанию.

    public class greenscript : MonoBehaviour 
    {
        // If possible set these already in the Inspector and don't use
        // Find and GetComponent at all
        public yellowscript yellow;
        public bluescript blue;
        public Renderer render;
    
        public bool green;
    
        // Use this for initialization
        private void Start () 
        {
            Renderer render = GetComponent<Renderer>();
    
            blue = FindObjectOfType<bluescript>();
            blue.bluetopurple = false;
    
            yellow = FindObjectOfType<yellowscript> ();
            yellow.yellowchange = false; 
    
            green = false;
        }
    
        private void OnMouseDown()
        {
            if (!yellow.yellowchange) return;
    
            // if you destroyed the blue GameObject already
            // checking this again would throw an error so catch that case
            if(!blue) return;
    
            if (!blue.bluetopurple) return;
    
            green = true;
    
            render.material.color = Color.green;
    
            Destroy(blue.gameObject);
        }
    }
    
  3. И, наконец, комментарий

    public class purplescript : MonoBehaviour 
    {
        public redscript red;
        public bluescript blue;
        public Renderer render;
    
        public bool purple;
    
        // Use this for initialization
        void Start() 
        {
            Renderer render = GetComponent<Renderer>();
    
            blue = FindObjectOfType<bluescript>();
            blue.bluetopurple = false;
    
            red = FindObjectOfType<redscript>();
            red.redtopurple = false;
    
            purple = false;
        }
    
        private void OnMouseDown()
        {
            // here again check if the object still exists first
            if(!red) return;
    
            if(!red.redtopurple) return;
            if(!blue.bluetopurple) return;
    
            purple = true;
    
            render.material.color = Color.magenta;
    
            Destroy(red.gameObject);
        }
    }
    

Вы не показали код для redscript и yellowscript. В greenscript вы Destroy(blue), но в purplescript вы полагаетесь на blue.bluetopurple .. это не так.


Альтернативное и более масштабируемое / обслуживаемое решение

Из сценариев, которые я вижу здесь, вы можете значительно упростить это, используя только 2 одинарных сценария a:

  • ScriptA: не полагается ни на какой другой скрипт, а только изменяет его цвет и изменяется при нажатии
  • ScriptB: Kind of делает то же самое, но выполняет щелчок, только если значения двух других сценариев имеют значение true, меняет цвет, уничтожает один из других сценариев GameObjects

Все остальные, как Какие значения для проверки , , какой цвет мне превратить в , , какой объект уничтожить , вы можете установить через параметры в Инспекторе , Таким образом, у вас будет только

public class ScriptA : MonoBehaviour
{
    [Header("Base-Components")]
    public Renderer renderer;

    [Header("Base-Settings")]
    // start with this color
    public Color InitialColor = Color.white;
    // turn to this after being clicked
    public Color TargetColor = Color.white;

    [Header("Values")]
    public bool WasClicked;

    private void Awake()
    {
        SetUp();
    }

    private void SetUp()
    {
        if(!renderer) renderer = GetComponent<Renderer>();
        renderer.material.color = InitialColor;

        WasClicked = false;
    }

    private void OnMouseDown()
    {
        HandleClick();
    }

    // make this virtual so we can extend/overwrite it in child classes
    protected virtual void HandleClick()
    {
        WasClicked = true;
        renderer.material.color = TargetColor;
    }
}

Теперь, поскольку второй скрипт очень похож, но он расширяет только наследуемое от ScriptA поведение. Это означает, что он будет иметь все уже реализованные свойства и методы, но теперь вы можете расширить те, которые реализованы как virtual:

public class ScriptB : MonoBehaviour
{
    // What does this script have, ScriptA didn't?
    [Header("Additional Components")]
    // The two components you want to check the bool for
    public ScriptA FirstToCheck;
    public ScriptA SecondToCheck;
    [Space]
    // The component you want to destroy
    public ScriptA ToDestroy;

    // Overwrite/Extend the behaviour of HandleClick
    protected virtual void HandleClick()
    {
        // One of the references doesn't exist 
        // so object was probably already destroyed
        if(!ToDestroy || !FirstToCheck || !SecondToCheck) return;

        // One of the objects wasn't clicked yet
        if(!FirstToCheck.WasClicked || !SecondToCheck.WasClicked) return;

        // Do what the parent implemented
        // in this case set my bool and change my color
        base.HandleClick();

        Destroy(ToDestroy.gameObject);
    }
}

Поместите ScriptA в куб (ы), которые не зависят от других для активации. И ScriptB на кубах, которые сначала проверяют два других куба. Затем настройте все параметры в Инспекторе и уже установите ссылки между всеми этими объектами.

0 голосов
/ 14 июня 2019

у вас не должно быть 3 классов для каждого куба ... У вас должен быть класс, прикрепленный ко всем кубам, и переменная, которая устанавливает инспектор, какой цвет у куба, и bool actived.Тогда есть основной класс, который содержит массив со всеми кубами.И вам нужен абстрактный класс с абстрактным методом Activate, каждый куб расширяет абстрактный класс.В основном классе, когда вы нажимаете на куб, возьмите из него абстрактный класс и вызовите метод Activate.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...