本身也具有一些unity知识,包括Eidtor界面使用、Shader效果实现、性能分析,但对C#、游戏逻辑不太清楚,这次想从开发者角度理解游戏,提高C#编程,从简单的unity游戏理解游戏逻辑,更好的为工作服务。
unity2019.4.40f1c1,使用Unity官网FPS Microgame(如下图)。原本想从游戏源码启动流程开始学习,但Unity核心代码没有开源,就还是先理解游戏逻辑。

游戏分成 5个Scene,我们关注MainScene,其中有个GameManager,从Inspector看挂有许多Scripts,我们先一个个分析。



GameFlowManager,引用using UnityEngine.SceneManagement,定义类GameFlowManager前半部分是在自定义Eidtor界面,这里float timeRatio = 1 - (m_TimeLoadEndGameScene - Time.time) / endSceneLoadDelay;不是很理解,待续
- using UnityEngine;
- using UnityEngine.SceneManagement;
-
- public class GameFlowManager : MonoBehaviour
- {
- [Header("Parameters")]
- [Tooltip("Duration of the fade-to-black at the end of the game")]
- public float endSceneLoadDelay = 3f;
- [Tooltip("The canvas group of the fade-to-black screen")]
- public CanvasGroup endGameFadeCanvasGroup;
-
- [Header("Win")]
- [Tooltip("This string has to be the name of the scene you want to load when winning")]
- public string winSceneName = "WinScene";
- [Tooltip("Duration of delay before the fade-to-black, if winning")]
- public float delayBeforeFadeToBlack = 4f;
- [Tooltip("Duration of delay before the win message")]
- public float delayBeforeWinMessage = 2f;
- [Tooltip("Sound played on win")]
- public AudioClip victorySound;
- [Tooltip("Prefab for the win game message")]
- public GameObject WinGameMessagePrefab;
-
- [Header("Lose")]
- [Tooltip("This string has to be the name of the scene you want to load when losing")]
- public string loseSceneName = "LoseScene";
-
-
- public bool gameIsEnding { get; private set; }
-
- PlayerCharacterController m_Player;
- NotificationHUDManager m_NotificationHUDManager;
- ObjectiveManager m_ObjectiveManager;
- float m_TimeLoadEndGameScene;
- string m_SceneToLoad;
-
- void Start()
- {
- Debug.Log("Start Game: " + m_Player);
- //返回场景中的所填类型的随机个体
- m_Player = FindObjectOfType
(); - //DebugUtility.cs不是Unity中的内置脚本,存在Assets/FPS/Scripts/DebugUtility.cs
- DebugUtility.HandleErrorIfNullFindObject
(m_Player, this); -
- m_ObjectiveManager = FindObjectOfType
(); - DebugUtility.HandleErrorIfNullFindObject
(m_ObjectiveManager, this); -
- AudioUtility.SetMasterVolume(1);
- }
-
- void Update()
- {
- if (gameIsEnding)
- {
- Debug.Log("m_TimeLoadEndGameScene: " + m_TimeLoadEndGameScene);
- Debug.Log("Time.time: " + Time.time);
- Debug.Log("endSceneLoadDelay: " + endSceneLoadDelay);
- float timeRatio = 1 - (m_TimeLoadEndGameScene - Time.time) / endSceneLoadDelay;
- Debug.Log("timeRatio: " + timeRatio);
-
- endGameFadeCanvasGroup.alpha = timeRatio;
-
- AudioUtility.SetMasterVolume(1 - timeRatio);
-
- // See if it's time to load the (after the delay)
- if (Time.time >= m_TimeLoadEndGameScene)
- {
- Debug.Log("Scene loading: " + m_SceneToLoad);
- SceneManager.LoadScene(m_SceneToLoad);
- gameIsEnding = false;
- }
- }
- else
- {
- if (m_ObjectiveManager.AreAllObjectivesCompleted())
- EndGame(true);
-
- // Test if player died
- if (m_Player.isDead)
- EndGame(false);
- }
- }
-
- void EndGame(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 win
- var audioSource = gameObject.AddComponent
(); - 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
(); - if (message)
- {
- message.delayBeforeShowing = delayBeforeWinMessage;
- message.GetComponent
().SetAsLastSibling(); - }
- }
- else
- {
- m_SceneToLoad = loseSceneName;
- m_TimeLoadEndGameScene = Time.time + endSceneLoadDelay;
- }
- }
- }