一、关于 显示分数时,如何让函数之间相互交流
这是一个非常好的逻辑问题
1 思路:主要涉及到两个脚本文件 1是主逻辑GameController脚本 2是挂在被击碎会加分的敌人身上的Collision脚本
GameController脚本(挂载在Hierarchy中的空物体GameController上)
public class GameController : MonoBehaviour { private int score; private void Start()//函数1 { score = 0; UpdateScore(); } void UpdateScore()//函数2 { tips.text = "Score:" + score; } // 这个地方也要注意,tips.text的返回值是string类型,而score的值是int类型。规范的写,应该把 + score; 改成 + score.tostring(); 不过unity会自动帮助修改。
public void AddScore(int newScoreValue)//函数3 { score += newScoreValue; UpdateScore(); } }
🐷逻辑是这样的:a、函数1是一个初始化,让分数重置为0 然后调用了函数2(函数2用于更新显示面板分数,但不是实际的去改变核心数值Score)
b、函数2的目的是更新显示面板的分数。但不负责核心变量Score的变化。
c、函数3是真正的增加了核心变量Score的数值。通过外部传递参数进来,改变核心变量Score的具体数值。但之后,更新面板的事情,交给函数2去做。
🐷总结:三个函数分别实现了 初始化;更新面板;更新分数 。 这三个函数最大限度地拆开了所有功能,将每个步骤都分开,这样外部调用会很方便,逻辑清晰。
Collision脚本(挂载在所有敌人的预制件上)
public class Collision : MonoBehaviour { public GameObject explo; public GameObject playerExplo; public int scoreValue; private GameController gameCon; private void Start()//函数1 { GameObject temporaryGC = GameObject.FindGameObjectWithTag("GameController");//这一部分非常重要! gameCon = temporaryGC.GetComponent<GameController>(); } private void OnTriggerEnter(Collider other)//函数2 { if(other.tag == "Bullet")//如果传递进来的参数,其标签是子弹, { Instantiate(explo, transform.position, transform.rotation);//那么就实例化一个explo,(explo是共有的,也就是说需要在Inspector面板里,拖拽一个 实际上是爆炸的特效) 而位置旋转参数,就跟这个脚本所挂载的游戏物体本身一样。 gameCon.AddScore(scoreValue); //通过GameController类的对象,调用增加分数函数。其参数scoreValue,是public类型,可以在Inspector面板上修改分值,达到“一个脚本作用于多个敌人时,有多个分值变化”。 } Destroy(other.gameObject); //销毁与它碰撞的任何物体
Destroy(gameObject);//销毁挂载此脚本的物体 } }
🐷逻辑是这样的:👾a、函数1是最重要的逻辑,让每一个敌人都得到游戏物体GameController实例化之后所拥有的核心参数score。
🧐讨论一下是如何获得的:
目的:让每个敌人爆炸时,都能增加游戏物体GameController的score值。
核心:1 找到游戏物体GameController。2 获得它实例化后的组件。3 一旦爆炸,立刻调用组件里的函数加分。
😡这里之前有一个疑惑:获取组件语句是在Start函数里调用的,也就是说敌人刚被实例化,就获取组件了,而敌人不一定什么时候被打死,那么当晚生成的敌人(即晚获取组件)先死掉,也加了分,而先获取组件的敌人后死掉,
但是他早就获取了组件,这个组件是没有更新晚生成却先死掉的得分的(获取组件方法是在Start函数里写的,是一次性的,不存在实时更新),那么会不会出现分数覆盖的情况?
👍如果你问这个问题,那你犯了一个致命的错误(也就是我):没搞明白什么叫实例化!
我们看看实例化的定义:实例化是指在面向对象的编程中,通常把用类创建对象的过程称为实例化。格式为 类名 对象名 = new 类名(参数1,参数2...参数n)。如Date date=new Date();
实例化是在内存里开辟了一个空间(new),存放这个类的一个对象。而Collision脚本只是引用,根本没有创建新的对象。它就像一个指针一样,始终与原对象同步更新。
👾b、函数2用于检测敌人是否被子弹碰撞到,如果是,就增加相应的分数。
存一些大神截图: