多个True if语句用于同一GameObject上的多个动作?

时间:2019-06-14 03:23:20

标签: c# unity3d

我正在创建一个小游戏项目(第一次学习C#,因此编码非常糟糕)。

我有一个黄色的立方体,在通过布尔选择黄色和蓝色的立方体之后,其颜色会变为绿色。我使该代码正常工作,并将其复制到蓝色立方体上的紫色脚本中,以将其更改为紫色。即使单击红色立方体并手动检查检查器中的布尔值,玩游戏也会执行绿色脚本,而忽略脚本的紫色操作部分。

代码通过选择一个多维数据集并选择另一个多维数据集来工作,第一个多维数据集执行脚本,该脚本会导致颜色变化并杀死第二个多维数据集。选择的蓝色立方体和黄色立方体将蓝色立方体变成绿色立方体,并杀死黄色立方体。当我想通过修改后的绿色立方体代码选择蓝色立方体和红色立方体时,该代码无法执行。

多维数据集上的蓝色脚本(正在运行)

    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 :(得分:0)

每个多维数据集都不应该有3个类...您应该为所有多维数据集附加一个类,并设置一个变量来设置检查器多维数据集的颜色,并激活bool。然后有一个主类,其中包含一个包含所有多维数据集的数组。您需要一个具有抽象方法Activate的抽象类,每个多维数据集都扩展了该抽象类。在主类中,单击多维数据集时,从中获取抽象类并调用方法Activate。

答案 1 :(得分:0)

首先代替

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

宁可使用

FindObjectOfType<bluescript>();

这是更有效的方法。或者,甚至根本不使用它,而是将相应的组件引用到Inspector中已经存在的脚本中。


我不太了解您要达到的目标,但请注意,{strong>每个游戏对象上的Input.GetMouseButtonDown(0)true。鼠标指针!

如果您想实现单击特定GameObject(带有ColliderGUIElement)时应该发生的事情,请使用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);
    

    在这里您破坏了 Component -不是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);
        }
    }
    

您没有显示redscriptyellowscript的代码。在greenscript中,您Destroy(blue),但是在purplescript中,您依靠blue.bluetopurple ..这似乎不正确。


替代方案和更好的可扩展性/可维护性

从我在这里看到的脚本中,您可以仅使用 2个单个脚本来简化很多操作:

  • ScriptA:不依赖其他任何脚本,而只是在点击时更改其颜色和布尔值
  • ScriptB:种类相同,但仅在其他两个脚本的值为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首先检查另外两个多维数据集。然后,在检查器中配置所有参数,并已经在所有这些对象之间设置了引用。