using Unity.FPS.Game;using UnityEngine;namespace Unity.FPS.Gameplay
{publicclassObjectiveKillEnemies:Objective{protectedoverridevoidStart(){base.Start();//Objective.cs
EventManager.AddListener<EnemyKillEvent>(OnEnemyKilled);// set a title and description specific for this type of objective, if it hasn't oneif(string.IsNullOrEmpty(Title))
Title ="Eliminate "+" the"+" enemy";}voidOnDestroy(){
EventManager.RemoveListener<EnemyKillEvent>(OnEnemyKilled);}}}
2.2 Title的产生:
利用Objective.cs来存储函数,不挂载。
利用using Unity.FPS.Game来使用。
代码:
using System;using UnityEngine;namespace Unity.FPS.Game
{publicabstractclassObjective:MonoBehaviour{[Tooltip("Name of the objective that will be shown on screen")]publicstring Title;[Tooltip("Delay before the objective becomes visible")]publicfloat DelayVisible;publicbool IsCompleted {get;privateset;}publicboolIsBlocking()=>!(IsCompleted);publicstaticevent Action<Objective> OnObjectiveCreated;publicstaticevent Action<Objective> OnObjectiveCompleted;protectedvirtualvoidStart(){
OnObjectiveCreated?.Invoke(this);DisplayMessageEvent displayMessage = Events.DisplayMessageEvent;//Event.cs里定义的
displayMessage.Message = Title;
displayMessage.DelayBeforeDisplay =0.0f;
EventManager.Broadcast(displayMessage);}/* public void CompleteObjective(string descriptionText, string counterText, string notificationText)
{
IsCompleted = true;//可能要用于结束消息提示。 单独挑出来
ObjectiveUpdateEvent evt = Events.ObjectiveUpdateEvent;
evt.Objective = this;
evt.NotificationText = notificationText;
evt.IsComplete = IsCompleted;
EventManager.Broadcast(evt);
OnObjectiveCompleted?.Invoke(this);
}*///任务完成时,借鉴使用 }}
2.3 Event.cs–定义事件名字
不挂载,用于存储函数。
命名空间为Unity.FPS.Game。(这里只截取需要的函数)
后续增加事件就往里头加。
using UnityEngine;namespace Unity.FPS.Game
{// The Game Events used across the Game.// Anytime there is a need for a new event, it should be added here.publicstaticclassEvents{publicstaticDisplayMessageEvent DisplayMessageEvent =newDisplayMessageEvent();}publicclassDisplayMessageEvent:GameEvent{publicstring Message;publicfloat DelayBeforeDisplay;}}
2.4 EventManager.cs–Listener的定义
代码:
using System;using System.Collections.Generic;namespace Unity.FPS.Game
{publicclassGameEvent{}// A simple Event System that can be used for remote systems communicationpublicstaticclassEventManager{staticreadonly Dictionary<Type, Action<GameEvent>> s_Events =newDictionary<Type, Action<GameEvent>>();staticreadonly Dictionary<Delegate, Action<GameEvent>> s_EventLookups =newDictionary<Delegate, Action<GameEvent>>();publicstaticvoidAddListener<T>(Action<T> evt)where T : GameEvent
{if(!s_EventLookups.ContainsKey(evt)){
Action<GameEvent> newAction =(e)=>evt((T) e);
s_EventLookups[evt]= newAction;if(s_Events.TryGetValue(typeof(T),out Action<GameEvent> internalAction))
s_Events[typeof(T)]= internalAction += newAction;else
s_Events[typeof(T)]= newAction;}}publicstaticvoidRemoveListener<T>(Action<T> evt)where T : GameEvent
{if(s_EventLookups.TryGetValue(evt,outvar action)){if(s_Events.TryGetValue(typeof(T),outvar tempAction)){
tempAction -= action;if(tempAction ==null)
s_Events.Remove(typeof(T));else
s_Events[typeof(T)]= tempAction;}
s_EventLookups.Remove(evt);}}publicstaticvoidBroadcast(GameEvent evt){if(s_Events.TryGetValue(evt.GetType(),outvar action))
action.Invoke(evt);}publicstaticvoidClear(){
s_Events.Clear();
s_EventLookups.Clear();}}}
2.5 备用:ObjectiveManager
using System.Collections.Generic;using UnityEngine;namespace Unity.FPS.Game
{publicclassObjectiveManager:MonoBehaviour{
List<Objective> m_Objectives =newList<Objective>();bool m_ObjectivesCompleted =false;voidAwake(){
Objective.OnObjectiveCreated += RegisterObjective;}voidRegisterObjective(Objective objective)=> m_Objectives.Add(objective);voidUpdate(){if(m_Objectives.Count ==0|| m_ObjectivesCompleted)return;for(int i =0; i < m_Objectives.Count; i++){// pass every objectives to check if they have been completedif(m_Objectives[i].IsBlocking()){// break the loop as soon as we find one uncompleted objectivereturn;}}
m_ObjectivesCompleted =true;
EventManager.Broadcast(Events.AllObjectivesCompletedEvent);}voidOnDestroy(){
Objective.OnObjectiveCreated -= RegisterObjective;}}}
2.6 备用:GameFlowManager
using UnityEngine;using UnityEngine.SceneManagement;namespace Unity.FPS.Game
{publicclassGameFlowManager:MonoBehaviour{[Header("Parameters")][Tooltip("Duration of the fade-to-black at the end of the game")]publicfloat EndSceneLoadDelay =3f;[Tooltip("The canvas group of the fade-to-black screen")]publicCanvasGroup EndGameFadeCanvasGroup;[Header("Win")][Tooltip("This string has to be the name of the scene you want to load when winning")]publicstring WinSceneName ="WinScene";[Tooltip("Duration of delay before the fade-to-black, if winning")]publicfloat DelayBeforeFadeToBlack =4f;[Tooltip("Win game message")]publicstring WinGameMessage;[Tooltip("Duration of delay before the win message")]publicfloat DelayBeforeWinMessage =2f;[Tooltip("Sound played on win")]publicAudioClip VictorySound;[Header("Lose")][Tooltip("This string has to be the name of the scene you want to load when losing")]publicstring LoseSceneName ="LoseScene";publicbool GameIsEnding {get;privateset;}float m_TimeLoadEndGameScene;string m_SceneToLoad;voidAwake(){
EventManager.AddListener<AllObjectivesCompletedEvent>(OnAllObjectivesCompleted);
EventManager.AddListener<PlayerDeathEvent>(OnPlayerDeath);}voidStart(){
AudioUtility.SetMasterVolume(1);}voidUpdate(){if(GameIsEnding){float timeRatio =1-(m_TimeLoadEndGameScene - Time.time)/ EndSceneLoadDelay;
EndGameFadeCanvasGroup.alpha = timeRatio;
AudioUtility.SetMasterVolume(1- timeRatio);// See if it's time to load the end scene (after the delay)if(Time.time >= m_TimeLoadEndGameScene){
SceneManager.LoadScene(m_SceneToLoad);
GameIsEnding =false;}}}voidOnAllObjectivesCompleted(AllObjectivesCompletedEvent evt)=>EndGame(true);voidOnPlayerDeath(PlayerDeathEvent evt)=>EndGame(false);voidEndGame(bool win){// unlocks the cursor before leaving the scene, to be able to click buttons
Cursor.lockState = CursorLockMode.None;
Cursor.visible =true;// Remember that we need to load the appropriate end scene after a delay
GameIsEnding =true;
EndGameFadeCanvasGroup.gameObject.SetActive(true);if(win){
m_SceneToLoad = WinSceneName;
m_TimeLoadEndGameScene = Time.time + EndSceneLoadDelay + DelayBeforeFadeToBlack;// play a sound on winvar audioSource = gameObject.AddComponent<AudioSource>();
audioSource.clip = VictorySound;
audioSource.playOnAwake =false;
audioSource.outputAudioMixerGroup = AudioUtility.GetAudioGroup(AudioUtility.AudioGroups.HUDVictory);
audioSource.PlayScheduled(AudioSettings.dspTime + DelayBeforeWinMessage);// create a game message//var message = Instantiate(WinGameMessagePrefab).GetComponent<DisplayMessage>();//if (message)//{// message.delayBeforeShowing = delayBeforeWinMessage;// message.GetComponent<Transform>().SetAsLastSibling();//}DisplayMessageEvent displayMessage = Events.DisplayMessageEvent;
displayMessage.Message = WinGameMessage;
displayMessage.DelayBeforeDisplay = DelayBeforeWinMessage;
EventManager.Broadcast(displayMessage);}else{
m_SceneToLoad = LoseSceneName;
m_TimeLoadEndGameScene = Time.time + EndSceneLoadDelay;}}voidOnDestroy(){
EventManager.RemoveListener<AllObjectivesCompletedEvent>(OnAllObjectivesCompleted);
EventManager.RemoveListener<PlayerDeathEvent>(OnPlayerDeath);}}}
2. 消息的文字产生2.1 开头“Kill all the enemy”的产生需要objectiveKillEnemy.prefab。挂载脚本ObjectiveKillEnemies。Title为所要展示的文字信息。其他不需要。using Unity.FPS.Game;using UnityEngine;namespace Unity.FPS.Gameplay{ public class ObjectiveKillEnemies : Objective {