您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
367 行
11 KiB
367 行
11 KiB
using System;
|
|
using System.Collections;
|
|
using GameplayIngredients;
|
|
using UnityEngine;
|
|
using UnityEngine.AddressableAssets;
|
|
using UnityEngine.Rendering.Universal;
|
|
using UnityEngine.ResourceManagement.AsyncOperations;
|
|
using UnityEngine.SceneManagement;
|
|
using Random = UnityEngine.Random;
|
|
#if UNITY_EDITOR
|
|
using UnityEditor.SceneManagement;
|
|
#endif
|
|
// ReSharper disable InconsistentNaming
|
|
|
|
namespace BoatAttack
|
|
{
|
|
[ManagerDefaultPrefab(nameof(AppSettings))]
|
|
public class AppSettings : Manager
|
|
{
|
|
public enum RenderRes
|
|
{
|
|
_Native,
|
|
_1440p,
|
|
_1080p,
|
|
_720p
|
|
}
|
|
|
|
public enum Framerate
|
|
{
|
|
_30,
|
|
_60,
|
|
_120
|
|
}
|
|
|
|
public enum SpeedFormat
|
|
{
|
|
_Kph,
|
|
_Mph
|
|
}
|
|
|
|
public static AppSettings Instance;
|
|
private GameObject loadingScreenObject;
|
|
public static Camera MainCamera;
|
|
[Header("Resolution Settings")]
|
|
public RenderRes maxRenderSize = RenderRes._720p;
|
|
public bool variableResolution;
|
|
[Range(0f, 1f)]
|
|
public float axisBias = 0.5f;
|
|
public float minScale = 0.5f;
|
|
public Framerate targetFramerate = Framerate._30;
|
|
private float currentDynamicScale = 1.0f;
|
|
private float maxScale = 1.0f;
|
|
public SpeedFormat speedFormat = SpeedFormat._Mph;
|
|
|
|
[Header("Asset References")]
|
|
public AssetReference loadingScreen;
|
|
public AssetReference volumeManager;
|
|
[Header("Prefabs")]
|
|
public GameObject consoleCanvas;
|
|
public static GameObject ConsoleCanvas;
|
|
|
|
// Use this for initialization
|
|
private void Awake()
|
|
{
|
|
if(UniversalRenderPipeline.asset.debugLevel == PipelineDebugLevel.Profiling)
|
|
Debug.Log("AppManager initializing");
|
|
Initialize();
|
|
CmdArgs();
|
|
SetRenderScale();
|
|
SceneManager.sceneLoaded += LevelWasLoaded;
|
|
}
|
|
|
|
private void Initialize()
|
|
{
|
|
Instance = this;
|
|
ConsoleCanvas = Instantiate(consoleCanvas);
|
|
DontDestroyOnLoad(ConsoleCanvas);
|
|
MainCamera = Camera.main;
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
SceneManager.sceneLoaded -= LevelWasLoaded;
|
|
}
|
|
|
|
private static void LevelWasLoaded(Scene scene, LoadSceneMode mode)
|
|
{
|
|
CleanupCameras();
|
|
Instance.Invoke(nameof(CleanupLoadingScreen), 0.5f);
|
|
}
|
|
|
|
private static void CleanupCameras()
|
|
{
|
|
foreach (var c in GameObject.FindGameObjectsWithTag("MainCamera"))
|
|
{
|
|
if (MainCamera != null && c != MainCamera.gameObject)
|
|
{
|
|
Destroy(c);
|
|
}
|
|
else
|
|
{
|
|
MainCamera = c.GetComponent<Camera>();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CleanupLoadingScreen()
|
|
{
|
|
if(loadingScreenObject) loadingScreen?.ReleaseInstance(loadingScreenObject);
|
|
}
|
|
|
|
private void SetRenderScale()
|
|
{
|
|
var res = maxRenderSize switch
|
|
{
|
|
RenderRes._720p => 1280f,
|
|
RenderRes._1080p => 1920f,
|
|
RenderRes._1440p => 2560f,
|
|
_ => Screen.width
|
|
};
|
|
var renderScale = Mathf.Clamp(res / Screen.width, 0.1f, 1.0f);
|
|
|
|
if(UniversalRenderPipeline.asset.debugLevel == PipelineDebugLevel.Profiling)
|
|
Debug.Log($"Settings render scale to {renderScale * 100}% based on {maxRenderSize.ToString()}");
|
|
|
|
maxScale = renderScale;
|
|
#if !UNITY_EDITOR
|
|
UniversalRenderPipeline.asset.renderScale = renderScale;
|
|
#endif
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
#if !UNITY_EDITOR
|
|
Utility.CheckQualityLevel(); //TODO - hoping to remove one day when we have a quality level callback
|
|
#endif
|
|
|
|
if (!MainCamera) return;
|
|
|
|
if (variableResolution)
|
|
{
|
|
MainCamera.allowDynamicResolution = true;
|
|
|
|
var offset = 0f;
|
|
var currentFrametime = Time.deltaTime;
|
|
const float rate = 0.1f;
|
|
|
|
offset = targetFramerate switch
|
|
{
|
|
Framerate._30 => currentFrametime > (1000f / 30f) ? -rate : rate,
|
|
Framerate._60 => currentFrametime > (1000f / 60f) ? -rate : rate,
|
|
Framerate._120 => currentFrametime > (1000f / 120f) ? -rate : rate,
|
|
_ => offset
|
|
};
|
|
|
|
currentDynamicScale = Mathf.Clamp(currentDynamicScale + offset, minScale, 1f);
|
|
|
|
var offsetVec = new Vector2(Mathf.Lerp(1, currentDynamicScale, Mathf.Clamp01((1 - axisBias) * 2f)),
|
|
Mathf.Lerp(1, currentDynamicScale, Mathf.Clamp01(axisBias * 2f)));
|
|
|
|
ScalableBufferManager.ResizeBuffers(offsetVec.x, offsetVec.y);
|
|
}
|
|
else
|
|
{
|
|
MainCamera.allowDynamicResolution = false;
|
|
}
|
|
}
|
|
|
|
public void ToggleSRPBatcher(bool enabled)
|
|
{
|
|
UniversalRenderPipeline.asset.useSRPBatcher = enabled;
|
|
}
|
|
|
|
public static void LoadScene(int buildIndex, LoadSceneMode mode = LoadSceneMode.Single)
|
|
{
|
|
LoadScene(SceneUtility.GetScenePathByBuildIndex(buildIndex), mode);
|
|
}
|
|
|
|
public static void LoadScene(string scenePath, LoadSceneMode mode = LoadSceneMode.Single)
|
|
{
|
|
Application.backgroundLoadingPriority = ThreadPriority.Low;
|
|
switch (mode)
|
|
{
|
|
case LoadSceneMode.Single:
|
|
Instance.StartCoroutine(LoadSceneInternal(scenePath));
|
|
break;
|
|
case LoadSceneMode.Additive:
|
|
SceneManager.LoadSceneAsync(scenePath, LoadSceneMode.Additive);
|
|
break;
|
|
default:
|
|
throw new ArgumentOutOfRangeException(nameof(mode), mode, null);
|
|
}
|
|
}
|
|
|
|
private static IEnumerator LoadSceneInternal(string scenePath)
|
|
{
|
|
var loadingScreenLoading = Instance.loadingScreen.InstantiateAsync();
|
|
yield return loadingScreenLoading;
|
|
Instance.loadingScreenObject = loadingScreenLoading.Result;
|
|
Instance.loadingScreenObject.SendMessage("SetLoad", 0.0001f);
|
|
DontDestroyOnLoad(Instance.loadingScreenObject);
|
|
|
|
var buildIndex = SceneUtility.GetBuildIndexByScenePath(scenePath);
|
|
if(Debug.isDebugBuild)
|
|
Debug.Log($"loading scene {scenePath} at build index {buildIndex}");
|
|
|
|
// get current scene and set a loading scene as active
|
|
var currentScene = SceneManager.GetActiveScene();
|
|
var loadingScene = SceneManager.CreateScene("Loading");
|
|
SceneManager.SetActiveScene(loadingScene);
|
|
|
|
// unload last scene
|
|
var unload = SceneManager.UnloadSceneAsync(currentScene, UnloadSceneOptions.None);
|
|
while (!unload.isDone)
|
|
{
|
|
Instance.loadingScreenObject.SendMessage("SetLoad", unload.progress * 0.5f);
|
|
yield return null;
|
|
}
|
|
|
|
// clean up
|
|
var clean = Resources.UnloadUnusedAssets();
|
|
while (!clean.isDone) { yield return null; }
|
|
|
|
// load new scene
|
|
var load = new AsyncOperation();
|
|
#if UNITY_EDITOR
|
|
if (buildIndex == -1)
|
|
{
|
|
load = EditorSceneManager.LoadSceneAsyncInPlayMode(scenePath,
|
|
new LoadSceneParameters(LoadSceneMode.Single));
|
|
}
|
|
else
|
|
{
|
|
load = SceneManager.LoadSceneAsync(buildIndex);
|
|
}
|
|
#else
|
|
load = SceneManager.LoadSceneAsync(scenePath);
|
|
#endif
|
|
while (!load.isDone)
|
|
{
|
|
Instance.loadingScreenObject.SendMessage("SetLoad", load.progress * 0.5f + 0.5f);
|
|
yield return null;
|
|
}
|
|
}
|
|
|
|
private static IEnumerator LoadPrefab<T>(AssetReference assetRef, AsyncOperationHandle assetLoading, Transform parent = null)
|
|
{
|
|
if (typeof(T) == typeof(GameObject))
|
|
{
|
|
assetLoading = assetRef.InstantiateAsync(parent);
|
|
}
|
|
else
|
|
{
|
|
assetLoading = assetRef.LoadAssetAsync<T>();
|
|
}
|
|
yield return assetLoading;
|
|
}
|
|
|
|
public static void ExitGame(string s = "null")
|
|
{
|
|
if(s != "null")
|
|
Debug.LogError(s);
|
|
#if UNITY_EDITOR
|
|
UnityEditor.EditorApplication.ExitPlaymode();
|
|
#else
|
|
Application.Quit();
|
|
#endif
|
|
}
|
|
|
|
private static void CmdArgs()
|
|
{
|
|
var args = Environment.GetCommandLineArgs();
|
|
if (args.Length <= 0) return;
|
|
foreach (var argRaw in args)
|
|
{
|
|
if(string.IsNullOrEmpty(argRaw) || argRaw[0] != '-') continue;
|
|
var arg = argRaw.Split(':');
|
|
|
|
switch (arg[0])
|
|
{
|
|
case "-loadlevel":
|
|
LoadScene(arg[1]);
|
|
break;
|
|
case "-benchmarkFlythrough":
|
|
LoadScene("benchmark_island-flythrough");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static class ConstantData
|
|
{
|
|
private static readonly string[] Levels =
|
|
{
|
|
"Island",
|
|
};
|
|
|
|
public static string GetLevelName(int level)
|
|
{
|
|
return $"scenes/_levels/level_{Levels[level]}";
|
|
}
|
|
|
|
public static readonly string[] AiNames =
|
|
{
|
|
"Felipe",
|
|
"Andre",
|
|
"Elvar",
|
|
"Jonas",
|
|
"Erika",
|
|
"Tim",
|
|
"Florin",
|
|
"Andy",
|
|
"Hakeem",
|
|
"Sophia",
|
|
"Martin",
|
|
};
|
|
|
|
public static readonly int[] Laps =
|
|
{
|
|
1,
|
|
3,
|
|
6,
|
|
9
|
|
};
|
|
|
|
public static int SeedNow
|
|
{
|
|
get
|
|
{
|
|
DateTime dt = DateTime.Now;
|
|
return dt.Year + dt.Month + dt.Day + dt.Hour + dt.Minute + dt.Second;
|
|
}
|
|
}
|
|
|
|
public static Color[] ColorPalette;
|
|
private static Texture2D _colorPaletteRaw;
|
|
|
|
public static Color GetPaletteColor(int index)
|
|
{
|
|
GenerateColors();
|
|
return ColorPalette[index];
|
|
}
|
|
|
|
public static Color GetRandomPaletteColor
|
|
{
|
|
get
|
|
{
|
|
GenerateColors();
|
|
Random.InitState(SeedNow+Random.Range(0,1000));
|
|
return ColorPalette[Random.Range(0, ColorPalette.Length)];
|
|
}
|
|
}
|
|
|
|
private static void GenerateColors()
|
|
{
|
|
if (ColorPalette != null && ColorPalette.Length != 0) return;
|
|
|
|
if (_colorPaletteRaw == null)
|
|
_colorPaletteRaw = Resources.Load<Texture2D>("textures/colorSwatch");
|
|
|
|
ColorPalette = _colorPaletteRaw.GetPixels();
|
|
Debug.Log($"Found {ColorPalette.Length} colors.");
|
|
}
|
|
|
|
}
|
|
}
|