一、前言
嗨,大家好,我是新发。
我打算写一篇使用Unity制作像天天酷跑一样的游戏的教程,会按功能点分成多篇文章来讲,希望可以帮助一些想学Unity的同学。
注:我使用的Unity版本是2020.1.14f1c1。
文章目录:
第一篇:人物动画序列帧
第二篇:使用Animator控制跑酷角色的动画状态切换
第三篇:跑酷地面制作
第四篇:使用脚本控制跑酷角色
第五篇:游戏结束与重新开始
第六篇:金币创建与吃金币
第七篇:游戏界面的基础UI
本工程的Demo工程,我已上传到GitHub,感兴趣的同学可以自己下载下来学习。
https://github.com/linxinfa/UnityParkourGameDemo
本节我将讲下游戏界面的基础UI的实现,本节的效果:
二、导入游戏界面UI素材
把游戏界面UI素材导入到工程中。
三、制作游戏界面UI预设
制作游戏界面UI预设:GameMainPanel.prefab
。
四、事件管理器
为了方便逻辑与UI之间的控制,我们弄一个事件管理器,通过事件来降低逻辑与UI之间的耦合度。
using UnityEngine;
using System.Collections.Generic;
public delegate void MyEventHandler(params object[] objs);
/// <summary>
/// 事件管理器,订阅事件与事件触发
/// </summary>
public class EventDispatcher
{
/// <summary>
/// 订阅事件
/// </summary>
public void Regist(string eventName, MyEventHandler handler)
{
if (handler == null)
return;
if (!listeners.ContainsKey(eventName))
{
listeners.Add(eventName, new Dictionary<int, MyEventHandler>());
}
var handlerDic = listeners[eventName];
var handlerHash = handler.GetHashCode();
if (handlerDic.ContainsKey(handlerHash))
{
handlerDic.Remove(handlerHash);
}
listeners[eventName].Add(handler.GetHashCode(), handler);
}
/// <summary>
/// 注销事件
/// </summary>
public void UnRegist(string eventName, MyEventHandler handler)
{
if (handler == null)
return;
if (listeners.ContainsKey(eventName))
{
listeners[eventName].Remove(handler.GetHashCode());
if (null == listeners[eventName] || 0 == listeners[eventName].Count)
{
listeners.Remove(eventName);
}
}
}
/// <summary>
/// 触发事件
/// </summary>
public void DispatchEvent(string eventName, params object[] objs)
{
if (listeners.ContainsKey(eventName))
{
var handlerDic = listeners[eventName];
if (handlerDic != null && 0 < handlerDic.Count)
{
var dic = new Dictionary<int, MyEventHandler>(handlerDic);
foreach (var f in dic.Values)
{
try
{
f(objs);
}
catch (System.Exception ex)
{
Debug.LogErrorFormat(szErrorMessage, eventName, ex.Message, ex.StackTrace);
}
}
}
}
}
/// <summary>
/// 清空事件
/// </summary>
/// <param name="key"></param>
public void ClearEvents(string eventName)
{
if (listeners.ContainsKey(eventName))
{
listeners.Remove(eventName);
}
}
private Dictionary<string, Dictionary<int, MyEventHandler>> listeners = new Dictionary<string, Dictionary<int, MyEventHandler>>();
private readonly string szErrorMessage = "DispatchEvent Error, Event:{0}, Error:{1}, {2}";
private static EventDispatcher s_instance;
public static EventDispatcher instance
{
get
{
if (null == s_instance)
s_instance = new EventDispatcher();
return s_instance;
}
}
}
接着,我们定义一些事件。
/// <summary>
/// 事件定义
/// </summary>
public class EventNameDef
{
/// <summary>
/// 跳跃事件
/// </summary>
public const string EVENT_JUMP = "EVENT_JUMP";
/// <summary>
/// 吃金币事件
/// </summary>
public const string EVENT_ADD_COIN = "EVENT_ADD_COIN";
}
事件的订阅和触发调用,在下面讲。
五、编写GameMainPanel.cs脚本
创建GameMainPanel.cs
脚本,挂到GameMainPanel
预设上。
这个脚本主要做两件事:
1 点击跳跃按钮,抛出跳跃事件;
2 监听加金币事件,当收到加金币事件时,同步金币数值到UI上。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class GameMainPanel : MonoBehaviour
{
/// <summary>
/// 跳跃按钮
/// </summary>
public Button jumpBtn;
/// <summary>
/// 金币文本
/// </summary>
public Text coinLbl;
private void Awake()
{
EventDispatcher.instance.Regist(EventNameDef.EVENT_ADD_COIN, OnEventAddCoin);
jumpBtn.onClick.AddListener(() =>
{
// 抛出事件
EventDispatcher.instance.DispatchEvent(EventNameDef.EVENT_JUMP);
});
}
private void OnDestroy()
{
EventDispatcher.instance.UnRegist(EventNameDef.EVENT_ADD_COIN, OnEventAddCoin);
}
/// <summary>
/// 加金币事件,同步数值到UI
/// </summary>
/// <param name="args"></param>
private void OnEventAddCoin(params object[] args)
{
coinLbl.text = ((int)args[0]).ToString();
}
}
六、游戏管理器添加金币逻辑
在之前创建的游戏管理器脚本GameMgr.cs
中添加金币逻辑,当金币发生变化时,抛出EVENT_ADD_COIN
事件。
public int score
{
get {
return m_score; }
set
{
if (value != m_score)
EventDispatcher.instance.DispatchEvent(EventNameDef.EVENT_ADD_COIN, value);
m_score = value;
}
}
private int m_score;
七、加金币
上一节讲了金币碰撞的检测,现在可以写上加金币逻辑了。
// Player.cs
/// <summary>
/// 触发器事件
/// </summary>
private void OnTriggerEnter2D(Collider2D collision)
{
if ("Coin" == collision.gameObject.tag)
{
// 吃到金币
Destroy(collision.gameObject);
// 加金币
GameMgr.instance.score++;
}
}
八、跳跃事件
为了响应跳跃事件,Player.cs
中订阅EVENT_JUMP
事件。
// Player.cs
private void Awake()
{
EventDispatcher.instance.Regist(EventNameDef.EVENT_JUMP, OnEventJump);
}
private void OnDestroy()
{
EventDispatcher.instance.UnRegist(EventNameDef.EVENT_JUMP, OnEventJump);
}
void OnEventJump(params object[] args)
{
if (0 == m_jumpCount) //一段
{
m_ani.SetBool("IsJumping1", true);
m_rig.velocity = new Vector2(0, JumpSpeed);
++m_jumpCount;
}
else if (1 == m_jumpCount) //二段
{
m_ani.SetBool("IsJumping2", true);
m_rig.velocity = new Vector2(0, SecondJumpSpeed);
++m_jumpCount;
}
}
九、运行测试
运行Unity,测试效果如下:
转载:https://blog.csdn.net/linxinfa/article/details/113914913