如何制作更好的坠落块?

时间:2017-10-31 15:57:47

标签: c# performance unity3d unity3d-2dtools

我和一个朋友正在尝试学习Unity和c#,所以我们可以尝试制作游戏。我的朋友遇到逻辑运算符问题,所以我试图制作一个简单的程序,当你按下某些键组合时会导致块掉落。(他在没有视觉辅助的情况下非常依旧)我能够把东西放在一起但它非常粗糙,我觉得还有很多方法可以解决这个问题。这是我通过大量试验和错误设法编写的内容。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Falling : MonoBehaviour {

    public float fallspeed = 8.0f;
    bool a;
    bool b;
    private GameObject box_0;
    private GameObject box_2;
    private GameObject box_3;
    private GameObject box_4;
    private GameObject box_5;
    private GameObject box_6;
    private GameObject clone;
    private GameObject clone1;
    private GameObject clone2;
    private GameObject clone3;
    private GameObject clone4;
    private GameObject clone5;
    // Use this for initialization
    void Start () {
        a = false;
        b = false;
        box_0 = GameObject.Find("box_0");
        box_2 = GameObject.Find("box_2");
        box_3 = GameObject.Find("box_3");
        box_4 = GameObject.Find("box_4");
        box_5 = GameObject.Find("box_5");
        box_6 = GameObject.Find("box_6");
    }

    // Update is called once per frame
    void Update () {
        // makes box_0 fall if a key is pressed
        if (Input.GetKeyDown (KeyCode.A)) {
            a = true;
            if (a) {
                clone = Instantiate (box_0, transform.position, Quaternion.identity);
                a = false;
            }
        }
        if (Input.GetKeyDown (KeyCode.B) || Input.GetKeyDown (KeyCode.C)) {
            a = true;
            if (a) {
                clone1 = Instantiate (box_2, transform.position, Quaternion.identity);
                a = false;
            }
        }
        if (Input.GetKeyDown (KeyCode.Q) && Input.GetKeyDown (KeyCode.E)) {
            a = true;
            if (a) {
                clone2 = Instantiate (box_3, transform.position, Quaternion.identity);
                a = false;
            }
        }
        if (Input.GetKeyDown (KeyCode.R) || (Input.GetKey (KeyCode.LeftShift) && Input.GetKeyDown (KeyCode.S)) ) {
            a = true;
            if (a) {
                clone3 = Instantiate (box_4, transform.position, Quaternion.identity);
                a = false;
            }
        }
        if (Input.GetKeyDown (KeyCode.U)) {
            a = true;
            if (a) {
                clone4 = Instantiate (box_5, transform.position, Quaternion.identity);
                a = false;
            }
        }
        if (Input.GetKeyDown (KeyCode.I)) {
            a = true;
            if (a) {
                clone5 = Instantiate (box_6, transform.position, Quaternion.identity);
                a = false;
            }
        }
        //makes clones fall if they exist
        if (clone != null) {
            clone.transform.Translate (Vector3.down * fallspeed * Time.deltaTime, Space.World);
        } else if (clone1 != null) {
            clone1.transform.Translate (Vector3.down * fallspeed * Time.deltaTime, Space.World);
        } else if (clone2 != null) {
            clone2.transform.Translate (Vector3.down * fallspeed * Time.deltaTime, Space.World);
        } else if (clone3 != null) {
            clone3.transform.Translate (Vector3.down * fallspeed * Time.deltaTime, Space.World);
        } else if (clone4 != null) {
            clone4.transform.Translate (Vector3.down * fallspeed * Time.deltaTime, Space.World);
        } else {
            if (clone5 != null) {
                clone5.transform.Translate (Vector3.down * fallspeed * Time.deltaTime, Space.World);
            }
        }
    }
}

代码功能正常但有问题。对于一个,如果我产生更多然后一个相同的克隆他们被卡住,我不认为我完全处理空游戏对象。谁能给我一些关于如何做得更好的建议呢?

(同样,如果它的相关性在屏幕顶部排列有六个彩色块,当按下某些键时,会创建正在参考的块的克隆并使其下降。该块具有对撞机并且当它撞到屏幕的底部时会撞到另一个对撞机并被摧毁。)

4 个答案:

答案 0 :(得分:3)

你可以肯定改进的一些事情......

1.如果有实例集合,请使用适合集合的数据结构。

而不是:

private GameObject box_0;
private GameObject box_2; //<<<That typo tho!
private GameObject box_3;
private GameObject box_4;
private GameObject box_5;
private GameObject box_6;
//...

你可以而且应该这样做:

private GameObject[] boxes = new GameObject[6];
private List<GameObject> clones = new List<GameObject>();

这些分别是arraylist; C#的许多集合数据类型中的两个。

  • 阵列非常适合固定某种类型对象的元素。
  • 列表非常适合动态元素。

其他类型包括:Set<>Dictionary<>Queue<>Stack<>等等;每个都有它自己的最佳用例。

2.记住你正在编程。尽可能尝试让机器成为努力工作的人。

而不是:

box_0 = GameObject.Find("box_0");
box_2 = GameObject.Find("box_2"); //<<<That typo tho!
box_3 = GameObject.Find("box_3");
box_4 = GameObject.Find("box_4");
box_5 = GameObject.Find("box_5");
box_6 = GameObject.Find("box_6");

你可以拥有:

for(int i=0; i<6; i++)
    boxes[i] = GameObject.Find("box_"+i);

这称为循环。当您需要多次重复执行任务时,这是执行此操作的方法。更具体地说,这是一个for循环。

还有:

  • whilewhile(/*condition evaluated before loop*/){/*some code*/}
  • do-whiledo{/*some code*/}while(/*condition evaluated after loop*/)
  • for-eachforeach(var element in someCollection{/*some code*/}
  • 和其他人一起。

3.注意裁员

a变量:

if (Input.GetKeyDown (KeyCode.A)) {
    a = true;
    if (a) {
        clone = Instantiate (box_0, transform.position, Quaternion.identity);
        a = false;
    }
}
if (Input.GetKeyDown (KeyCode.B) || Input.GetKeyDown (KeyCode.C)) {
    a = true;
    if (a) {
        clone1 = Instantiate (box_2, transform.position, Quaternion.identity);
        a = false;
    }
}
//...

没有 b甚至没有使用过!

4.如果克隆是动态的(有时可能为空,有时不是),您可以动态处理它们!

如果您将clones 列表保留为现有克隆列表,而不是可能的克隆列表,那么以后会更容易自动化!

if (Input.GetKeyDown (KeyCode.A))
    clones.Add(Instantiate(boxes[0], transform.position, Quaternion.identity));
if (Input.GetKeyDown (KeyCode.B) || Input.GetKeyDown (KeyCode.C))
    clones.Add(Instantiate(boxes[1], transform.position, Quaternion.identity);
//...

稍后,而不是:

if (clone != null) {
    clone.transform.Translate (Vector3.down * fallspeed * Time.deltaTime, Space.World);
} else if (clone1 != null) {
    clone1.transform.Translate (Vector3.down * fallspeed * Time.deltaTime, Space.World);
} else if (clone2 != null) {
    clone2.transform.Translate (Vector3.down * fallspeed * Time.deltaTime, Space.World);
} else if (clone3 != null) {
    clone3.transform.Translate (Vector3.down * fallspeed * Time.deltaTime, Space.World);
} else if (clone4 != null) {
    clone4.transform.Translate (Vector3.down * fallspeed * Time.deltaTime, Space.World);
} else {
    if (clone5 != null) {
        clone5.transform.Translate (Vector3.down * fallspeed * Time.deltaTime, Space.World);
    }
}

你可以这样做:

foreach(var clone in clones)
    clone.transform.Translate (Vector3.down * fallspeed * Time.deltaTime, Space.World);

5.你应该保持一致。

private GameObject box_0;
private GameObject box_2; //<<<NOPE! should be box_1!
//And others should follow the sequence from 1!
private GameObject box_3;
private GameObject box_4;
private GameObject box_5;
private GameObject box_6;

private GameObject clone; //<<<NOPE! Should be 'clone_0', 'clone_1' etc...
private GameObject clone1;
private GameObject clone2;
private GameObject clone3;
private GameObject clone4;
private GameObject clone5;

答案 1 :(得分:1)

首先,这个变量太多了。当您发现自己复制并粘贴代码时,您可能会做错事。把所有那些坏男孩放在一些List<GameObject>中,你就可以达到同样的效果。

我推荐的是Mikko Koivisto回答的问题,那就是制作另一个脚本来处理盒子的实际落下效果。但是为了将它全部保存在一个脚本中,我以不同的方式处理它。

我稍微更改了你的代码,因此它更清晰,更具可读性。评论基本上告诉了所有的变化。

至于为什么旧箱子卡住了。在创建新克隆时,您一直覆盖克隆变量。那么在更新中,您的旧克隆将不再更新,因为它们不再在变量中定义,因此它们停止了下降。

  

注意:为了使其正常工作,您必须在编辑器中将这些框添加到您的脚本中,您也可以在代码中执行此操作,但这样做会更加混乱。只需在编辑器中单击脚本,打开框列表,将大小放在六个上,然后将它们全部拖到那里。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Falling : MonoBehaviour
{

    public float fallspeed = 8.0f;
    //removed bool a, b because they never get used anymore

    //"boxes" is public so you can add the boxes in the editor instead of having to do it in your start function
    public List<GameObject> boxes;  //Instead of 6 different variables you could just throw them all in a list
    private List<GameObject> clones; //Same here

    // Update is called once per frame
    void Update()
    {

        // makes box_0 fall if a key is pressed
        //Not sure why you were checking if(a) constantly when you set it true 1 line ahead, how could it be false? I took the liberty to remove that
        if (Input.GetKeyDown(KeyCode.A))
        {
            clones.Add(Instantiate(boxes[0], transform.position, Quaternion.identity)); //No need for different variables, just throw them all in one list
        }
        if (Input.GetKeyDown(KeyCode.B) || Input.GetKeyDown(KeyCode.C))
        {
             clones.Add(Instantiate(boxes[1], transform.position, Quaternion.identity));
        }
        if (Input.GetKeyDown(KeyCode.Q) && Input.GetKeyDown(KeyCode.E))
        {
            clones.Add(Instantiate(boxes[2], transform.position, Quaternion.identity));
        }
        if (Input.GetKeyDown(KeyCode.R) || (Input.GetKey(KeyCode.LeftShift) && Input.GetKeyDown(KeyCode.S)))
        {
            clones.Add(Instantiate(boxes[3], transform.position, Quaternion.identity));
        }
        if (Input.GetKeyDown(KeyCode.U))
        {
            clones.Add(Instantiate(boxes[4], transform.position, Quaternion.identity));
        }
        if (Input.GetKeyDown(KeyCode.I))
        {
            clones.Add(Instantiate(boxes[5], transform.position, Quaternion.identity));
        }


        //Instead of checking if any of them exist you can just loop through the list with clones and make them all fall
        foreach (GameObject clone in clones)
        {
            clone.transform.Translate(Vector3.down * fallspeed * Time.deltaTime, Space.World);
        } 
    }
}

答案 2 :(得分:0)

“如果我产生更多然后一个同样的克隆,他们会被卡住,我不认为我完全处理了空游戏对象。”

将其附加到每个框并从Falling-script中删除clone.transform.Translate部分:

public class BoxScript : MonoBehaviour {

    public float fallspeed = 8.0f;
    public bool fall = false;
    void Update () {
        if (fall) {
            transform.Translate (Vector3.down * fallspeed * Time.deltaTime, Space.World);
        }
    }
}

...然后在创建新框时:

clone = Instantiate (box_0, transform.position, Quaternion.identity);
clone.fall = true;

答案 3 :(得分:0)

我认为你可以制作一个盒子和克隆的列表,这样你就可以对你的代码进行分解(我不熟悉统一,所以可能存在拼写错误,但一般的想法是:

        var clones = new List<GameObject>();
        GameObject box = null;
        if (Input.GetKeyDown(KeyCode.A))
        {
            box = box_0
        }
        // else if ... box = box_1 ...
        // end of your series of else if
        if (box != null)
        {
            clone = Instantiate(box, transform.position, Quaternion.identity);
            clones.Add(clone);
        }
        box = null;
        //   
        foreach (GameObject clone in clones)
        {
            clone.transform.Translate(Vector3.down * fallspeed * Time.deltaTime, Space.World)
        }