refactor
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using RebootKit.Engine.Services.Console;
|
||||
using RebootKit.Engine.Foundation;
|
||||
using RebootKit.Engine.Services.Console;
|
||||
using RebootKitEditor.Utils;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
namespace RebootKitEditor {
|
||||
static class REditorConsts {
|
||||
internal const string k_EditorMenu = "Reboot Reality/";
|
||||
|
||||
internal const string k_OnGameRunScriptContentKey = "RebootKitEditor.OnGameRunScriptContent";
|
||||
}
|
||||
}
|
||||
@@ -27,21 +27,23 @@ namespace RebootKitEditor.RebootWindow {
|
||||
public VisualElement Build() {
|
||||
m_RootElement = new ScrollView();
|
||||
|
||||
Label servicesAmountLabel = new($"Game services: {m_EngineConfigAsset.services.Length}") {
|
||||
style = {
|
||||
color = new Color(0.7f, 0.9f, 0.9f),
|
||||
unityFontStyleAndWeight = FontStyle.Bold
|
||||
}
|
||||
};
|
||||
m_RootElement.Add(servicesAmountLabel);
|
||||
|
||||
for (int i = 0; i < m_EngineConfigAsset.services.Length; i++) {
|
||||
ServiceAsset serviceAsset = m_EngineConfigAsset.services[i];
|
||||
|
||||
VisualElement serviceView = CreateServicesView(serviceAsset);
|
||||
serviceView.style.backgroundColor = i % 2 == 0 ? new Color(0.1f, 0.1f, 0.1f) : new Color(0.2f, 0.2f, 0.2f);
|
||||
m_RootElement.Add(serviceView);
|
||||
}
|
||||
// int servicesLength = m_EngineConfigAsset.services?.Length ?? 0;
|
||||
//
|
||||
// Label servicesAmountLabel = new($"Game services: {servicesLength}") {
|
||||
// style = {
|
||||
// color = new Color(0.7f, 0.9f, 0.9f),
|
||||
// unityFontStyleAndWeight = FontStyle.Bold
|
||||
// }
|
||||
// };
|
||||
// m_RootElement.Add(servicesAmountLabel);
|
||||
//
|
||||
// for (int i = 0; i < servicesLength; i++) {
|
||||
// ServiceAsset serviceAsset = m_EngineConfigAsset.services[i];
|
||||
//
|
||||
// VisualElement serviceView = CreateServicesView(serviceAsset);
|
||||
// serviceView.style.backgroundColor = i % 2 == 0 ? new Color(0.1f, 0.1f, 0.1f) : new Color(0.2f, 0.2f, 0.2f);
|
||||
// m_RootElement.Add(serviceView);
|
||||
// }
|
||||
|
||||
return m_RootElement;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using RebootKit.Engine.UI;
|
||||
using RebootKit.Engine.Main;
|
||||
using RebootKit.Engine.Services.Console;
|
||||
using RebootKit.Engine.UI;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
@@ -55,6 +58,67 @@ namespace RebootKitEditor.RebootWindow {
|
||||
persistentPathContainer.Add(openPersistentPathButton);
|
||||
|
||||
rootContainer.Add(persistentPathContainer);
|
||||
|
||||
Label onGameRunScriptLabel = new("On Game Run Script (User):") {
|
||||
style = {
|
||||
fontSize = 12,
|
||||
color = new Color(0.7f, 0.9f, 0.9f)
|
||||
}
|
||||
};
|
||||
rootContainer.Add(onGameRunScriptLabel);
|
||||
|
||||
TextField onGameRunScriptTextField = new() {
|
||||
style = {
|
||||
fontSize = 12,
|
||||
},
|
||||
multiline = true,
|
||||
value = EditorPrefs.GetString(REditorConsts.k_OnGameRunScriptContentKey, "")
|
||||
};
|
||||
|
||||
onGameRunScriptTextField.RegisterValueChangedCallback(evt => {
|
||||
EditorPrefs.SetString(REditorConsts.k_OnGameRunScriptContentKey, evt.newValue);
|
||||
});
|
||||
rootContainer.Add(onGameRunScriptTextField);
|
||||
|
||||
Label consoleCommandsLabel = new("Console Commands:") {
|
||||
style = {
|
||||
fontSize = 12,
|
||||
color = new Color(0.7f, 0.9f, 0.9f)
|
||||
}
|
||||
};
|
||||
rootContainer.Add(consoleCommandsLabel);
|
||||
|
||||
ConsoleService.ConsoleCommand[] consoleCommands = ConsoleService.GenerateCommandsToRegister();
|
||||
foreach (ConsoleService.ConsoleCommand consoleCommand in consoleCommands) {
|
||||
VisualElement commandContainer = new() {
|
||||
style = {
|
||||
flexDirection = FlexDirection.Row,
|
||||
marginTop = 4,
|
||||
marginBottom = 4,
|
||||
paddingLeft = 4,
|
||||
paddingRight = 4,
|
||||
paddingTop = 4,
|
||||
paddingBottom = 4,
|
||||
}
|
||||
};
|
||||
Label commandLabel = new(consoleCommand.name) {
|
||||
style = {
|
||||
fontSize = 12,
|
||||
color = new Color(0.7f, 0.9f, 0.9f)
|
||||
}
|
||||
};
|
||||
commandContainer.Add(commandLabel);
|
||||
|
||||
Label descriptionLabel = new(consoleCommand.description) {
|
||||
style = {
|
||||
fontSize = 12,
|
||||
color = new Color(0.5f, 0.7f, 0.7f)
|
||||
}
|
||||
};
|
||||
commandContainer.Add(descriptionLabel);
|
||||
|
||||
rootContainer.Add(commandContainer);
|
||||
}
|
||||
|
||||
return rootContainer;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace RebootKitEditor.RebootWindow {
|
||||
}
|
||||
};
|
||||
root.Add(label);
|
||||
|
||||
|
||||
Button openButton = new(() => OpenWorldScenes(worldConfigAsset)) {
|
||||
text = "Open",
|
||||
style = {
|
||||
@@ -76,14 +76,16 @@ namespace RebootKitEditor.RebootWindow {
|
||||
return;
|
||||
}
|
||||
|
||||
EditorSceneManager.SaveOpenScenes();
|
||||
|
||||
// Load first scene from build settings
|
||||
string mainScenePath = SceneManager.GetSceneByBuildIndex(RConsts.k_MainSceneBuildIndex).path;
|
||||
string mainScenePath = GetScenePathByBuildIndex(RConsts.k_MainSceneBuildIndex);
|
||||
if (mainScenePath == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
EditorSceneManager.OpenScene(mainScenePath, OpenSceneMode.Single);
|
||||
|
||||
// Load world scene
|
||||
string worldScenePath = AssetDatabase.GetAssetPath(worldConfigAsset.Config.mainScene.editorAsset);
|
||||
string worldScenePath = AssetDatabase.GUIDToAssetPath(worldConfigAsset.Config.mainScene.AssetGUID);
|
||||
if (string.IsNullOrEmpty(worldScenePath)) {
|
||||
Debug.LogError($"WorldConfigAsset {worldConfigAsset.name} has invalid main scene path");
|
||||
return;
|
||||
@@ -91,5 +93,14 @@ namespace RebootKitEditor.RebootWindow {
|
||||
|
||||
SceneManager.SetActiveScene(EditorSceneManager.OpenScene(worldScenePath, OpenSceneMode.Additive));
|
||||
}
|
||||
|
||||
static string GetScenePathByBuildIndex(int buildIndex) {
|
||||
if (buildIndex < 0 || buildIndex >= EditorBuildSettings.scenes.Length) {
|
||||
Debug.LogError($"Build index {buildIndex} out of range. Total scenes in build: {EditorBuildSettings.scenes.Length}");
|
||||
return null;
|
||||
}
|
||||
|
||||
return EditorBuildSettings.scenes[buildIndex].path;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
# RebootKit
|
||||
|
||||
# Installation
|
||||
# Installationa (WIP)
|
||||
|
||||
### nuget
|
||||
|
||||
@@ -22,3 +22,10 @@ Ensure you have the following dependencies in your `Packages/manifest.json` file
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
# TODO
|
||||
- [ ] Save system
|
||||
- [ ] Built in main menu
|
||||
- [ ] Generic settings ui based on Config Variables
|
||||
- [ ] Extendable FPP Controller
|
||||
- [ ] UI System
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
using System;
|
||||
using RebootKit.Engine.Services.Game;
|
||||
using UnityEngine.AddressableAssets;
|
||||
|
||||
namespace RebootKit.Engine {
|
||||
[Serializable]
|
||||
public class AppConfig {
|
||||
public MainMenuConfig mainMenuConfig;
|
||||
public GameConfig gameConfig;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class MainMenuConfig {
|
||||
public AssetReference scene;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class GameConfig {
|
||||
public GameModeAsset defaultGameMode;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 75a5232723f54287b48c0294a0009869
|
||||
timeCreated: 1743174115
|
||||
3
Runtime/Engine/Code/Components.meta
Normal file
3
Runtime/Engine/Code/Components.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 87d77002476b4d1cbe17b0b969e66c9d
|
||||
timeCreated: 1746819904
|
||||
39
Runtime/Engine/Code/Components/CopyTransform.cs
Normal file
39
Runtime/Engine/Code/Components/CopyTransform.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace RebootKit.Engine.Components {
|
||||
[Flags]
|
||||
public enum TransformComponents {
|
||||
None = 0,
|
||||
Position = 1 << 0,
|
||||
Rotation = 1 << 1,
|
||||
Scale = 1 << 2,
|
||||
All = Position | Rotation | Scale
|
||||
}
|
||||
|
||||
[DefaultExecutionOrder(100)]
|
||||
public class CopyTransform : MonoBehaviour {
|
||||
[SerializeField] TransformComponents m_Components = TransformComponents.All;
|
||||
[SerializeField] Transform m_Source;
|
||||
|
||||
Transform m_Transform;
|
||||
|
||||
void Awake() {
|
||||
m_Transform = transform;
|
||||
}
|
||||
|
||||
void LateUpdate() {
|
||||
if (m_Components.HasFlag(TransformComponents.Position)) {
|
||||
m_Transform.position = m_Source.position;
|
||||
}
|
||||
|
||||
if (m_Components.HasFlag(TransformComponents.Rotation)) {
|
||||
m_Transform.rotation = m_Source.rotation;
|
||||
}
|
||||
|
||||
if (m_Components.HasFlag(TransformComponents.Scale)) {
|
||||
m_Transform.localScale = m_Source.localScale;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Runtime/Engine/Code/Components/CopyTransform.cs.meta
Normal file
3
Runtime/Engine/Code/Components/CopyTransform.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 43e47286597d44b9bca21389d3909958
|
||||
timeCreated: 1746661605
|
||||
@@ -1,4 +1,4 @@
|
||||
using RebootKit.Engine.Foundation;
|
||||
using RebootKit.Engine.Main;
|
||||
using UnityEngine;
|
||||
|
||||
namespace RebootKit.Engine {
|
||||
@@ -7,8 +7,7 @@ namespace RebootKit.Engine {
|
||||
public bool initializeOnLoad = true;
|
||||
|
||||
public EngineCoreServicesAsset coreServices;
|
||||
public ServiceAsset[] services;
|
||||
|
||||
public AppConfig appConfig;
|
||||
|
||||
public GameAsset gameAsset;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using RebootKit.Engine.Foundation;
|
||||
using RebootKit.Engine.Services.Console;
|
||||
using RebootKit.Engine.Services.Game;
|
||||
using RebootKit.Engine.Services.GameMode;
|
||||
using RebootKit.Engine.Services.Input;
|
||||
using RebootKit.Engine.Services.Simulation;
|
||||
using UnityEngine;
|
||||
@@ -11,6 +11,6 @@ namespace RebootKit.Engine {
|
||||
public ServiceAsset<ConsoleService> consoleService;
|
||||
public ServiceAsset<InputService> inputService;
|
||||
public ServiceAsset<WorldService> worldService;
|
||||
public ServiceAsset<GameService> gameService;
|
||||
public ServiceAsset<GameModesService> gameService;
|
||||
}
|
||||
}
|
||||
@@ -32,5 +32,12 @@ namespace RebootKit.Engine.Extensions {
|
||||
public static bool IsNonZero(this float3 vec, float epsilon = float.Epsilon) {
|
||||
return !vec.IsZero(epsilon);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsInRange(this float3 vec, float3 pos, float range) {
|
||||
float dstSquared = math.distancesq(vec, pos);
|
||||
float rangeSquared = range * range;
|
||||
return dstSquared <= rangeSquared;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
|
||||
namespace RebootKit.Engine.Services.Console {
|
||||
namespace RebootKit.Engine.Foundation {
|
||||
public enum CVarValueKind {
|
||||
Number, String
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using RebootKit.Engine.Main;
|
||||
|
||||
namespace RebootKit.Engine.Foundation {
|
||||
public enum LogLevel {
|
||||
@@ -19,16 +20,16 @@ namespace RebootKit.Engine.Foundation {
|
||||
public void Log(LogLevel level, string message) {
|
||||
switch (level) {
|
||||
case LogLevel.Info:
|
||||
UnityEngine.Debug.Log(FormatMessage(level, m_Name, message, true));
|
||||
RR.Log(FormatMessage(level, m_Name, message, true));
|
||||
break;
|
||||
case LogLevel.Debug:
|
||||
UnityEngine.Debug.Log(FormatMessage(level, m_Name, message, true));
|
||||
RR.Log(FormatMessage(level, m_Name, message, true));
|
||||
break;
|
||||
case LogLevel.Warning:
|
||||
UnityEngine.Debug.LogWarning(FormatMessage(level, m_Name, message, true));
|
||||
RR.LogWarning(FormatMessage(level, m_Name, message, true));
|
||||
break;
|
||||
case LogLevel.Error:
|
||||
UnityEngine.Debug.LogError(FormatMessage(level, m_Name, message, true));
|
||||
RR.LogError(FormatMessage(level, m_Name, message, true));
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(level), level, null);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using UnityEngine;
|
||||
using RebootKit.Engine.Main;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Assertions;
|
||||
|
||||
namespace RebootKit.Engine.Foundation {
|
||||
@@ -20,7 +21,7 @@ namespace RebootKit.Engine.Foundation {
|
||||
DIContext context = RR.DIContext;
|
||||
|
||||
foreach (GameObject root in gameObject.scene.GetRootGameObjects()) {
|
||||
s_logger.Info("Injecting root game object: " + root.name);
|
||||
// s_logger.Info("Injecting root game object: " + root.name);
|
||||
context.InjectGameObject(root);
|
||||
}
|
||||
}
|
||||
|
||||
3
Runtime/Engine/Code/Main.meta
Normal file
3
Runtime/Engine/Code/Main.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce874693b1034e70a925c0043b78e7ea
|
||||
timeCreated: 1746821949
|
||||
@@ -1,10 +1,11 @@
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEditor;
|
||||
using RebootKit.Engine.Foundation;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using Logger = RebootKit.Engine.Foundation.Logger;
|
||||
|
||||
namespace RebootKit.Engine.Foundation {
|
||||
namespace RebootKit.Engine.Main {
|
||||
public static class EntryPoint {
|
||||
static readonly Logger s_logger = new(nameof(EntryPoint));
|
||||
|
||||
@@ -16,32 +17,30 @@ namespace RebootKit.Engine.Foundation {
|
||||
s_cancellationTokenSource.Cancel();
|
||||
}
|
||||
|
||||
RR.s_Shared = null;
|
||||
|
||||
// unload all scenes
|
||||
|
||||
s_cancellationTokenSource = new CancellationTokenSource();
|
||||
RunAsync(s_cancellationTokenSource.Token).Forget();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
static void OnPlayerModeState(PlayModeStateChange state) {
|
||||
if (state == PlayModeStateChange.ExitingPlayMode) {
|
||||
static void OnPlayerModeState(UnityEditor.PlayModeStateChange state) {
|
||||
if (state == UnityEditor.PlayModeStateChange.ExitingPlayMode) {
|
||||
s_cancellationTokenSource.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
EditorApplication.playModeStateChanged -= OnPlayerModeState;
|
||||
EditorApplication.playModeStateChanged += OnPlayerModeState;
|
||||
UnityEditor.EditorApplication.playModeStateChanged -= OnPlayerModeState;
|
||||
UnityEditor.EditorApplication.playModeStateChanged += OnPlayerModeState;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static async UniTask RunAsync(CancellationToken cancellationToken) {
|
||||
ConfigVarsContainer.Init();
|
||||
|
||||
s_logger.Info("Loading boot scene");
|
||||
SceneManager.LoadScene(RConsts.k_BootSceneBuildIndex, LoadSceneMode.Single);
|
||||
|
||||
|
||||
s_logger.Info("Loading engine config");
|
||||
EngineConfigAsset configAsset = Resources.Load<EngineConfigAsset>(RConsts.k_EngineConfigResourcesPath);
|
||||
if (configAsset == null) {
|
||||
if (configAsset is null) {
|
||||
s_logger.Error($"Couldn't load engine config from resources: {RConsts.k_EngineConfigResourcesPath}");
|
||||
return;
|
||||
}
|
||||
@@ -50,19 +49,18 @@ namespace RebootKit.Engine.Foundation {
|
||||
return;
|
||||
}
|
||||
|
||||
using RR instance = new();
|
||||
RR.s_Shared = instance;
|
||||
|
||||
s_logger.Info("Initializing RR");
|
||||
await instance.Init(configAsset, cancellationToken);
|
||||
await RR.InitAsync(configAsset, cancellationToken);
|
||||
|
||||
s_logger.Info("Loading main scene");
|
||||
await SceneManager.LoadSceneAsync(RConsts.k_MainSceneBuildIndex, LoadSceneMode.Single).ToUniTask(cancellationToken: cancellationToken);
|
||||
|
||||
s_logger.Info("Starting RR");
|
||||
instance.Run();
|
||||
RR.Run();
|
||||
|
||||
await UniTask.WaitUntilCanceled(Application.exitCancellationToken);
|
||||
|
||||
RR.Shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
201
Runtime/Engine/Code/Main/RR.cs
Normal file
201
Runtime/Engine/Code/Main/RR.cs
Normal file
@@ -0,0 +1,201 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using R3;
|
||||
using RebootKit.Engine.Foundation;
|
||||
using RebootKit.Engine.Services.Console;
|
||||
using RebootKit.Engine.Services.GameMode;
|
||||
using RebootKit.Engine.Services.Input;
|
||||
using RebootKit.Engine.Services.Simulation;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using Assert = UnityEngine.Assertions.Assert;
|
||||
using Logger = RebootKit.Engine.Foundation.Logger;
|
||||
|
||||
namespace RebootKit.Engine.Main {
|
||||
public interface IGame : IDisposable {
|
||||
UniTask InitAsync(CancellationToken cancellationToken);
|
||||
void Run();
|
||||
}
|
||||
|
||||
public abstract class GameAsset : ScriptableObject {
|
||||
public abstract IGame CreateGame();
|
||||
}
|
||||
|
||||
public static class RR {
|
||||
static readonly Logger s_logger = new("RR");
|
||||
|
||||
[ConfigVar("con.write_log", 1, "Enables writing game log to console output")]
|
||||
static ConfigVar s_writeLogToConsole;
|
||||
|
||||
static EngineConfigAsset s_engineConfigAsset;
|
||||
|
||||
static DisposableBag s_disposableBag;
|
||||
static DisposableBag s_servicesBag;
|
||||
static DIContext s_diContext;
|
||||
static ConsoleService s_consoleService;
|
||||
|
||||
static GameModesService s_gameModesService;
|
||||
static InputService s_inputService;
|
||||
static WorldService s_worldService;
|
||||
|
||||
public static ConsoleService Console => s_consoleService;
|
||||
public static InputService Input => s_inputService;
|
||||
public static WorldService World => s_worldService;
|
||||
public static GameModesService GameModes => s_gameModesService;
|
||||
public static DIContext DIContext => s_diContext;
|
||||
|
||||
static IGame s_game;
|
||||
|
||||
public static async UniTask InitAsync(EngineConfigAsset configAsset, CancellationToken cancellationToken) {
|
||||
Assert.IsNotNull(configAsset, "Config asset is required");
|
||||
Assert.IsNotNull(configAsset.gameAsset, "Game asset is required");
|
||||
|
||||
s_engineConfigAsset = configAsset;
|
||||
|
||||
s_logger.Info("Initializing");
|
||||
s_servicesBag = new DisposableBag();
|
||||
s_disposableBag = new DisposableBag();
|
||||
s_diContext = new DIContext();
|
||||
|
||||
s_logger.Debug("Registering core services");
|
||||
s_consoleService = CreateService(s_engineConfigAsset.coreServices.consoleService);
|
||||
s_inputService = CreateService(s_engineConfigAsset.coreServices.inputService);
|
||||
s_worldService = CreateService(s_engineConfigAsset.coreServices.worldService);
|
||||
s_gameModesService = CreateService(s_engineConfigAsset.coreServices.gameService);
|
||||
|
||||
await InitializeAssetsAsync(cancellationToken);
|
||||
|
||||
s_logger.Debug("Creating game");
|
||||
s_game = s_engineConfigAsset.gameAsset.CreateGame();
|
||||
|
||||
await s_game.InitAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public static void Shutdown() {
|
||||
s_logger.Info("Shutting down");
|
||||
s_servicesBag.Dispose();
|
||||
s_disposableBag.Dispose();
|
||||
}
|
||||
|
||||
public static void Run() {
|
||||
s_game.Run();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
string scriptContent = UnityEditor.EditorPrefs.GetString("RebootKitEditor.OnGameRunScriptContent", "");
|
||||
s_logger.Info($"Executing script: {scriptContent}");
|
||||
|
||||
if (!string.IsNullOrEmpty(scriptContent)) {
|
||||
foreach (string cmd in scriptContent.Split('\n')) {
|
||||
s_logger.Info($"Executing command: {cmd}");
|
||||
Console.Execute(cmd);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Assets API
|
||||
static readonly List<GameModeAsset> s_gameModesAssets = new();
|
||||
static readonly List<WorldConfigAsset> s_worldConfigsAssets = new();
|
||||
|
||||
public static IReadOnlyList<GameModeAsset> GameModesAssets => s_gameModesAssets;
|
||||
public static IReadOnlyList<WorldConfigAsset> WorldConfigsAssets => s_worldConfigsAssets;
|
||||
|
||||
public static async UniTask InitializeAssetsAsync(CancellationToken cancellationToken) {
|
||||
s_gameModesAssets.Clear();
|
||||
s_worldConfigsAssets.Clear();
|
||||
|
||||
s_logger.Info("Loading game assets");
|
||||
|
||||
await Addressables.LoadAssetsAsync<GameModeAsset>("game_mode", asset => { s_gameModesAssets.Add(asset); }).ToUniTask(cancellationToken: cancellationToken);
|
||||
s_logger.Info($"Loaded {s_gameModesAssets.Count} game modes");
|
||||
|
||||
await Addressables.LoadAssetsAsync<WorldConfigAsset>("world", asset => { s_worldConfigsAssets.Add(asset); }).ToUniTask(cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
// Game API
|
||||
public static void StartGameMode(GameModeAsset gameMode, WorldConfig world) {
|
||||
if (gameMode is null) {
|
||||
throw new ArgumentNullException(nameof(gameMode));
|
||||
}
|
||||
|
||||
s_logger.Info($"Starting game mode: {gameMode.name} in world: {world.name}");
|
||||
s_gameModesService.Start(gameMode, world);
|
||||
}
|
||||
|
||||
public static TGame Game<TGame>() where TGame : IGame {
|
||||
if (s_game is TGame game) {
|
||||
return game;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Game is not of type {typeof(TGame)}");
|
||||
}
|
||||
|
||||
// Service API
|
||||
public static TService CreateService<TService>(ServiceAsset<TService> asset) where TService : class, IService {
|
||||
TService service = asset.Create(s_diContext);
|
||||
s_diContext.Bind(service);
|
||||
s_servicesBag.Add(service);
|
||||
return service;
|
||||
}
|
||||
|
||||
public static TService CreateService<TService>() where TService : class, IService {
|
||||
TService service = s_diContext.Create<TService>();
|
||||
s_diContext.Bind(service);
|
||||
s_servicesBag.Add(service);
|
||||
return service;
|
||||
}
|
||||
|
||||
// General API
|
||||
public static void Log(string message) {
|
||||
Debug.Log(message);
|
||||
|
||||
s_consoleService?.WriteToOutput(message);
|
||||
}
|
||||
|
||||
public static void LogWarning(string message) {
|
||||
Debug.LogWarning(message);
|
||||
s_consoleService?.WriteToOutput(message);
|
||||
}
|
||||
|
||||
public static void LogError(string message) {
|
||||
Debug.LogError(message);
|
||||
s_consoleService?.WriteToOutput(message);
|
||||
}
|
||||
|
||||
// CVar API
|
||||
public static ConfigVar CVarIndex(string name, int defaultValue = -1) {
|
||||
ConfigVar cvar = ConfigVarsContainer.Get(name);
|
||||
if (cvar != null) {
|
||||
return cvar;
|
||||
}
|
||||
|
||||
cvar = new ConfigVar(name, defaultValue);
|
||||
ConfigVarsContainer.Register(cvar);
|
||||
return cvar;
|
||||
}
|
||||
|
||||
public static ConfigVar CVarNumber(string name, double defaultValue = 0) {
|
||||
ConfigVar cvar = ConfigVarsContainer.Get(name);
|
||||
if (cvar != null) {
|
||||
return cvar;
|
||||
}
|
||||
|
||||
cvar = new ConfigVar(name, defaultValue);
|
||||
ConfigVarsContainer.Register(cvar);
|
||||
return cvar;
|
||||
}
|
||||
|
||||
public static ConfigVar CVarString(string name, string defaultValue = "") {
|
||||
ConfigVar cvar = ConfigVarsContainer.Get(name);
|
||||
if (cvar != null) {
|
||||
return cvar;
|
||||
}
|
||||
|
||||
cvar = new ConfigVar(name, defaultValue);
|
||||
ConfigVarsContainer.Register(cvar);
|
||||
return cvar;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Runtime/Engine/Code/Misc.meta
Normal file
3
Runtime/Engine/Code/Misc.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7a57aa60af614860ba14c07fdb43ad4e
|
||||
timeCreated: 1746661579
|
||||
@@ -1,49 +0,0 @@
|
||||
using RebootKit.Engine.Foundation;
|
||||
using RebootKit.Engine.Services.Console;
|
||||
using RebootKit.Engine.Services.Game;
|
||||
using RebootKit.Engine.Services.Input;
|
||||
using RebootKit.Engine.Services.Simulation;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace RebootKit.Engine {
|
||||
public partial class RR {
|
||||
public static ConsoleService Console => s_Shared.m_ConsoleService;
|
||||
public static InputService Input => s_Shared.m_InputService;
|
||||
public static WorldService World => s_Shared.m_WorldService;
|
||||
public static GameService Game => s_Shared.m_GameService;
|
||||
public static DIContext DIContext => s_Shared.m_DIContext;
|
||||
|
||||
public static ConfigVar CVarIndex(string name, int defaultValue = -1) {
|
||||
ConfigVar cvar = ConfigVarsContainer.Get(name);
|
||||
if (cvar != null) {
|
||||
return cvar;
|
||||
}
|
||||
|
||||
cvar = new ConfigVar(name, defaultValue);
|
||||
ConfigVarsContainer.Register(cvar);
|
||||
return cvar;
|
||||
}
|
||||
|
||||
public static ConfigVar CVarNumber(string name, double defaultValue = 0) {
|
||||
ConfigVar cvar = ConfigVarsContainer.Get(name);
|
||||
if (cvar != null) {
|
||||
return cvar;
|
||||
}
|
||||
|
||||
cvar = new ConfigVar(name, defaultValue);
|
||||
ConfigVarsContainer.Register(cvar);
|
||||
return cvar;
|
||||
}
|
||||
|
||||
public static ConfigVar CVarString(string name, string defaultValue = "") {
|
||||
ConfigVar cvar = ConfigVarsContainer.Get(name);
|
||||
if (cvar != null) {
|
||||
return cvar;
|
||||
}
|
||||
|
||||
cvar = new ConfigVar(name, defaultValue);
|
||||
ConfigVarsContainer.Register(cvar);
|
||||
return cvar;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 90375a4c5db84d538d31d54f302ac022
|
||||
timeCreated: 1743212750
|
||||
@@ -1,14 +0,0 @@
|
||||
using System;
|
||||
using RebootKit.Engine.Services.Game;
|
||||
|
||||
namespace RebootKit.Engine {
|
||||
public partial class RR {
|
||||
public static void StartGameMode(GameModeAsset gameMode) {
|
||||
if (gameMode == null) {
|
||||
throw new ArgumentNullException(nameof(gameMode));
|
||||
}
|
||||
|
||||
s_Shared.m_GameService.Start(gameMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c614fae80bc84ae8b7f3ee034a42f074
|
||||
timeCreated: 1743437396
|
||||
@@ -1,80 +0,0 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using R3;
|
||||
using RebootKit.Engine.Foundation;
|
||||
using RebootKit.Engine.Services.Console;
|
||||
using RebootKit.Engine.Services.Game;
|
||||
using RebootKit.Engine.Services.Input;
|
||||
using RebootKit.Engine.Services.Simulation;
|
||||
using UnityEngine.Assertions;
|
||||
using Logger = RebootKit.Engine.Foundation.Logger;
|
||||
|
||||
namespace RebootKit.Engine {
|
||||
public partial class RR : IDisposable {
|
||||
internal static RR s_Shared;
|
||||
|
||||
static readonly Logger s_logger = new("RR");
|
||||
|
||||
DIContext m_DIContext;
|
||||
|
||||
ConsoleService m_ConsoleService;
|
||||
|
||||
EngineConfigAsset m_EngineConfigAsset;
|
||||
GameService m_GameService;
|
||||
InputService m_InputService;
|
||||
WorldService m_WorldService;
|
||||
|
||||
DisposableBag m_DisposableBag;
|
||||
|
||||
public RR() {
|
||||
m_DisposableBag = new DisposableBag();
|
||||
|
||||
m_DIContext = new DIContext();
|
||||
// m_DIContext.AddInjector(new CVarFieldInjector());
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
s_logger.Info("Shutting down");
|
||||
m_DisposableBag.Dispose();
|
||||
}
|
||||
|
||||
public async UniTask Init(EngineConfigAsset configAsset, CancellationToken cancellationToken) {
|
||||
Assert.IsNotNull(configAsset, "Config asset is required");
|
||||
|
||||
s_logger.Info("Initializing");
|
||||
m_EngineConfigAsset = configAsset;
|
||||
|
||||
CreateCoreServices();
|
||||
CreateServices();
|
||||
|
||||
await UniTask.Yield(cancellationToken);
|
||||
}
|
||||
|
||||
public void Run() {
|
||||
StartGameMode(m_EngineConfigAsset.appConfig.gameConfig.defaultGameMode);
|
||||
}
|
||||
|
||||
TService CreateService<TService>(ServiceAsset<TService> asset) where TService : class, IService {
|
||||
TService service = asset.Create(m_DIContext);
|
||||
m_DIContext.Bind(service);
|
||||
m_DisposableBag.Add(service);
|
||||
return service;
|
||||
}
|
||||
|
||||
void CreateCoreServices() {
|
||||
s_logger.Debug("Registering core services");
|
||||
|
||||
m_ConsoleService = CreateService(m_EngineConfigAsset.coreServices.consoleService);
|
||||
m_InputService = CreateService(m_EngineConfigAsset.coreServices.inputService);
|
||||
m_WorldService = CreateService(m_EngineConfigAsset.coreServices.worldService);
|
||||
m_GameService = CreateService(m_EngineConfigAsset.coreServices.gameService);
|
||||
}
|
||||
|
||||
void CreateServices() {
|
||||
foreach (ServiceAsset serviceAsset in m_EngineConfigAsset.services) {
|
||||
CreateService(serviceAsset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,40 +2,35 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using RebootKit.Engine.Foundation;
|
||||
using RebootKit.Engine.Main;
|
||||
using UnityEngine;
|
||||
using Logger = RebootKit.Engine.Foundation.Logger;
|
||||
|
||||
namespace RebootKit.Engine.Services.Console {
|
||||
public interface IConsoleCommand {
|
||||
string Name { get; }
|
||||
string Description { get; }
|
||||
void Execute(string[] args);
|
||||
}
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class RCCMD : Attribute {
|
||||
public string name;
|
||||
public string description;
|
||||
|
||||
public class HelpCommand : IConsoleCommand {
|
||||
public string Name { get; } = "help";
|
||||
public string Description { get; } = "Prints available commands/cvars and their descriptions.";
|
||||
|
||||
public void Execute(string[] args) {
|
||||
RR.Console.PrintHelp();
|
||||
}
|
||||
}
|
||||
|
||||
public class PrintCVarsCommand : IConsoleCommand {
|
||||
public string Name { get; } = "print_cvars";
|
||||
public string Description { get; } = "Prints all cvars and their values.";
|
||||
|
||||
public void Execute(string[] args) {
|
||||
RR.Console.PrintCVars();
|
||||
public RCCMD(string name, string description) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
|
||||
public class ConsoleService : IService {
|
||||
static readonly Logger s_logger = new(nameof(ConsoleService));
|
||||
|
||||
readonly List<IConsoleCommand> m_ConsoleCommands = new();
|
||||
public struct ConsoleCommand {
|
||||
public string name;
|
||||
public string description;
|
||||
public Action<string[]> action;
|
||||
}
|
||||
|
||||
readonly List<ConsoleCommand> m_ConsoleCommands = new();
|
||||
|
||||
FileStream m_LogFileStream;
|
||||
TextWriter m_LogFileWriter;
|
||||
@@ -60,8 +55,7 @@ namespace RebootKit.Engine.Services.Console {
|
||||
|
||||
Load();
|
||||
|
||||
RegisterCommand(new PrintCVarsCommand());
|
||||
RegisterCommand(new HelpCommand());
|
||||
RegisterCommands();
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
@@ -97,37 +91,34 @@ namespace RebootKit.Engine.Services.Console {
|
||||
OnOutputMessage?.Invoke(message);
|
||||
}
|
||||
|
||||
string[] ParseCommandInputArguments(string text) {
|
||||
if (text.Length == 0) {
|
||||
return Array.Empty<string>();
|
||||
}
|
||||
|
||||
return new[] {text};
|
||||
string[] ParseCommandInput(string text) {
|
||||
return text.Split(' ');
|
||||
}
|
||||
|
||||
// @NOTE: Input must be in format: "command arg1 arg2 arg3", one command = one call
|
||||
public void Execute(string input) {
|
||||
if (input.Length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
string commandName = input;
|
||||
if (input.IndexOf(' ') != -1) {
|
||||
commandName = input.Substring(0, input.IndexOf(' '));
|
||||
string[] arguments = ParseCommandInput(input);
|
||||
if (arguments.Length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
string[] arguments = ParseCommandInputArguments(input.Substring(commandName.Length));
|
||||
string commandName = arguments[0];
|
||||
|
||||
foreach (IConsoleCommand command in m_ConsoleCommands) {
|
||||
if (command.Name.Equals(commandName)) {
|
||||
command.Execute(arguments);
|
||||
foreach (ConsoleCommand command in m_ConsoleCommands) {
|
||||
if (command.name.Equals(commandName)) {
|
||||
command.action(arguments);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (ConfigVar cvar in ConfigVarsContainer.All()) {
|
||||
if (cvar.name.Equals(commandName)) {
|
||||
if (arguments.Length == 1) {
|
||||
cvar.ParseFromString(arguments[0]);
|
||||
if (arguments.Length == 2) {
|
||||
cvar.ParseFromString(arguments[1]);
|
||||
}
|
||||
|
||||
WriteToOutput($"<b>{cvar.name}</b> - {cvar}\n");
|
||||
@@ -138,25 +129,84 @@ namespace RebootKit.Engine.Services.Console {
|
||||
WriteToOutput($"ERROR: Command/CVar `{commandName}` not found.");
|
||||
}
|
||||
|
||||
public void RegisterCommand(IConsoleCommand command) {
|
||||
if (m_ConsoleCommands.Any(t => t.Name.Equals(command.Name))) {
|
||||
s_logger.Error($"`{command.Name}` command is already registered");
|
||||
public void RegisterCommand(string name, string description, Action<string[]> action) {
|
||||
if (IsCommandRegistered(name)) {
|
||||
s_logger.Error($"`{name}` command is already registered");
|
||||
return;
|
||||
}
|
||||
|
||||
m_ConsoleCommands.Add(command);
|
||||
s_logger.Info($"Registered command: {command.Name}");
|
||||
m_ConsoleCommands.Add(new ConsoleCommand {
|
||||
name = name,
|
||||
description = description,
|
||||
action = action
|
||||
});
|
||||
s_logger.Info($"Registered command: {name}");
|
||||
}
|
||||
|
||||
public void PrintHelp() {
|
||||
public static ConsoleCommand[] GenerateCommandsToRegister() {
|
||||
IEnumerable<MethodInfo> methods = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(assembly => assembly.GetTypes())
|
||||
.SelectMany(type => type.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static))
|
||||
.Where(method => method.GetCustomAttributes(typeof(RCCMD), false).Length > 0);
|
||||
|
||||
List<ConsoleCommand> commands = new();
|
||||
foreach (MethodInfo method in methods) {
|
||||
RCCMD attribute = (RCCMD)method.GetCustomAttributes(typeof(RCCMD), false)[0];
|
||||
|
||||
if (!method.IsStatic) {
|
||||
s_logger.Error($"Command `{attribute.name}` is not static, skipping");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (method.GetParameters().Length != 1) {
|
||||
s_logger.Error($"Command `{attribute.name}` has invalid number of parameters, skipping");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (method.GetParameters()[0].ParameterType != typeof(string[])) {
|
||||
s_logger.Error($"Command `{attribute.name}` has invalid parameter type, skipping");
|
||||
continue;
|
||||
}
|
||||
|
||||
Action<string[]> action = (Action<string[]>)Delegate.CreateDelegate(typeof(Action<string[]>), method);
|
||||
|
||||
commands.Add(new ConsoleCommand {
|
||||
name = attribute.name,
|
||||
description = attribute.description,
|
||||
action = action
|
||||
});
|
||||
}
|
||||
|
||||
return commands.ToArray();
|
||||
}
|
||||
|
||||
public void RegisterCommands() {
|
||||
ConsoleCommand[] commands = GenerateCommandsToRegister();
|
||||
foreach (ConsoleCommand command in commands) {
|
||||
RegisterCommand(command.name, command.description, command.action);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsCommandRegistered(string name) {
|
||||
foreach (ConsoleCommand command in m_ConsoleCommands) {
|
||||
if (command.name.Equals(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
[RCCMD("help", "Prints help message with all commands and cvars")]
|
||||
public static void PrintHelpCommand(string[] args) {
|
||||
StringBuilder message = new();
|
||||
|
||||
message.AppendLine("Available commands:");
|
||||
foreach (IConsoleCommand command in m_ConsoleCommands) {
|
||||
foreach (ConsoleCommand command in RR.Console.m_ConsoleCommands) {
|
||||
message.Append(" ");
|
||||
message.Append(command.Name);
|
||||
message.Append(command.name);
|
||||
message.Append(" - ");
|
||||
message.Append(command.Description);
|
||||
message.Append(command.description);
|
||||
message.AppendLine();
|
||||
}
|
||||
|
||||
@@ -169,17 +219,18 @@ namespace RebootKit.Engine.Services.Console {
|
||||
message.AppendLine();
|
||||
}
|
||||
|
||||
WriteToOutput(message.ToString());
|
||||
RR.Console.WriteToOutput(message.ToString());
|
||||
}
|
||||
|
||||
public void PrintCVars() {
|
||||
[RCCMD("cvars", "Prints all cvars")]
|
||||
public static void PrintCVars(string[] args) {
|
||||
StringBuilder message = new();
|
||||
|
||||
foreach (ConfigVar cvar in ConfigVarsContainer.All()) {
|
||||
message.AppendLine($"{cvar.name} - {cvar}");
|
||||
}
|
||||
|
||||
WriteToOutput(message.ToString());
|
||||
RR.Console.WriteToOutput(message.ToString());
|
||||
}
|
||||
|
||||
void Save() {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Text;
|
||||
using RebootKit.Engine.Foundation;
|
||||
using RebootKit.Engine.Main;
|
||||
using RebootKit.Engine.Services.Input;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
@@ -44,6 +44,10 @@ namespace RebootKit.Engine.Services.ConsoleUI {
|
||||
public event Action ClearRequested = () => { };
|
||||
|
||||
public void SetMessageContent(string message) {
|
||||
if (m_LabelMessage == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_LabelMessage.text = message;
|
||||
m_ScrollView.schedule.Execute(() => { m_ScrollView.scrollOffset = new Vector2(0, m_ScrollView.contentContainer.contentRect.height); }).StartingIn(16);
|
||||
}
|
||||
|
||||
3
Runtime/Engine/Code/Services/Crosshair.meta
Normal file
3
Runtime/Engine/Code/Services/Crosshair.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d31f3fe40394defabe1b77f6ddf8861
|
||||
timeCreated: 1746665551
|
||||
13
Runtime/Engine/Code/Services/Crosshair/CrosshairService.cs
Normal file
13
Runtime/Engine/Code/Services/Crosshair/CrosshairService.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using RebootKit.Engine.Foundation;
|
||||
|
||||
namespace RebootKit.Engine.Services.Crosshair {
|
||||
public class CrosshairService : IService {
|
||||
|
||||
public CrosshairService() {
|
||||
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f23a52c23aae46e8bd6b77222b10e5e2
|
||||
timeCreated: 1746665562
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using RebootKit.Engine.Main;
|
||||
using RebootKit.Engine.UI;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
@@ -10,13 +11,18 @@ namespace RebootKit.Engine.Services.Development {
|
||||
VisualElement m_RootElement;
|
||||
|
||||
Label m_FPSLabel;
|
||||
Label m_GameModeLabel;
|
||||
|
||||
void Update() {
|
||||
if (m_RootElement == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_FPSLabel.text = $"fps: {Mathf.RoundToInt(1f / Time.deltaTime)} | dt: {Time.deltaTime:F4}ms | runtime: {Time.time:F4}s";
|
||||
Resolution resolution = Screen.currentResolution;
|
||||
m_FPSLabel.text = $"fps: {Mathf.RoundToInt(1f / Time.deltaTime)} | dt: {Time.deltaTime:F4}ms | runtime: {Time.time:F4}s | resolution: {resolution.width}x{resolution.height}@{resolution.refreshRateRatio}Hz";
|
||||
m_GameModeLabel.text = RR.GameModes.ActiveGameMode.CurrentValue != null
|
||||
? $"Game Mode: {RR.GameModes.ActiveGameMode.CurrentValue.GetType().Name}"
|
||||
: "Game Mode: none";
|
||||
}
|
||||
|
||||
public override VisualElement Build() {
|
||||
@@ -24,7 +30,8 @@ namespace RebootKit.Engine.Services.Development {
|
||||
|
||||
CreateLabel($"Toggle Overlay [F3] | RebootKit | game: {Application.productName}, version: {Application.version}");
|
||||
m_FPSLabel = CreateLabel($"FPS: {Application.targetFrameRate}");
|
||||
|
||||
|
||||
m_GameModeLabel = CreateLabel("Game Mode: none");
|
||||
return m_RootElement;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using R3;
|
||||
using RebootKit.Engine.Foundation;
|
||||
|
||||
namespace RebootKit.Engine.Services.Game {
|
||||
public class GameService : IService {
|
||||
static readonly Logger s_logger = new(nameof(GameService));
|
||||
|
||||
[Inject] DIContext m_DIContext;
|
||||
|
||||
GameModeAsset m_GameModeAsset;
|
||||
|
||||
CancellationTokenSource m_DestroyCancellationTokenSource = new();
|
||||
DisposableBag m_ActiveGameModeDisposableBag;
|
||||
IGameMode m_ActiveGameMode;
|
||||
|
||||
public void Dispose() {
|
||||
m_DestroyCancellationTokenSource.Cancel();
|
||||
m_DestroyCancellationTokenSource.Dispose();
|
||||
m_ActiveGameModeDisposableBag.Dispose();
|
||||
}
|
||||
|
||||
public void Start(GameModeAsset asset) {
|
||||
if (m_ActiveGameMode != null) {
|
||||
s_logger.Warning("Game is already running");
|
||||
return;
|
||||
}
|
||||
|
||||
Stop();
|
||||
|
||||
m_ActiveGameModeDisposableBag = new DisposableBag();
|
||||
m_ActiveGameMode = asset.Create(m_DIContext);
|
||||
m_ActiveGameModeDisposableBag.Add(m_ActiveGameMode);
|
||||
|
||||
InitializeGameModeAsync().Forget();
|
||||
}
|
||||
|
||||
async UniTask InitializeGameModeAsync() {
|
||||
await m_ActiveGameMode.OnInit(m_DestroyCancellationTokenSource.Token);
|
||||
|
||||
m_ActiveGameMode.OnStart();
|
||||
Observable.EveryUpdate().Subscribe(_ => { m_ActiveGameMode?.OnTick(); }).AddTo(ref m_ActiveGameModeDisposableBag);
|
||||
}
|
||||
|
||||
public void Stop() {
|
||||
if (m_ActiveGameMode == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_ActiveGameMode.OnStop();
|
||||
m_ActiveGameMode = null;
|
||||
|
||||
m_ActiveGameModeDisposableBag.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using RebootKit.Engine.Foundation;
|
||||
using UnityEngine;
|
||||
|
||||
namespace RebootKit.Engine.Services.Game {
|
||||
[CreateAssetMenu(menuName = RConsts.k_ServiceAssetMenu + "Game")]
|
||||
public class GameServiceAsset : ServiceAsset<GameService> {
|
||||
public override GameService Create(DIContext context) {
|
||||
GameService service = context.Create<GameService>();
|
||||
return service;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
namespace RebootKit.Engine.Services.Game {
|
||||
public class Player {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be94d631484b4bd2a2c9825290b74b36
|
||||
timeCreated: 1744413325
|
||||
62
Runtime/Engine/Code/Services/GameMode/GameModesService.cs
Normal file
62
Runtime/Engine/Code/Services/GameMode/GameModesService.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using R3;
|
||||
using RebootKit.Engine.Foundation;
|
||||
using RebootKit.Engine.Main;
|
||||
using RebootKit.Engine.Services.Simulation;
|
||||
|
||||
namespace RebootKit.Engine.Services.GameMode {
|
||||
public class GameModesService : IService {
|
||||
static readonly Logger s_logger = new(nameof(GameModesService));
|
||||
|
||||
[Inject] DIContext m_DIContext;
|
||||
|
||||
GameModeAsset m_GameModeAsset;
|
||||
|
||||
readonly CancellationTokenSource m_DestroyCancellationTokenSource = new();
|
||||
DisposableBag m_ActiveGameModeDisposableBag;
|
||||
readonly ReactiveProperty<IGameMode> m_ActiveGameMode = new(null);
|
||||
|
||||
public ReadOnlyReactiveProperty<IGameMode> ActiveGameMode => m_ActiveGameMode;
|
||||
|
||||
public void Dispose() {
|
||||
m_DestroyCancellationTokenSource.Cancel();
|
||||
m_DestroyCancellationTokenSource.Dispose();
|
||||
m_ActiveGameModeDisposableBag.Dispose();
|
||||
}
|
||||
|
||||
public void Start(GameModeAsset asset, WorldConfig worldConfig) {
|
||||
if (m_ActiveGameMode.Value != null) {
|
||||
s_logger.Warning("Game is already running");
|
||||
return;
|
||||
}
|
||||
|
||||
Stop();
|
||||
|
||||
m_ActiveGameModeDisposableBag = new DisposableBag();
|
||||
m_ActiveGameMode.Value = asset.Create(m_DIContext);
|
||||
m_ActiveGameModeDisposableBag.Add(m_ActiveGameMode);
|
||||
|
||||
InitializeGameModeAsync(worldConfig, CancellationToken.None).Forget();
|
||||
}
|
||||
|
||||
async UniTask InitializeGameModeAsync(WorldConfig worldConfig, CancellationToken cancellationToken) {
|
||||
await m_ActiveGameMode.Value.OnInit(m_DestroyCancellationTokenSource.Token);
|
||||
|
||||
await RR.World.LoadAsync(worldConfig, cancellationToken);
|
||||
m_ActiveGameMode.Value.OnStart();
|
||||
Observable.EveryUpdate().Subscribe(_ => { m_ActiveGameMode.Value?.OnTick(); }).AddTo(ref m_ActiveGameModeDisposableBag);
|
||||
}
|
||||
|
||||
public void Stop() {
|
||||
if (m_ActiveGameMode.Value == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_ActiveGameMode.Value.OnStop();
|
||||
m_ActiveGameMode.Value = null;
|
||||
|
||||
m_ActiveGameModeDisposableBag.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Runtime/Engine/Code/Services/GameMode/GameServiceAsset.cs
Normal file
12
Runtime/Engine/Code/Services/GameMode/GameServiceAsset.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using RebootKit.Engine.Foundation;
|
||||
using UnityEngine;
|
||||
|
||||
namespace RebootKit.Engine.Services.GameMode {
|
||||
[CreateAssetMenu(menuName = RConsts.k_ServiceAssetMenu + "Game")]
|
||||
public class GameServiceAsset : ServiceAsset<GameModesService> {
|
||||
public override GameModesService Create(DIContext context) {
|
||||
GameModesService service = context.Create<GameModesService>();
|
||||
return service;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using RebootKit.Engine.Foundation;
|
||||
|
||||
namespace RebootKit.Engine.Services.Game {
|
||||
namespace RebootKit.Engine.Services.GameMode {
|
||||
public interface IGameMode : IDisposable {
|
||||
UniTask OnInit(CancellationToken cancellationToken);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using RebootKit.Engine.Foundation;
|
||||
@@ -7,30 +8,72 @@ using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
using UnityEngine.ResourceManagement.ResourceProviders;
|
||||
using UnityEngine.SceneManagement;
|
||||
using Logger = RebootKit.Engine.Foundation.Logger;
|
||||
|
||||
namespace RebootKit.Engine.Services.Simulation {
|
||||
public class WorldService : IService {
|
||||
readonly List<Actor> m_Actors = new();
|
||||
WorldConfig m_Config;
|
||||
|
||||
public void Dispose() {
|
||||
KillAllActors();
|
||||
static readonly Logger s_logger = new(nameof(WorldService));
|
||||
|
||||
enum WorldState {
|
||||
Unloaded,
|
||||
Loading,
|
||||
Loaded
|
||||
}
|
||||
|
||||
public async UniTask Load(WorldConfig worldConfig) {
|
||||
WorldState m_WorldState = WorldState.Unloaded;
|
||||
WorldConfig m_Config;
|
||||
AsyncOperationHandle<SceneInstance> m_SceneInstance;
|
||||
|
||||
readonly List<Actor> m_Actors = new();
|
||||
|
||||
public void Dispose() {
|
||||
Unload();
|
||||
}
|
||||
|
||||
public async UniTask LoadAsync(WorldConfig worldConfig, CancellationToken cancellationToken) {
|
||||
await UniTask.WaitWhile(() => m_WorldState == WorldState.Loading, cancellationToken: cancellationToken);
|
||||
|
||||
Unload();
|
||||
|
||||
m_WorldState = WorldState.Loading;
|
||||
m_Config = worldConfig;
|
||||
|
||||
AsyncOperationHandle<SceneInstance> handle = worldConfig.mainScene.LoadSceneAsync(LoadSceneMode.Additive, false);
|
||||
await handle.ToUniTask();
|
||||
m_SceneInstance = worldConfig.mainScene.LoadSceneAsync(LoadSceneMode.Additive, false);
|
||||
await m_SceneInstance.ToUniTask(cancellationToken: cancellationToken);
|
||||
|
||||
await handle.Result.ActivateAsync();
|
||||
SceneManager.SetActiveScene(handle.Result.Scene);
|
||||
await m_SceneInstance.Result.ActivateAsync();
|
||||
SceneManager.SetActiveScene(m_SceneInstance.Result.Scene);
|
||||
|
||||
foreach (GameObject root in handle.Result.Scene.GetRootGameObjects()) {
|
||||
foreach (GameObject root in m_SceneInstance.Result.Scene.GetRootGameObjects()) {
|
||||
foreach (Actor actor in root.GetComponentsInChildren<Actor>()) {
|
||||
RegisterActor(actor);
|
||||
}
|
||||
}
|
||||
|
||||
m_WorldState = WorldState.Loaded;
|
||||
}
|
||||
|
||||
public async UniTask<TRequiredActor> LoadAsync<TRequiredActor>(WorldConfig worldConfig, CancellationToken cancellationToken) where TRequiredActor : Actor {
|
||||
await LoadAsync(worldConfig, cancellationToken);
|
||||
|
||||
TRequiredActor actor = m_Actors.FirstOrDefault(t => t is TRequiredActor) as TRequiredActor;
|
||||
if (actor is null) {
|
||||
s_logger.Error($"Actor of type {typeof(TRequiredActor)} not found in the scene");
|
||||
return null;
|
||||
}
|
||||
|
||||
return actor;
|
||||
}
|
||||
|
||||
public void Unload() {
|
||||
KillAllActors();
|
||||
|
||||
if (m_SceneInstance.IsValid()) {
|
||||
m_SceneInstance.Release();
|
||||
m_SceneInstance = default;
|
||||
}
|
||||
|
||||
m_WorldState = WorldState.Unloaded;
|
||||
}
|
||||
|
||||
public async UniTask<TActor> SpawnActor<TActor>(AssetReferenceT<GameObject> asset, CancellationToken cancellationToken) where TActor : Actor {
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 19001, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_Name: Teko-VariableFont_wght SDF
|
||||
m_EditorClassIdentifier:
|
||||
m_Version: 1.1.0
|
||||
m_Material: {fileID: 1107025805838944769}
|
||||
m_SourceFontFileGUID: 7c0f83ef535953a479fd66830c0386b1
|
||||
m_fontAssetCreationEditorSettings:
|
||||
sourceFontFileGUID: 7c0f83ef535953a479fd66830c0386b1
|
||||
faceIndex: 0
|
||||
pointSizeSamplingMode: 0
|
||||
pointSize: 90
|
||||
padding: 9
|
||||
paddingMode: 2
|
||||
packingMode: 0
|
||||
atlasWidth: 1024
|
||||
atlasHeight: 1024
|
||||
characterSetSelectionMode: 7
|
||||
characterSequence:
|
||||
referencedFontAssetGUID:
|
||||
referencedTextAssetGUID:
|
||||
fontStyle: 0
|
||||
fontStyleModifier: 0
|
||||
renderMode: 4165
|
||||
includeFontFeatures: 0
|
||||
m_SourceFontFile: {fileID: 12800000, guid: 7c0f83ef535953a479fd66830c0386b1, type: 3}
|
||||
m_SourceFontFilePath:
|
||||
m_AtlasPopulationMode: 1
|
||||
InternalDynamicOS: 0
|
||||
IsEditorFont: 0
|
||||
m_FaceInfo:
|
||||
m_FaceIndex: 0
|
||||
m_FamilyName: Teko
|
||||
m_StyleName: Light
|
||||
m_PointSize: 90
|
||||
m_Scale: 1
|
||||
m_UnitsPerEM: 1000
|
||||
m_LineHeight: 128.97
|
||||
m_AscentLine: 86.22
|
||||
m_CapLine: 56
|
||||
m_MeanLine: 44
|
||||
m_Baseline: 0
|
||||
m_DescentLine: -42.75
|
||||
m_SuperscriptOffset: 86.22
|
||||
m_SuperscriptSize: 0.5
|
||||
m_SubscriptOffset: -42.75
|
||||
m_SubscriptSize: 0.5
|
||||
m_UnderlineOffset: -11.25
|
||||
m_UnderlineThickness: 4.5
|
||||
m_StrikethroughOffset: 17.6
|
||||
m_StrikethroughThickness: 4.5
|
||||
m_TabWidth: 12
|
||||
m_GlyphTable: []
|
||||
m_CharacterTable: []
|
||||
m_AtlasTextures:
|
||||
- {fileID: 4954975621857233213}
|
||||
m_AtlasTextureIndex: 0
|
||||
m_IsMultiAtlasTexturesEnabled: 0
|
||||
m_GetFontFeatures: 1
|
||||
m_ClearDynamicDataOnBuild: 0
|
||||
m_AtlasWidth: 1024
|
||||
m_AtlasHeight: 1024
|
||||
m_AtlasPadding: 9
|
||||
m_AtlasRenderMode: 4165
|
||||
m_UsedGlyphRects: []
|
||||
m_FreeGlyphRects:
|
||||
- m_X: 0
|
||||
m_Y: 0
|
||||
m_Width: 1023
|
||||
m_Height: 1023
|
||||
m_FontFeatureTable:
|
||||
m_MultipleSubstitutionRecords: []
|
||||
m_LigatureSubstitutionRecords: []
|
||||
m_GlyphPairAdjustmentRecords: []
|
||||
m_MarkToBaseAdjustmentRecords: []
|
||||
m_MarkToMarkAdjustmentRecords: []
|
||||
m_ShouldReimportFontFeatures: 0
|
||||
m_FallbackFontAssetTable: []
|
||||
m_FontWeightTable:
|
||||
- regularTypeface: {fileID: 0}
|
||||
italicTypeface: {fileID: 0}
|
||||
- regularTypeface: {fileID: 0}
|
||||
italicTypeface: {fileID: 0}
|
||||
- regularTypeface: {fileID: 0}
|
||||
italicTypeface: {fileID: 0}
|
||||
- regularTypeface: {fileID: 0}
|
||||
italicTypeface: {fileID: 0}
|
||||
- regularTypeface: {fileID: 0}
|
||||
italicTypeface: {fileID: 0}
|
||||
- regularTypeface: {fileID: 0}
|
||||
italicTypeface: {fileID: 0}
|
||||
- regularTypeface: {fileID: 0}
|
||||
italicTypeface: {fileID: 0}
|
||||
- regularTypeface: {fileID: 0}
|
||||
italicTypeface: {fileID: 0}
|
||||
- regularTypeface: {fileID: 0}
|
||||
italicTypeface: {fileID: 0}
|
||||
- regularTypeface: {fileID: 0}
|
||||
italicTypeface: {fileID: 0}
|
||||
m_RegularStyleWeight: 0
|
||||
m_RegularStyleSpacing: 0
|
||||
m_BoldStyleWeight: 0.75
|
||||
m_BoldStyleSpacing: 7
|
||||
m_ItalicStyleSlant: 35
|
||||
m_TabMultiple: 10
|
||||
--- !u!21 &1107025805838944769
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Teko-VariableFont_wght Atlas Material
|
||||
m_Shader: {fileID: 19011, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_Parent: {fileID: 0}
|
||||
m_ModifiedSerializedProperties: 0
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_LockedProperties:
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 4954975621857233213}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _FaceDilate: 0
|
||||
- _GradientScale: 10
|
||||
- _OutlineSoftness: 0
|
||||
- _OutlineWidth: 0
|
||||
- _PerspectiveFilter: 0.875
|
||||
- _ScaleRatioA: 1
|
||||
- _ScaleRatioB: 1
|
||||
- _ScaleRatioC: 1
|
||||
- _ScaleX: 1
|
||||
- _ScaleY: 1
|
||||
- _ShaderFlags: 0
|
||||
- _Sharpness: 0
|
||||
- _TextureHeight: 1024
|
||||
- _TextureWidth: 1024
|
||||
- _UnderlayDilate: 0
|
||||
- _UnderlayOffsetX: 0
|
||||
- _UnderlayOffsetY: 0
|
||||
- _UnderlaySoftness: 0
|
||||
- _VertexOffsetX: 0
|
||||
- _VertexOffsetY: 0
|
||||
- _WeightBold: 0.75
|
||||
- _WeightNormal: 0
|
||||
m_Colors:
|
||||
- _FaceColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _OutlineColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5}
|
||||
m_BuildTextureStacks: []
|
||||
m_AllowLocking: 1
|
||||
--- !u!28 &4954975621857233213
|
||||
Texture2D:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Teko-VariableFont_wght Atlas
|
||||
m_ImageContentsHash:
|
||||
serializedVersion: 2
|
||||
Hash: 00000000000000000000000000000000
|
||||
m_IsAlphaChannelOptional: 0
|
||||
serializedVersion: 3
|
||||
m_Width: 1
|
||||
m_Height: 1
|
||||
m_CompleteImageSize: 1
|
||||
m_MipsStripped: 0
|
||||
m_TextureFormat: 1
|
||||
m_MipCount: 1
|
||||
m_IsReadable: 1
|
||||
m_IsPreProcessed: 0
|
||||
m_IgnoreMipmapLimit: 1
|
||||
m_MipmapLimitGroupName:
|
||||
m_StreamingMipmaps: 0
|
||||
m_StreamingMipmapsPriority: 0
|
||||
m_VTOnly: 0
|
||||
m_AlphaIsTransparency: 0
|
||||
m_ImageCount: 1
|
||||
m_TextureDimension: 2
|
||||
m_TextureSettings:
|
||||
serializedVersion: 2
|
||||
m_FilterMode: 1
|
||||
m_Aniso: 1
|
||||
m_MipBias: 0
|
||||
m_WrapU: 0
|
||||
m_WrapV: 0
|
||||
m_WrapW: 0
|
||||
m_LightmapFormat: 0
|
||||
m_ColorSpace: 1
|
||||
m_PlatformBlob:
|
||||
image data: 1
|
||||
_typelessdata: cd
|
||||
m_StreamData:
|
||||
serializedVersion: 2
|
||||
offset: 0
|
||||
size: 0
|
||||
path:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0332b18d9c9c6214c809861e68baf097
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -5,12 +5,18 @@ namespace RebootKit.FPPKit {
|
||||
public class FPPLocomotion : MonoBehaviour {
|
||||
[SerializeField] CharacterController m_CharacterController;
|
||||
|
||||
public float maxStrafeSpeed = 2.0f;
|
||||
public float maxMovementSpeedBackward = 2.0f;
|
||||
public float maxMovementSpeed = 4.0f;
|
||||
public float maxSprintSpeed = 15.0f;
|
||||
public float jumpHeight = 1.0f;
|
||||
public float gravity = 10f;
|
||||
public float maxFallSpeed = 20f;
|
||||
public float damping = 20.0f;
|
||||
|
||||
[Range(0.0f, 1.0f)]
|
||||
public float airControlRatio = 0.5f;
|
||||
|
||||
float3 m_CurrentVelocity;
|
||||
bool m_IsFalling;
|
||||
|
||||
@@ -20,8 +26,12 @@ namespace RebootKit.FPPKit {
|
||||
float3 m_PendingInputValue;
|
||||
|
||||
public bool IsGrounded => m_CharacterController.isGrounded;
|
||||
public bool IsMovingBackwards { get; private set; }
|
||||
public bool IsSprinting => m_IsSprinting;
|
||||
public bool IsStrafing { get; private set; }
|
||||
|
||||
public float3 Velocity => m_CurrentVelocity;
|
||||
public float3 Velocity => m_CurrentVelocity;
|
||||
public float3 LocalVelocity => m_CharacterController.transform.InverseTransformDirection(m_CurrentVelocity);
|
||||
|
||||
void Update() {
|
||||
ConsumePendingInput();
|
||||
@@ -42,12 +52,13 @@ namespace RebootKit.FPPKit {
|
||||
}
|
||||
|
||||
void ConsumePendingInput() {
|
||||
// if (!IsGrounded) {
|
||||
// m_PendingInputValue = float3.zero;
|
||||
// return;
|
||||
// }
|
||||
if (!IsGrounded) {
|
||||
m_PendingInputValue *= airControlRatio;
|
||||
}
|
||||
|
||||
m_PendingInputValue.y = 0.0f;
|
||||
|
||||
float3 localInputValue = m_CharacterController.transform.InverseTransformDirection(m_PendingInputValue);
|
||||
|
||||
float pendingInputMagnitude = math.length(m_PendingInputValue);
|
||||
float3 direction = float3.zero;
|
||||
@@ -56,7 +67,21 @@ namespace RebootKit.FPPKit {
|
||||
direction = math.normalize(m_PendingInputValue);
|
||||
}
|
||||
|
||||
float movementSpeed = m_IsSprinting ? maxSprintSpeed : maxMovementSpeed;
|
||||
IsStrafing = false;
|
||||
IsMovingBackwards = false;
|
||||
|
||||
float movementSpeed;
|
||||
if (math.dot(localInputValue, Vector3.forward) <= 0.0f) {
|
||||
movementSpeed = maxMovementSpeedBackward;
|
||||
IsMovingBackwards = true;
|
||||
} else if (m_IsSprinting) {
|
||||
movementSpeed = maxSprintSpeed;
|
||||
} else if (math.abs(localInputValue.x) > 0.0f && math.abs(localInputValue.z) < 0.1f) {
|
||||
movementSpeed = maxStrafeSpeed;
|
||||
} else {
|
||||
movementSpeed = maxMovementSpeed;
|
||||
}
|
||||
|
||||
float3 movementVelocity = m_CurrentVelocity;
|
||||
movementVelocity.y = 0.0f;
|
||||
movementVelocity += direction * (movementSpeed * pendingInputMagnitude);
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using RebootKit.Engine;
|
||||
using RebootKit.Engine.Foundation;
|
||||
using RebootKit.Engine.Main;
|
||||
using RebootKit.Engine.Services.Console;
|
||||
using RebootKit.Engine.Services.Input;
|
||||
using Unity.Mathematics;
|
||||
@@ -12,7 +13,6 @@ using UnityEngine.InputSystem;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace RebootKit.FPPKit {
|
||||
|
||||
public static class FPPConfig {
|
||||
[ConfigVar("fpp.mouse.sens", 0.25f, "Mouse look sensitivity")] public static ConfigVar s_MouseSensitivity;
|
||||
[ConfigVar("fpp.mouse.invert.y", 0, "Invert mouse look")] public static ConfigVar s_MouseInvertY;
|
||||
@@ -21,20 +21,28 @@ namespace RebootKit.FPPKit {
|
||||
|
||||
public static class SensitivityReader {
|
||||
public static float2 Read(InputAction action) {
|
||||
if (action == null || action.activeControl == null) {
|
||||
return float2.zero;
|
||||
}
|
||||
|
||||
float2 sensitivity = action.ReadValue<Vector2>();
|
||||
|
||||
// @TODO: differentiate between gamepad and mouse
|
||||
|
||||
sensitivity *= FPPConfig.s_MouseSensitivity.FloatValue;
|
||||
bool isGamepad = action.activeControl.device is Gamepad;
|
||||
|
||||
if (FPPConfig.s_MouseInvertY.IndexValue == 1) {
|
||||
sensitivity.y *= -1;
|
||||
if (isGamepad) {
|
||||
sensitivity *= FPPConfig.s_GamepadSensitivity.FloatValue;
|
||||
} else {
|
||||
sensitivity *= FPPConfig.s_MouseSensitivity.FloatValue;
|
||||
|
||||
if (FPPConfig.s_MouseInvertY.IndexValue == 1) {
|
||||
sensitivity.y *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
return sensitivity;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class FPPPlayerController : IController {
|
||||
readonly Config m_Config;
|
||||
FPPActor m_FPPActor;
|
||||
|
||||
Reference in New Issue
Block a user