对同一游戏对象执行多个操作的多个 True if 语句?



我正在创建一个小型游戏项目(第一次学习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);
}

我希望通过将变量更改为我想选择的其他多维数据集来轻松修改绿色立方体脚本,但显然不是,我不确定如何解决它。

首先而不是

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

而是使用

FindObjectOfType<bluescript>();

这更有效率。或者,如果可能的话,甚至根本不使用它,而是将相应的组件引用到检查器中已有的脚本中。


我真的不明白你想实现什么,但请注意,Input.GetMouseButtonDown(0)true在每个游戏对象上......不仅仅是你目前用鼠标指针悬停的游戏对象!

如果您想实现单击特定游戏对象(带有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);
    

    在这里,您销毁的是一个组件- 而不是游戏对象!我猜你想做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的代码。在greenscriptDestroy(blue)但在purplescript你依赖blue.bluetopurple..这似乎不对。


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

从我在这里看到的脚本中,您可以通过仅使用2 个单个脚本来简化它:

  • ScriptA:不依赖于任何其他脚本,而只是在单击时显示其颜色和布尔值
  • ScriptB:执行相同的操作,但仅在其他两个脚本的值为真时单击,更改其颜色,销毁其他脚本之一的游戏对象

其余的,例如要检查哪些值我该转向哪种颜色要销毁哪个对象,您可以通过检查器中的参数进行设置。所以你只会有

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立方体上,首先检查另外两个立方体。然后在检查器中配置所有参数,并已设置所有这些对象之间的引用。

每个立方体不应该有 3 个类......你应该有一个附加到所有立方体的类,以及一个变量,用于设置立方体的颜色,以及激活的布尔值。然后有一个主类,其中包含一个包含所有多维数据集的数组。并且您需要一个具有抽象方法Activate的抽象类,每个多维数据集扩展抽象类。在主类中单击多维数据集时,从中获取抽象类并调用方法 Activate。

最新更新