一、GameManager脚本
两个成员变量FloatingTextManager,以及成员函数ShowText。
// 在组件面板中赋给初始实体 public FloatingTextManager floatingTextManager; public void ShowText(string msg, int fontSize, Color color, Vector3 position, Vector3 motion, float duration) { floatingTextManager.show(msg, fontSize, color, position, motion, duration); }
因为GameManager实体(instance)是一个任何实体都能接触到的全局实体,而floatingTextManager不是(当然也可以将其设置为全局实体,但好像没必要),所以任何实体想要实现显示文本的功能,需要通过调用instance的ShowText,来间接调用floatingTextManager的show。
这里的showText主要是起到传参的作用。
二、FloatingTextManager脚本
有三个成员变量:
public GameObject textContainer; public GameObject textPrefab; private List<FloatingText> floatingTexts = new List<FloatingText>();
textContainer——应该是作为容器,但目前没有实际的影响?在教程中,我们新建了一个Panel(UI的一种,位于Canvas下)作为挂载FloatingTextManager脚本的实体,并且将textContainer也设置成它自身。
textPrefab——文本预设,是事先做好的一个Text样例,存在prefab文件夹中。当list中没有可用的FloatingText实体而需要新建时,我们将实体化这个预设,赋给Text成员变量go。
floatingTexts——一个列表,装入其中的FloatingText实体将永远不会被摧毁,只会被停用。这样做避免了每次都需要新建文本。
当试图从列表中选取FloatingText实体时,可能有以下几种情况:
a.列表为空,则新建实体加入列表,开始Show过程;
b.列表不为空,但所有元素都处于激活状态(即都处于Show过程中),则新建实体加入列表,开始Show过程;
c.列表不为空,且有元素处于停用状态(已经Show完毕),则选取该元素赋新值,进行重复使用。
成员函数:
// 从列表里选取FloatingText实体 private FloatingText GetFloatingText()// 这里面有个transform父子关系的建立不太明白? public void show(string msg, int fontSize, Color color, Vector3 position, Vector3 motion, float duration) { FloatingText floatingText = GetFloatingText(); // ...一系列传参 // 将世界坐标转换为(主摄像机下的)屏幕坐标 floatingText.go.transform.position = Camera.main.WorldToScreenPoint(position); floatingText.Show(); } // 每帧调用列表中所有浮现文本实体的更新 private void Update() { foreach (FloatingText txt in floatingTexts) txt.UpdateFloatingText(); }
Update——因为FloatingText类没有继承自MonoBehavior,所以没有现成的Update函数。所以需要借助Manager间接调用刷新函数。
三、FloatingText脚本
含有多个成员变量,其中比较重要的如下:
public bool active; // 是否激活状态 public GameObject go; // 初始化预设时,会赋给这个变量 public Text txt; // unity自带的文本组件
go——一开始百思不得其解为啥会有这个,我不能直接初把预设给txt吗?后来弄明白了。textPrefab是一个GameObject,Text是它的一个组件,只有前者会有激活/停用状态。
嗯……看来要补习下GameObject相关知识。https://zhuanlan.zhihu.com/p/41449496
GameObject是场景中所有实体的基类。它是组件的容器,本身没有功能。
脚本必须挂在一个GameObject上面才能执行。gameObject属性可以在所有继承MonoBehaviour的类中获取到,因为脚本必须要挂在到一个物体上才能执行,这个gameObject就是脚本挂到的物体。
修改物体的active状态是一个快速隐藏/显示物体的方法。物体的active是false时,物体上所有的组件都不会执行,相当于将物体隐藏了。
成员函数:
public void Show(){}// 激活 public void Hide(){}// 停用 // 因为没有继承,所以没有现成的Update,需要自己写 public void UpdateFloatingText() { // 若停用,则不用更新 if (!active) return; // 检测文本已存在的时间,若超过存活时间,则隐藏 if (Time.time - lastShown > duration) Hide(); // 每帧移动 go.transform.position += motion * Time.deltaTime; }
四、Chest脚本
教程里要做的效果是玩家与宝箱碰撞→宝箱上方浮现文字“获得了X金币”→文字向上移动,一段时间后消失。
宝箱可以视作效果的触发者,所以由宝箱脚本来调用浮现文本相关代码。
GameManager.instance.ShowText("+ " + pesosAmount + " pesos!", 25, Color.yellow, transform.position, Vector3.up * 30, 0.7f);
宝箱提供了:文本内容(金币数量)和自身位置。
可以看到,这里是通过全局变量instance进行调用的。
暂无关于此日志的评论。