Прежде всего вместо
GameObject.Find("blue").GetComponent<bluescript>();
скорее используйте
FindObjectOfType<bluescript>();
это намного эффективнее. Или, если возможно, даже не используйте его вообще, а скорее ссылайтесь на соответствующие компоненты на сценарии, которые уже есть в Инспекторе.
Я не совсем понял, чего вы пытаетесь достичь, но учтите, что Input.GetMouseButtonDown(0)
- это true
на каждый GameObject ... не только тот, который вы в данный момент наводите мышкой!
Если вы хотите реализовать что-то, что должно произойти, когда вы щелкаете по определенному GameObject (с Collider
или GUIElement
), тогда лучше использовать OnMouseDown
. Также вы делаете много ненужных вещей в Update
, который называется каждый кадр, поэтому могут быть и некоторые проблемы.
Тогда в вашем коде много мелких проблем
для вашего синего сценария
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;
}
}
аналогичные проблемы также встречаются в гринскрипте. Вы вызываете один и тот же код снова и снова, каждый кадр в 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);
}
}
И, наконец, комментарий
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
на кубах, которые сначала проверяют два других куба. Затем настройте все параметры в Инспекторе и уже установите ссылки между всеми этими объектами.