在游戏中,按下小地图键打开小地图,显示所有房间信息以及玩家所在位置。
这里使用到的方法原理,即采用小地图专用摄像机,通过设置其Target Texture和Culling Mask属性,将拍摄到的画面渲染在一张Texture图片上,然后将该Texture图片做成UI显示出来。
Hierarchy面板中的结构:
MiniMap游戏物体下,有小地图摄像机与画布对象,以及画布下的Raw Image对象(用于显示Texture)。
首先,我们将要显示在小地图上的对象的Layer设置在一个单独的Layer上。如这里我要显示房间的墙壁,我就将房间墙壁的Layer设置为MiniMap:
设置摄像机
-
新建摄像机,设置为正交拍摄(调整摄像机坐标(Z轴)和背景不透明度),取消Audio Listener组件
-
设置摄像机Culling Mask属性为MiniMap(小地图图层),这样相机只会渲染MiniMap图层的对象
-
在Project面板中新建一张Render Texture图片(这里命名为MiniMapBG),作为摄像机的输出目标,设置好图片的大小,并将摄像机Target Texture属性设置为它
设置画布
-
在画布下新建UI:Raw Image,将其Texture属性也设置为刚刚创建的Render Texture
至此,小地图创建工作以及大致完成,剩下的功能可根据需要自行修改。
当敌人受到伤害,则在其位置显示伤害数字,并且在显示期间数字会向上移动一段距离
原理:世界坐标画布。
-
在敌人对象下新建Canvas画布,设置为世界坐标,Reset一下其Transform数据,然后将Canvas组件下的Event Camera设置为主相机Main Camera(注意如果要把Canvas做成预制体,那么也要将主相机做成预制体,这样才能在Canvas预制体中设置Event Camera属性)
-
代码思路:
-
-
新建脚本,挂在Canvas下,当检测到Text为avtive,则启动计时器,当计时器时间小于规定的显示时间,则增加其Y坐标向上移动;当计时器超过规定时间,则重置坐标与计时器,将Text设置为非active
-
//敌人脚本中,受伤后调用的方法 protected void OnHurt(int damageAmount) { if(!isHurt) { isHurt = true; //被击shader sp.material.SetFloat("_FlashAmount", 1); hurtTimeCounter = hurtTimeLength; //被击后退 enemyRig.AddForce(new Vector2(hurtMovmentVector.x, hurtMovmentVector.y)); //切换受伤动画 enemyAnim.SetTrigger("hurt"); //敌人受伤数值随机 damageAmount = Random.Range(damageAmount - hurtInterval, damageAmount + hurtInterval + 1); //敌人受伤UI damageText.gameObject.SetActive(true); EventEnemyHurt?.Invoke(damageAmount);//等价于if(EventEnemyHurt!=null) { EventEnemyHurt(damageAmount); } } }
public class HitBarCanvas : MonoBehaviour { public Text damageText; public float textSpeed; public float timer;//规定显示的事件 public float nowTime;//计时器 private void Awake() { //FindObjectOfType<Enemy>().EventEnemyHurt += ShowDamageText; //不能直接找,要从父对象上找脚本,不然都去找第一个Enemy脚本了 GetComponentInParent<Enemy>().EventEnemyHurt += ShowDamageText;//注册事件 } void Update() { VisibelController(); } public void VisibelController() { if (damageText.gameObject.activeInHierarchy) { nowTime += Time.deltaTime; if (nowTime < timer) { //设置lacalPosition本地坐标,而不是transform.position世界坐标 damageText.transform.localPosition += new Vector3(0, textSpeed * Time.deltaTime, 0); } else { damageText.transform.localPosition = new Vector3(0, 0, 0);//设置localPosition本地坐标才对 nowTime = 0; damageText.gameObject.SetActive(false); } } } //事件触发后执行的方法 public void ShowDamageText(int damageAmount) { damageText.text = damageAmount.ToString(); } }
注意:
-
如果敌人向左右移动时的图片翻转用的是设置Sclae的方法,那么这里伤害数字也会跟着翻转,可以通过设置SpriteRenderer组件中的 flipX 属性来实现翻转,就能避免此问题
-
在敌人对象销毁时,记得解绑事件
if (movementVector.x != 0)//反转人物图片 { if (movementVector.x < 0) { sp.flipX = true; //用sprite renderer来翻转图片,用localScale的话,其子物体伤害信息也会跟着翻转 } else { sp.flipX = false; } }
private void OnDisable() { //解绑事件 if(EventEnemyHurt!=null) { foreach (var item in EventEnemyHurt.GetInvocationList()) { EventEnemyHurt -= item as DelEnemyHurt; //EventEnemyHurt为事件,DelEnemyHurt为委托 } } }