
在游戏中,按下小地图键打开小地图,显示所有房间信息以及玩家所在位置。
这里使用到的方法原理,即采用小地图专用摄像机,通过设置其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为委托
}
}
}