一、Message消息
Unity中的消息系统为脚本之间的通信提供了一种便捷的方式,主要包括SendMessage()、BroadcastMessage()和SendMessageUpwards()这三个方法。
1、SendMessage()
SendMessage()
是 Unity 中的一个方法,它允许你向GameObject或者GameObject子类的一个实例发送消息。这个方法可以用来在不同的脚本之间进行通信,即使它们不在同一 GameObject 上。SendMessage()
可以调用任何公开的(public
)方法,包括生命周期方法(如 Start()
和 Update()
)。
基本用法
S
endMessage()
用于向 GameObject 上所有挂载的脚本发送指定名称的消息。接收消息的脚本需要有相应名称的函数。该方法可以携带一个参数(可选),传递给接收消息的函数。
示例
// 发送消息的脚本
public class MessageSender : MonoBehaviour
{
void Start()
{
gameObject.SendMessage("TakeDamage", 10);
}
}
// 接收消息的脚本
public class HealthManager : MonoBehaviour
{
public int currentHealth = 100;
void TakeDamage(int damage)
{
currentHealth -= damage;
Debug.Log("受到 " + damage + " 点伤害,剩余生命值:" + currentHealth);
}
}
3、SendMessageUpwards()
基本用法
SendMessageUpwards()
向 GameObject 及其所有父物体上挂载的脚本发送消息
示例
// 子物体上发送消息的脚本
public class ChildMessageSender : MonoBehaviour
{
void Start()
{
gameObject.SendMessageUpwards("OnChildEvent");
}
}
// 父物体上接收消息的脚本
public class ParentController : MonoBehaviour
{
void OnChildEvent()
{
Debug.Log("父物体接收到子物体的事件消息");
}
}
3、BroadcastMessage()
基本用法
BroadcastMessage()
与SendMessage()
类似,但它会向 GameObject 及其所有子物体上挂载的脚本发送消息。
示例
// 发送消息的脚本
public class ParentMessageSender : MonoBehaviour
{
void Start()
{
gameObject.BroadcastMessage("OnEnemySpawn");
}
}
// 子物体上接收消息的脚本
public class EnemyAI : MonoBehaviour
{
void OnEnemySpawn()
{
Debug.Log("敌人AI接收到生成消息");
}
}
应用场景
消息系统在游戏开发中常用于实现组件之间的解耦。例如,在一个角色扮演游戏中,当角色受到伤害时,可以通过SendMessage()通知生命值管理组件进行相应的处理;
在一个包含多个敌人的场景中,使用BroadcastMessage()可以方便地通知所有敌人执行某个动作,如进入战斗状态;
SendMessageUpwards()则可以用于子物体向父物体汇报状态或请求某些操作,比如在一个 UI 界面中,子元素可以通过它向父级 UI 管理器发送事件消息。
二、Time时间信息的接口类
Time
类提供了与时间相关的信息和功能,在游戏开发中用于控制游戏的时间流逝、帧率等
1、时间尺度
用法
Time.timeScale
属性用于控制游戏的时间流逝速度。默认值为 1,表示正常的时间流逝速度;当设置为 0 时,游戏会暂停。例如,实现游戏的暂停功能:
public class PauseManager : MonoBehaviour
{
public bool isPaused = false;
void Update()
{
if (Input.GetKeyDown(KeyCode.Escape))
{
isPaused =!isPaused;
Time.timeScale = isPaused? 0 : 1;
}
}
}
2、时间增量
用法
Time.deltaTime
表示上一帧到当前帧所经过的时间(以秒为单位)。在处理游戏对象的移动、旋转等连续变化的操作时,通常会乘以Time.deltaTime
,以确保在不同帧率下动作的流畅性和一致性。例如:
public class SmoothMovement : MonoBehaviour
{
public float speed = 5f;
void Update()
{
float horizontalInput = Input.GetAxis("Horizontal");
float verticalInput = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(horizontalInput, 0, verticalInput);
transform.Translate(movement * speed * Time.deltaTime);
}
}
3、固定时间步长
Time.fixedDeltaTime
表示FixedUpdate()
函数的调用间隔,它是一个固定的值,与帧率无关。在处理物理模拟等需要稳定时间间隔的操作时,FixedUpdate()
会以Time.fixedDeltaTime
为间隔进行调用。
3、应用场景
可以用于实现倒计时、时间限制的关卡、慢动作效果等。例如,在一个赛车游戏中,可以使用Time.timeScale
来实现慢动作过弯效果,增强游戏的视觉冲击力
三、协程
协程(Coroutine)是Unity中用于控制代码在多个帧上执行的一种机制,它允许你在不阻塞主线程的情况下执行长时间运行的操作或等待某个条件满足。协程在Unity中通过IEnumerator
接口实现
1、协程的基本结构
using UnityEngine;
public class CoroutineExample : MonoBehaviour
{
IEnumerator DelayPrint()
{
Debug.Log("开始协程");
yield return new WaitForSeconds(3f);
Debug.Log("3秒后打印");
}
}
2、启动和停止携程
启动协程:使用StartCoroutine()
方法来启动一个协程
public class CoroutineExample : MonoBehaviour
{
IEnumerator DelayPrint()
{
Debug.Log("开始协程");
yield return new WaitForSeconds(3f);
Debug.Log("3秒后打印");
}
void Start()
{
StartCoroutine(DelayPrint());
}
}
停止协程
可以使用StopCoroutine()
方法来停止一个协程。如果要停止的协程是通过方法名启动的,需要在启动协程时保存协程的引用
public class CoroutineControl : MonoBehaviour
{
private Coroutine myCoroutine;
IEnumerator Countdown()
{
for (int i = 10; i > 0; i--)
{
Debug.Log(i);
yield return new WaitForSeconds(1f);
}
}
void Start()
{
myCoroutine = StartCoroutine(Countdown());
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
StopCoroutine(myCoroutine);
}
}
}
等待条件
yield return语句可以搭配不同的条件来实现各种等待效果。
等待固定时间:使用WaitForSeconds(),如前面的例子所示,用于等待指定的秒数。
等待帧结束:yield return null表示等待当前帧结束,然后继续执行协程。在一些需要在每帧更新后执行特定操作的场景中会用到。
等待另一个协程结束:可以使用yield return StartCoroutine(otherCoroutine())来等待另一个协程执行完毕。例如:
public class CoroutineChain : MonoBehaviour
{
IEnumerator Coroutine1()
{
Debug.Log("Coroutine1 开始");
yield return new WaitForSeconds(2f);
Debug.Log("Coroutine1 结束");
}
IEnumerator Coroutine2()
{
Debug.Log("Coroutine2 开始");
yield return StartCoroutine(Coroutine1());
Debug.Log("Coroutine2 继续执行");
}
void Start()
{
StartCoroutine(Coroutine2());
}
}
3、应用场景
在加载场景时,可以使用协程来显示加载进度条,同时异步加载资源;
在制作动画效果时,通过协程实现动画的延迟播放和顺序播放;
在网络通信中,等待服务器响应时不会阻塞主线程,保证游戏的流畅运行。
四、Invoke 延时调用
Invoke
是 Unity 中用于实现延时调用方法的功能,它可以在指定的时间后调用一个方法,或者按照一定的时间间隔重复调用一个方法。
1、单次延时调用
使用Invoke()方法可以在指定的秒数后调用一个无参数的方法。其语法形式为Invoke(string methodName, float time),其中methodName是要调用的方法名(以字符串形式表示),time是延迟的时间(单位为秒)。例如,在 3 秒后调用DoSomething方法
public class InvokeExample : MonoBehaviour
{
void Start()
{
Invoke("DoSomething", 3f);
}
void DoSomething()
{
Debug.Log("3秒已到,执行操作");
}
}
2、重复延时调用
InvokeRepeating()方法用于按照固定的时间间隔重复调用一个方法。语法为InvokeRepeating(string methodName, float time, float repeatRate),time表示首次调用前的延迟时间,repeatRate表示每次调用的时间间隔。比如,每隔 2 秒重复打印一条信息:
public class RepeatingInvokeExample : MonoBehaviour
{
void Start()
{
InvokeRepeating("LogMessage", 1f, 2f);
}
void LogMessage()
{
Debug.Log("重复调用,输出信息");
}
void OnDisable()
{
CancelInvoke("LogMessage");
}
}
这里在OnDisable
方法中使用CancelInvoke()
来停止重复调用,以避免在对象禁用后仍然执行不必要的操作。
4、应用场景
技能冷却:在角色扮演游戏中,当玩家释放技能后,可以使用Invoke来设置技能的冷却时间,在冷却时间结束后,允许玩家再次使用该技能。
定时事件:比如在游戏中定时生成敌人、刷新道具等。可以通过InvokeRepeating按照一定的时间间隔来触发这些事件。
延迟效果:在角色受到伤害后,延迟一段时间再显示血条减少的动画效果,或者在敌人死亡后,延迟播放爆炸特效等。