代码之家  ›  专栏  ›  技术社区  ›  David Adams

如何制作更好的落锤?

  •  1
  • David Adams  · 技术社区  · 7 年前

    我和一个朋友正在尝试学习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 回复  |  直到 7 年前
        1
  •  3
  •   CosmicGiant    4 年前

    有几件事你绝对可以改进。。。


    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>();
    

    它们分别是 array 和a list ; C#的许多收集数据类型中的两种。

    • 固定的 特定类型对象的元素数量。
    • 列表非常适合 元素的数量。

    其他类型包括: Set<> , Dictionary<> , Queue<> , Stack<>


    1. 请记住,您正在编程。只要可能,尽量使 机器 做那个努力工作的人。

    取而代之的是:

    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

    还有:

    • while ( while(/*condition evaluated before loop*/){/*some code*/} )
    • do-while ( do{/*some code*/}while(/*condition evaluated after loop*/) )
    • for-each ( foreach(var element in someCollection){/*some code*/} )

    1. 注意 !

    这个 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 甚至没有使用!


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

    如果你保持 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);
    

    1. 你应该始终如一。

    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;
    
        2
  •  1
  •   Shogunivar    7 年前

    首先,变量太多了。当你发现自己复制和粘贴代码时,你可能做错了什么。把那些坏小子都放进去 List<GameObject> 你可以得到同样的结果。

    我建议Mikko Koivisto回答的问题是制作另一个脚本来处理盒子的实际下降效果。但是为了把它全部保存在一个脚本中,我用了不同的方式处理它。

    我对你的代码做了一点修改,使它更干净,可读性更强。评论基本上反映了所有的变化。

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

    注意:为了让它工作,你必须在编辑器中将框添加到你的脚本中,你也可以在代码中这样做,但这要复杂得多。只需单击编辑器中的脚本,打开框列表,将大小设置为6,然后将它们全部拖到那里。

    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);
            } 
        }
    }
    
        3
  •  0
  •   Mikko Koivisto    7 年前

    “首先,如果我在同一个克隆中繁殖了多个克隆,它们就会被卡住,我认为我根本无法很好地处理空的游戏对象。”

    将其连接到每个盒子并删除克隆。使改变翻译落下脚本中的部分:

    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;
    
        4
  •  0
  •   Maxime    7 年前

    我认为你可以制作一个方框和克隆列表,这样你就可以分解你的代码(我不熟悉unity,所以可能会有拼写错误,但总体思路是:

            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)
            }