1. 在GameHUD上挂脚本
2. 画出Rect区域
3. 预制件ObjectivePrime
- 整个偷走。
3.1预制件的组件设计
3.2 导入两个音源
- 作为提示出现和消失的声音
- 位置如下:
一、ObjectiveHUDManager
using System.Collections.Generic;
using UnityEngine;
namespace Unity.FPS.Game
{
public class ObjectiveManager : MonoBehaviour
{
List<Objective> m_Objectives = new List<Objective>();
bool m_ObjectivesCompleted = false;
void Awake()
{
Objective.OnObjectiveCreated += RegisterObjective;
}
void RegisterObjective(Objective objective) => m_Objectives.Add(objective);
void Update()
{
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 completed
if (m_Objectives[i].IsBlocking())
{
// break the loop as soon as we find one uncompleted objective
return;
}
}
m_ObjectivesCompleted = true;
EventManager.Broadcast(Events.AllObjectivesCompletedEvent);
}
void OnDestroy()
{
Objective.OnObjectiveCreated -= RegisterObjective;
}
}
}
二、ObjectiveToast
using Unity.FPS.Game;
using UnityEngine;
using UnityEngine.UI;
namespace Unity.FPS.UI
{
public class ObjectiveToast : MonoBehaviour
{
[Header("References")] [Tooltip("Text content that will display the title")]
public TMPro.TextMeshProUGUI TitleTextContent;
[Tooltip("Text content that will display the description")]
public TMPro.TextMeshProUGUI DescriptionTextContent;
[Tooltip("Text content that will display the counter")]
public TMPro.TextMeshProUGUI CounterTextContent;
[Tooltip("Rect that will display the description")]
public RectTransform SubTitleRect;
[Tooltip("Canvas used to fade in and out the content")]
public CanvasGroup CanvasGroup;
[Tooltip("Layout group containing the objective")]
public HorizontalOrVerticalLayoutGroup LayoutGroup;
[Header("Transitions")] [Tooltip("Delay before moving complete")]
public float CompletionDelay;
[Tooltip("Duration of the fade in")] public float FadeInDuration = 0.5f;
[Tooltip("Duration of the fade out")] public float FadeOutDuration = 2f;
[Header("Sound")] [Tooltip("Sound that will be player on initialization")]
public AudioClip InitSound;
[Tooltip("Sound that will be player on completion")]
public AudioClip CompletedSound;
[Header("Movement")] [Tooltip("Time it takes to move in the screen")]
public float MoveInDuration = 0.5f;
[Tooltip("Animation curve for move in, position in x over time")]
public AnimationCurve MoveInCurve;
[Tooltip("Time it takes to move out of the screen")]
public float MoveOutDuration = 2f;
[Tooltip("Animation curve for move out, position in x over time")]
public AnimationCurve MoveOutCurve;
float m_StartFadeTime;
bool m_IsFadingIn;
bool m_IsFadingOut;
bool m_IsMovingIn;
bool m_IsMovingOut;
AudioSource m_AudioSource;
RectTransform m_RectTransform;
public void Initialize(string titleText, string descText, string counterText, bool isOptionnal, float delay)
{
// set the description for the objective, and forces the content size fitter to be recalculated
Canvas.ForceUpdateCanvases();
TitleTextContent.text = titleText;
DescriptionTextContent.text = descText;
CounterTextContent.text = counterText;
if (GetComponent<RectTransform>())
{
LayoutRebuilder.ForceRebuildLayoutImmediate(GetComponent<RectTransform>());
}
m_StartFadeTime = Time.time + delay;
// start the fade in
m_IsFadingIn = true;
m_IsMovingIn = true;
}
public void Complete()
{
m_StartFadeTime = Time.time + CompletionDelay;
m_IsFadingIn = false;
m_IsMovingIn = false;
// if a sound was set, play it
PlaySound(CompletedSound);
// start the fade out
m_IsFadingOut = true;
m_IsMovingOut = true;
}
void Update()
{
float timeSinceFadeStarted = Time.time - m_StartFadeTime;
SubTitleRect.gameObject.SetActive(!string.IsNullOrEmpty(DescriptionTextContent.text));
if (m_IsFadingIn && !m_IsFadingOut)
{
// fade in
if (timeSinceFadeStarted < FadeInDuration)
{
// calculate alpha ratio
CanvasGroup.alpha = timeSinceFadeStarted / FadeInDuration;
}
else
{
CanvasGroup.alpha = 1f;
// end the fade in
m_IsFadingIn = false;
PlaySound(InitSound);
}
}
if (m_IsMovingIn && !m_IsMovingOut)
{
// move in
if (timeSinceFadeStarted < MoveInDuration)
{
LayoutGroup.padding.left = (int) MoveInCurve.Evaluate(timeSinceFadeStarted / MoveInDuration);
if (GetComponent<RectTransform>())
{
LayoutRebuilder.ForceRebuildLayoutImmediate(GetComponent<RectTransform>());
}
}
else
{
// making sure the position is exact
LayoutGroup.padding.left = 0;
if (GetComponent<RectTransform>())
{
LayoutRebuilder.ForceRebuildLayoutImmediate(GetComponent<RectTransform>());
}
m_IsMovingIn = false;
}
}
if (m_IsFadingOut)
{
// fade out
if (timeSinceFadeStarted < FadeOutDuration)
{
// calculate alpha ratio
CanvasGroup.alpha = 1 - (timeSinceFadeStarted) / FadeOutDuration;
}
else
{
CanvasGroup.alpha = 0f;
// end the fade out, then destroy the object
m_IsFadingOut = false;
Destroy(gameObject);
}
}
if (m_IsMovingOut)
{
// move out
if (timeSinceFadeStarted < MoveOutDuration)
{
LayoutGroup.padding.left = (int) MoveOutCurve.Evaluate(timeSinceFadeStarted / MoveOutDuration);
if (GetComponent<RectTransform>())
{
LayoutRebuilder.ForceRebuildLayoutImmediate(GetComponent<RectTransform>());
}
}
else
{
m_IsMovingOut = false;
}
}
}
void PlaySound(AudioClip sound)
{
if (!sound)
return;
if (!m_AudioSource)
{
m_AudioSource = gameObject.AddComponent<AudioSource>();
m_AudioSource.outputAudioMixerGroup = AudioUtility.GetAudioGroup(AudioUtility.AudioGroups.HUDObjective);
}
m_AudioSource.PlayOneShot(sound);
}
}
}
借鉴
- 在EnemyController里设置被击杀函数
- 调用UnregisterEnemy函数。
- 之前要先定义一个 EnemyManager m_EnemyManager;
EnemyManager m_EnemyManager;
void OnDie()
{
// spawn a particle system when dying
var vfx = Instantiate(DeathVfx, DeathVfxSpawnPoint.position, Quaternion.identity);
Destroy(vfx, 5f);
// tells the game flow manager to handle the enemy destuction
m_EnemyManager.UnregisterEnemy(this);
// loot an object
if (TryDropItem())
{
Instantiate(LootPrefab, transform.position, Quaternion.identity);
}
// this will call the OnDestroy function
Destroy(gameObject, DeathDuration);
}
- 在挂在GameHUD的EnemyManager上:
using System.Collections.Generic;
using Unity.FPS.Game;
using UnityEngine;
namespace Unity.FPS.AI
{
public class EnemyManager : MonoBehaviour
{
public List<EnemyController> Enemies { get; private set; }
public int NumberOfEnemiesTotal { get; private set; }
public int NumberOfEnemiesRemaining => Enemies.Count;
void Awake()
{
Enemies = new List<EnemyController>();
}
public void RegisterEnemy(EnemyController enemy)
{
Enemies.Add(enemy);
NumberOfEnemiesTotal++;
}
public void UnregisterEnemy(EnemyController enemyKilled)
{
int enemiesRemainingNotification = NumberOfEnemiesRemaining - 1;
EnemyKillEvent evt = Events.EnemyKillEvent;
evt.Enemy = enemyKilled.gameObject;
evt.RemainingEnemyCount = enemiesRemainingNotification;
EventManager.Broadcast(evt);
// removes the enemy from the list, so that we can keep track of how many are left on the map
Enemies.Remove(enemyKilled);
}
}
}