前言
之前在B站上看到了一位博主写了一个FPS的杀敌信息提示功能,感觉写的很好,就来尝试一下
完成效果
20240306_击杀信息提示
UI搭建
我这里是直接在画布下新建了一个空物体KillMessage,新建脚本挂在KillMessage上,UI分为杀人者信息、击杀方式图标、被杀者信息,KillerIcon之后可以扩展为特殊提示图标,我这里UI设置的高度都是统一,宽度可以根据需求设置或设置自适应。
UI搭建完成之后,新建KillMessage脚本挂载到KillMessage物体上,并制作为预制体。
UI信息生成方法
这里粘上全部脚本,分别创建UI预制体下对应的几个对象。
public class Killmessage : MonoBehaviour
{
[SerializeField]
Text killMsgTxt;
[SerializeField]
Image killerIcon;
[SerializeField]
Text killerTxt;
[SerializeField]
Image killTxtImg;
[HideInInspector]
public float msgRefreshTimer;//信息存在时间
//两个方法,修改击杀信息以及击杀者信息方法
public void SetKillData(string killData,Color color)
{
killMsgTxt.text = killData;
killMsgTxt.color = color;
}
public void SetKillerData(string killerName,Color color)
{
killerTxt.text = killerName;
killerTxt.color = color;
}
//修改击杀信息图像
public void SetKillTxtImg(Sprite sprite)
{
killTxtImg.sprite = sprite;
}
//刷新生成信息位置
public void SetPos(int pos)
{
(transform as RectTransform).anchoredPosition = new Vector2(0,-60*pos);
}
}
UI信息管理方法
这里使用队列和列表做了一个简易的对象池,队列存储已经实例化的信息,列表存储已经显示的信息。
[SerializeField]
List<Killmessage> killMsgs = new List<Killmessage>(); //存储显示的信息
Queue<Killmessage> killMsgsQueue = new Queue<Killmessage>();//信息对象池
新建一个信息生成类 ,我这里人名是直接在inspector面板下自定义的,真实项目中,这个人名可以根据具体情况去获取
[SerializeField]
Killmessage killMsg;//生成信息方法类
[SerializeField]
string[] killNames;//存储人名
[SerializeField]
Sprite[] killTxtImg;//存储武器
//新建一个UI信息对象用来实例化
[SerializeField]
Killmessage prefabKillMsgs;
[SerializeField]
int maxMsgCount=5;//生成信息最大数量
[SerializeField]
float refreshTimer = 3.0f;//每条信息存在时间
实例化信息到队列 ,因为队列中已经添加了一条信息了,所以循环从1开始实例化
void Start()
{
killMsgsQueue.Enqueue(prefabKillMsgs);//先添加一个到队列
for (int i=1;i<maxMsgCount;i++)
{
killMsgsQueue.Enqueue(Instantiate(prefabKillMsgs.gameObject, transform).GetComponent<Killmessage>());
}
}
获取队列中信息方法
Killmessage GetMsg()
{
if (killMsgsQueue.Count==0)//队列为空的时候,从列表中取出添加到队列
{
RemoveFirstMsg();
}
return killMsgsQueue.Dequeue();//直接从队列中取出第一位
}
void RemoveFirstMsg()
{
Killmessage firstMsg = killMsgs[0];
killMsgs.RemoveAt(0);
firstMsg.gameObject.SetActive(false);
for (int i=0;i<killMsgs.Count;i++)
{
killMsgs[i].SetPos(i);
}
killMsgsQueue.Enqueue(firstMsg);
}
生成击杀信息方法,这里方法比较简单,通过调用Killmessage类中的信息生成方法来生成信息,同时将生成的信息添加到列表中。
void AddKillMsg(string killerName,Color killerColor,string killTxt,Color killTxtColor,Sprite killTxtImg)
{
Killmessage msg=GetMsg();
msg.SetKillData(killTxt,killTxtColor);
msg.SetKillerData(killerName,killerColor);
msg.SetKillTxtImg(killTxtImg);
msg.SetPos(killMsgs.Count);
msg.msgRefreshTimer = Time.time + refreshTimer;
killMsgs.Add(msg);//添加信息到列表
msg.gameObject.SetActive(true);
}
信息生成及销毁方法调用
这里测试使用空格键按下之后生成消息,生成的第一条消息到时间后隐藏,并移出列表
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
CreateKillData();
}
if (killMsgs.Count>0)
{
Killmessage firstMsg = killMsgs[0];
if (Time.time>firstMsg.msgRefreshTimer)
{
RemoveFirstMsg();
}
}
}
void CreateKillData()
{
bool random = Random.Range(0, 2) == 0;
AddKillMsg(killNames[Random.Range(0, killNames.Length)], random ? Color.red : Color.yellow,
killNames[Random.Range(0, killNames.Length)], random ? Color.yellow : Color.red,
killTxtImg[Random.Range(0, killTxtImg.Length)]);
}
完整脚本
public class KillMsgCtrl : MonoBehaviour
{
[SerializeField]
Killmessage killMsg;//生成信息方法类
[SerializeField]
string[] killNames;//存储人名
[SerializeField]
Sprite[] killTxtImg;//存储武器
[SerializeField]
List<Killmessage> killMsgs = new List<Killmessage>(); //存储显示的信息
Queue<Killmessage> killMsgsQueue = new Queue<Killmessage>();//信息对象池
[SerializeField]
Killmessage prefabKillMsgs;
[SerializeField]
int maxMsgCount=5;//生成信息最大数量
[SerializeField]
float refreshTimer = 3.0f;
void Start()
{
killMsgsQueue.Enqueue(prefabKillMsgs);//先添加一个到队列
for (int i=1;i<maxMsgCount;i++)
{
killMsgsQueue.Enqueue(Instantiate(prefabKillMsgs.gameObject, transform).GetComponent<Killmessage>());
}
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
CreateKillData();
}
if (killMsgs.Count>0)
{
Killmessage firstMsg = killMsgs[0];
if (Time.time>firstMsg.msgRefreshTimer)
{
RemoveFirstMsg();
}
}
}
void CreateKillData()
{
bool random = Random.Range(0, 2) == 0;
AddKillMsg(killNames[Random.Range(0, killNames.Length)], random ? Color.red : Color.yellow,
killNames[Random.Range(0, killNames.Length)], random ? Color.yellow : Color.red,
killTxtImg[Random.Range(0, killTxtImg.Length)]);
}
/// <summary>
/// 获取空闲信息
/// </summary>
/// <returns></returns>
Killmessage GetMsg()
{
if (killMsgsQueue.Count==0)
{
RemoveFirstMsg();
}
return killMsgsQueue.Dequeue();
}
void RemoveFirstMsg()
{
Killmessage firstMsg = killMsgs[0];
killMsgs.RemoveAt(0);
firstMsg.gameObject.SetActive(false);
for (int i=0;i<killMsgs.Count;i++)
{
killMsgs[i].SetPos(i);
}
killMsgsQueue.Enqueue(firstMsg);
}
/// <summary>
/// 生成击杀信息
/// </summary>
void AddKillMsg(string killerName,Color killerColor,string killTxt,Color killTxtColor,Sprite killTxtImg)
{
Killmessage msg=GetMsg();
msg.SetKillData(killTxt,killTxtColor);
msg.SetKillerData(killerName,killerColor);
msg.SetKillTxtImg(killTxtImg);
msg.SetPos(killMsgs.Count);
msg.msgRefreshTimer = Time.time + refreshTimer;
killMsgs.Add(msg);//添加信息到列表
msg.gameObject.SetActive(true);
}
}
总结
对FPS游戏相关感兴趣的可以去看看这位博主的视频,感觉很多干货 B站 @内個_shei_鸭 UID229806705