This commit is contained in:
2025-04-14 23:22:38 +02:00
parent 72b8a37345
commit 1e190fe94b
166 changed files with 2989 additions and 687 deletions

View File

@@ -1,159 +0,0 @@
using System;
namespace RebootKit.Engine.Services.Console {
public enum CVarValueKind {
Number, String
}
[Serializable]
public struct CVarValue {
public CVarValueKind kind;
public double numberValue;
public string stringValue;
public CVarValue(int value) {
kind = CVarValueKind.Number;
numberValue = value;
stringValue = null;
}
public CVarValue(float value) {
kind = CVarValueKind.Number;
numberValue = value;
stringValue = null;
}
public CVarValue(double value) {
kind = CVarValueKind.Number;
numberValue = value;
stringValue = null;
}
public CVarValue(string value) {
kind = CVarValueKind.String;
numberValue = 0;
stringValue = value;
}
public void CopyFrom(CVarValue value) {
kind = value.kind;
numberValue = value.numberValue;
stringValue = value.stringValue;
}
public override string ToString() {
return kind switch {
CVarValueKind.Number => numberValue.ToString(),
CVarValueKind.String => $"\"{stringValue}\"",
_ => throw new ArgumentOutOfRangeException()
};
}
}
[Flags]
public enum CVarFlags {
None, Persistent, ReadOnly
}
[Serializable]
public class CVar {
public CVarFlags flags;
public string name;
public string description;
public CVarValue defaultValue;
public CVar(CVar other) {
flags = other.flags;
name = other.name;
description = other.description;
defaultValue = other.defaultValue;
Value = other.Value;
}
public CVar(string name, CVarValue value, string description = "") {
this.name = name;
this.description = description;
defaultValue = value;
Value = defaultValue;
}
public CVar(string name, int value, string description = "") {
this.name = name;
this.description = description;
defaultValue = new CVarValue(value);
Value = defaultValue;
}
public CVar(string name, float value, string description = "") {
this.name = name;
this.description = description;
defaultValue = new CVarValue(value);
Value = defaultValue;
}
public CVar(string name, double value, string description = "") {
this.name = name;
this.description = description;
defaultValue = new CVarValue(value);
Value = defaultValue;
}
public CVar(string name, string value, string description = "") {
this.name = name;
this.description = description;
defaultValue = new CVarValue(value);
Value = defaultValue;
}
public CVarValue Value { get; private set; }
public int IndexValue => (int) Value.numberValue;
public float FloatValue => (float) Value.numberValue;
public double NumberValue => Value.numberValue;
public string StringValue => Value.stringValue;
public event Action StateChanged = delegate { };
public void Set(int value) {
if (flags.HasFlag(CVarFlags.ReadOnly)) return;
Value = new CVarValue(value);
StateChanged?.Invoke();
}
public void Set(float value) {
if (flags.HasFlag(CVarFlags.ReadOnly)) return;
Value = new CVarValue(value);
StateChanged?.Invoke();
}
public void Set(string value) {
if (flags.HasFlag(CVarFlags.ReadOnly)) return;
Value = new CVarValue(value);
StateChanged?.Invoke();
}
public void ParseFromString(string str) {
if (flags.HasFlag(CVarFlags.ReadOnly)) return;
if (float.TryParse(str, out float f))
Set(f);
else
Set(str);
}
public void Reset() {
if (flags.HasFlag(CVarFlags.ReadOnly)) return;
Value = defaultValue;
StateChanged?.Invoke();
}
public override string ToString() {
return Value.ToString();
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 0f560b25a893456c90fac62ad278c02b
timeCreated: 1740779755

View File

@@ -1,16 +0,0 @@
using UnityEngine;
namespace RebootKit.Engine.Services.Console {
[CreateAssetMenu(menuName = RConsts.k_AddComponentMenu + "cvar", fileName = "cvar")]
public class CVarAsset : ScriptableObject {
[SerializeField] CVar m_CVar;
public CVar Create(string cvarName = null) {
CVar cvar = new(m_CVar);
if (cvarName != null) cvar.name = cvarName;
return cvar;
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 443a66c3a441450d96d222872a567df0
timeCreated: 1741639598

View File

@@ -1,57 +0,0 @@
using System;
using System.Reflection;
using RebootKit.Engine.Foundation;
namespace RebootKit.Engine.Services.Console {
[AttributeUsage(AttributeTargets.Field)]
public class CVarAttribute : Attribute {
public CVarAttribute(string name, float defaultValue) {
Name = name;
Value = new CVarValue(defaultValue);
}
public CVarAttribute(string name, double defaultValue) {
Name = name;
Value = new CVarValue(defaultValue);
}
public CVarAttribute(string name, string defaultValue) {
Name = name;
Value = new CVarValue(defaultValue);
}
public CVarAttribute(string name, int defaultValue) {
Name = name;
Value = new CVarValue(defaultValue);
}
public string Name { get; }
public CVarValue Value { get; }
}
public class CVarFieldInjector : DIContext.IFieldInjector {
static readonly Logger s_logger = new(nameof(CVarFieldInjector));
public bool Inject(FieldInfo field, object target, DIContext context) {
if (!Attribute.IsDefined(field, typeof(CVarAttribute))) return false;
ConsoleService console = context.Resolve<ConsoleService>();
if (console == null) {
s_logger.Error($"Cannot inject field because cannot resolve `{nameof(ConsoleService)}`");
return false;
}
CVarAttribute cvarAttribute = field.GetCustomAttribute<CVarAttribute>();
CVar cvar = console.GetCVar(cvarAttribute.Name);
if (cvar == null) {
cvar = new CVar(cvarAttribute.Name, cvarAttribute.Value);
console.Replace(cvar);
}
field.SetValue(target, cvar);
return true;
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 1ce6213dda8c4f8d9eafe4afd1614a86
timeCreated: 1742005021

View File

@@ -1,8 +1,10 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using RebootKit.Engine.Foundation;
using UnityEngine;
using Logger = RebootKit.Engine.Foundation.Logger;
namespace RebootKit.Engine.Services.Console {
@@ -21,104 +23,136 @@ namespace RebootKit.Engine.Services.Console {
}
}
public class ConsoleService : IService {
static readonly Logger _logger = new(nameof(ConsoleService));
public class PrintCVarsCommand : IConsoleCommand {
public string Name { get; } = "print_cvars";
public string Description { get; } = "Prints all cvars and their values.";
readonly List<IConsoleCommand> _commands = new();
readonly List<CVar> _cvars = new();
public void Execute(string[] args) {
RR.Console.PrintCVars();
}
}
public class ConsoleService : IService {
static readonly Logger s_logger = new(nameof(ConsoleService));
readonly List<IConsoleCommand> m_ConsoleCommands = new();
FileStream m_LogFileStream;
TextWriter m_LogFileWriter;
bool m_IsLoading;
public ConsoleService() {
_logger.Info("Waking up");
ConfigVar.StateChanged += OnCVarStateChanged;
m_LogFileStream = new FileStream(Application.persistentDataPath + "/rr_logs.txt", FileMode.Append, FileAccess.Write);
m_LogFileWriter = new StreamWriter(m_LogFileStream);
m_LogFileWriter.WriteLine("============================");
m_LogFileWriter.WriteLine("Starting new log");
m_LogFileWriter.WriteLine($" > Game: {Application.productName}");
m_LogFileWriter.WriteLine($" > Version: {Application.version}");
m_LogFileWriter.WriteLine($" > Date: {DateTime.Now}");
m_LogFileWriter.WriteLine("============================");
m_LogFileWriter.Flush();
s_logger.Info("Waking up");
Load();
RegisterCommand(new PrintCVarsCommand());
RegisterCommand(new HelpCommand());
}
public void Dispose() {
s_logger.Info("Shutting down");
ConfigVar.StateChanged -= OnCVarStateChanged;
m_LogFileWriter.Dispose();
m_LogFileStream.Dispose();
m_LogFileStream = null;
m_LogFileWriter = null;
}
void OnCVarStateChanged(ConfigVar cvar) {
if (m_IsLoading) {
return;
}
if (!cvar.flags.HasFlag(CVarFlags.ReadOnly)) {
Save();
}
}
public event Action<string> OnOutputMessage = _ => { };
public void WriteToOutput(string message) {
if (m_LogFileWriter != null) {
m_LogFileWriter.WriteLine(message);
m_LogFileWriter.Flush();
}
OnOutputMessage?.Invoke(message);
}
public bool CVarExists(string name) {
foreach (CVar cvar in _cvars)
if (cvar.name.Equals(name))
return true;
return false;
}
public CVar GetCVar(string name) {
foreach (CVar cvar in _cvars)
if (cvar.name.Equals(name))
return cvar;
return null;
}
public CVar ReplaceOrDefault(CVar cvar) {
CVar foundCVar = GetCVar(cvar.name);
if (foundCVar != null) return foundCVar;
_cvars.Add(cvar);
return cvar;
}
public void Replace(CVar cvar) {
CVar foundCVar = GetCVar(cvar.name);
if (foundCVar != null) _cvars.Remove(foundCVar);
_cvars.Add(cvar);
}
string[] ParseCommandInputArguments(string text) {
if (text.Length == 0) return Array.Empty<string>();
if (text.Length == 0) {
return Array.Empty<string>();
}
return new[] {text};
}
public void Execute(string input) {
if (input.Length == 0) return;
if (input.Length == 0) {
return;
}
string commandName = input;
if (input.IndexOf(' ') != -1) commandName = input.Substring(0, input.IndexOf(' '));
if (input.IndexOf(' ') != -1) {
commandName = input.Substring(0, input.IndexOf(' '));
}
string[] arguments = ParseCommandInputArguments(input.Substring(commandName.Length));
foreach (IConsoleCommand command in _commands)
foreach (IConsoleCommand command in m_ConsoleCommands) {
if (command.Name.Equals(commandName)) {
command.Execute(arguments);
return;
}
}
foreach (CVar cvar in _cvars)
foreach (ConfigVar cvar in ConfigVarsContainer.All()) {
if (cvar.name.Equals(commandName)) {
if (arguments.Length == 1) cvar.ParseFromString(arguments[0]);
if (arguments.Length == 1) {
cvar.ParseFromString(arguments[0]);
}
WriteToOutput($"<b>{cvar.name}</b> - {cvar}\n");
return;
}
}
WriteToOutput($"ERROR: Command/CVar `{commandName}` not found.");
}
public void RegisterCommand(IConsoleCommand command) {
if (_commands.Any(t => t.Name.Equals(command.Name))) {
_logger.Error($"`{command.Name}` command is already registered");
if (m_ConsoleCommands.Any(t => t.Name.Equals(command.Name))) {
s_logger.Error($"`{command.Name}` command is already registered");
return;
}
_commands.Add(command);
_logger.Info($"Registered command: {command.Name}");
m_ConsoleCommands.Add(command);
s_logger.Info($"Registered command: {command.Name}");
}
public void PrintHelp() {
StringBuilder message = new();
message.AppendLine("Available commands:");
foreach (IConsoleCommand command in _commands) {
foreach (IConsoleCommand command in m_ConsoleCommands) {
message.Append(" ");
message.Append(command.Name);
message.Append(" - ");
@@ -127,7 +161,7 @@ namespace RebootKit.Engine.Services.Console {
}
message.AppendLine("Available cvars:");
foreach (CVar cvar in _cvars) {
foreach (ConfigVar cvar in ConfigVarsContainer.All()) {
message.Append(" ");
message.Append(cvar.name);
message.Append(" - ");
@@ -137,5 +171,60 @@ namespace RebootKit.Engine.Services.Console {
WriteToOutput(message.ToString());
}
public void PrintCVars() {
StringBuilder message = new();
foreach (ConfigVar cvar in ConfigVarsContainer.All()) {
message.AppendLine($"{cvar.name} - {cvar}");
}
WriteToOutput(message.ToString());
}
void Save() {
string path = Application.persistentDataPath + "/" + RConsts.k_CVarsFilename;
s_logger.Info("Saving cvars to file: " + path);
StringBuilder sb = new();
foreach (ConfigVar cvar in ConfigVarsContainer.All()) {
if (!cvar.flags.HasFlag(CVarFlags.ReadOnly)) {
sb.AppendFormat("{0} {1}\n", cvar.name, cvar);
}
}
File.WriteAllText(path, sb.ToString());
}
void Load() {
string path = Application.persistentDataPath + "/" + RConsts.k_CVarsFilename;
if (!File.Exists(path)) {
s_logger.Info("CVar file not found, skipping load");
return;
}
m_IsLoading = true;
ExecuteFile(path);
m_IsLoading = false;
}
bool ExecuteFile(string path) {
if (!File.Exists(path)) {
s_logger.Error($"Cannot load file '{path}', file not found");
return false;
}
s_logger.Info($"Executing file '{path}'");
string[] lines = File.ReadAllLines(path);
foreach (string line in lines) {
WriteToOutput(path + " > " + line);
Execute(line);
}
return true;
}
}
}

View File

@@ -1,30 +1,15 @@
using RebootKit.Engine.Foundation;
using UnityEngine;
using Logger = RebootKit.Engine.Foundation.Logger;
namespace RebootKit.Engine.Services.Console {
[CreateAssetMenu(menuName = RConsts.k_ServiceAssetMenu + "Console")]
public class ConsoleServiceAsset : ServiceAsset<ConsoleService> {
[SerializeField] CVar[] _initialCVars;
[SerializeField] bool _loadCVarsFromResources = true;
static readonly Logger s_logger = new(nameof(ConsoleServiceAsset));
public override ConsoleService Create(DIContext context) {
ConsoleService service = new();
context.Inject(service);
foreach (CVar cvar in _initialCVars) {
service.Replace(cvar);
cvar.Reset();
}
if (_loadCVarsFromResources) {
CVarAsset[] cvarsAssets = Resources.LoadAll<CVarAsset>("cvar");
foreach (CVarAsset cvarAsset in cvarsAssets) {
CVar cvar = cvarAsset.Create();
service.Replace(cvar);
}
}
return service;
}
}

View File

@@ -57,6 +57,7 @@ namespace RebootKit.Engine.Services.ConsoleUI {
}
void OnUserInput(string input) {
RR.Console.WriteToOutput("> " + input);
RR.Console.Execute(input);
}

View File

@@ -1,28 +1,39 @@
using System.Threading;
using Cysharp.Threading.Tasks;
using System;
using RebootKit.Engine.UI;
using UnityEngine;
using UnityEngine.UIElements;
namespace RebootKit.Engine.Services.Development {
public class DebugOverlayView : MonoBehaviour, IView {
[SerializeField] UIDocument m_Document;
void Start() {
}
public async UniTask Show(CancellationToken cancellationToken) {
gameObject.SetActive(true);
await UniTask.Yield(cancellationToken);
}
public async UniTask Hide(CancellationToken cancellationToken) {
gameObject.SetActive(false);
await UniTask.Yield(cancellationToken);
}
public class DebugOverlayView : UIDocumentView {
const string k_DebugLabelClassName = "rr__debug-label";
void SetOverlayModeChanged(int mode) {
VisualElement m_RootElement;
Label m_FPSLabel;
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";
}
public override VisualElement Build() {
m_RootElement = new VisualElement();
CreateLabel($"Toggle Overlay [F3] | RebootKit | game: {Application.productName}, version: {Application.version}");
m_FPSLabel = CreateLabel($"FPS: {Application.targetFrameRate}");
return m_RootElement;
}
Label CreateLabel(string text) {
Label label = (Label)LabelBuilder.New(text).Build();
label.AddToClassList(k_DebugLabelClassName);
m_RootElement.Add(label);
return label;
}
}
}

View File

@@ -1,24 +1,23 @@
using System;
using Cysharp.Threading.Tasks;
using RebootKit.Engine.Foundation;
using RebootKit.Engine.Services.Console;
using UnityEngine;
using UnityEngine.InputSystem;
namespace RebootKit.Engine.Services.Development {
static class DebugCVars {
public const string k_OverlayMode = "debug.mode";
static class DebugConfig {
[ConfigVar("debug.overlay", 1, "Controls overlay visibility. 0 - hidden, 1 - visible")] public static ConfigVar s_OverlayMode;
}
public class DevToolsService : ServiceMonoBehaviour {
[SerializeField] DebugOverlayView m_DebugOverlayView;
[CVar(DebugCVars.k_OverlayMode, 1)] CVar m_OverlayMode;
IDisposable m_CVarChangedListener;
void OnEnable() {
m_CVarChangedListener = RR.CVarChanged.Listen(OnCVarChanged);
OnOverlayModeChanged(m_OverlayMode.IndexValue);
void Start() {
ConfigVar.StateChanged += OnCVarChanged;
// OnOverlayModeChanged(m_OverlayMode.IndexValue);
}
void OnDisable() {
@@ -26,20 +25,26 @@ namespace RebootKit.Engine.Services.Development {
}
public override void Dispose() {
m_CVarChangedListener.Dispose();
ConfigVar.StateChanged -= OnCVarChanged;
}
void Update() {
if (InputSystem.GetDevice<Keyboard>().f3Key.wasReleasedThisFrame) {
DebugConfig.s_OverlayMode.Set(DebugConfig.s_OverlayMode.IndexValue == 1 ? 0 : 1);
}
}
void OnOverlayModeChanged(int mode) {
if (mode == 1) {
m_DebugOverlayView.Show(destroyCancellationToken).Forget();
m_DebugOverlayView.gameObject.SetActive(true);
} else {
m_DebugOverlayView.Hide(destroyCancellationToken).Forget();
m_DebugOverlayView.gameObject.SetActive(false);
}
}
void OnCVarChanged(string cvarName, CVarValue value) {
if (cvarName == DebugCVars.k_OverlayMode) {
OnOverlayModeChanged((int)value.numberValue);
void OnCVarChanged(ConfigVar cvar) {
if (cvar == DebugConfig.s_OverlayMode) {
OnOverlayModeChanged(cvar.IndexValue);
}
}
}

View File

@@ -1,78 +0,0 @@
using System;
using System.Threading;
using RebootKit.Engine.Foundation;
using UnityEngine;
namespace RebootKit.Engine.Services.Game {
public abstract class GameModeAsset : FactoryAsset<GameMode> {
[field: SerializeField]
public GameMode.Config GameModeConfig { get; private set; }
public override GameMode Create(DIContext context) {
GameMode gameMode = new(GameModeConfig);
context.Inject(gameMode);
ConfigureGameMode(gameMode);
return gameMode;
}
public abstract void ConfigureGameMode(GameMode gameMode);
}
public class GameMode : IDisposable {
[Serializable]
public class Config {
public ControllerAsset[] controllers;
}
readonly Config m_Config;
readonly ControllersManager<IController> m_Controllers;
readonly CancellationTokenSource m_DestroyCancellationTokenSource;
[Inject] DIContext m_DIContext;
bool m_IsRunning;
public GameMode(Config config) {
m_Config = config;
m_IsRunning = false;
m_DestroyCancellationTokenSource = new CancellationTokenSource();
m_Controllers = new ControllersManager<IController>(m_DestroyCancellationTokenSource.Token);
}
public void Dispose() {
m_DestroyCancellationTokenSource.Cancel();
m_Controllers.Dispose();
}
public async Awaitable<bool> Start(CancellationToken cancellationToken) {
m_Controllers.Add(m_Config.controllers, m_DIContext);
await m_Controllers.Start(cancellationToken);
m_IsRunning = true;
return true;
}
public void Stop() {
m_IsRunning = false;
m_Controllers.Stop();
}
public void Tick() {
m_Controllers.Tick();
}
public void AddController(IController controller) {
m_Controllers.Add(controller);
}
public T FindController<T>() where T : class, IController {
if (m_Controllers.TryFind<T>(out T controller)) {
return controller;
}
return null;
}
}
}

View File

@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: 73f15dc489209cc4a9ff6963e0fbd2c6

View File

@@ -1,47 +1,57 @@
using System.Threading;
using Cysharp.Threading.Tasks;
using R3;
using RebootKit.Engine.Foundation;
using UnityEngine.Assertions;
namespace RebootKit.Engine.Services.Game {
public class GameService : IService {
static readonly Logger s_logger = new(nameof(GameService));
[Inject] DIContext m_DIContext;
GameMode m_GameMode;
GameModeAsset m_GameModeAsset;
bool m_isRunning;
CancellationTokenSource m_DestroyCancellationTokenSource = new();
DisposableBag m_ActiveGameModeDisposableBag;
IGameMode m_ActiveGameMode;
public void Dispose() {
m_isRunning = false;
m_GameMode.Dispose();
m_DestroyCancellationTokenSource.Cancel();
m_DestroyCancellationTokenSource.Dispose();
m_ActiveGameModeDisposableBag.Dispose();
}
public async UniTask Start(GameModeAsset asset, CancellationToken cancellationToken) {
Assert.IsNotNull(asset);
m_GameMode = asset.Create(m_DIContext);
await m_GameMode.Start(cancellationToken);
Run(cancellationToken).Forget();
}
async UniTask Run(CancellationToken cancellationToken) {
if (m_GameMode == null) {
s_logger.Error("Trying to run game without game mode");
public void Start(GameModeAsset asset) {
if (m_ActiveGameMode != null) {
s_logger.Warning("Game is already running");
return;
}
m_isRunning = true;
while (m_isRunning) {
await UniTask.Yield(PlayerLoopTiming.Update, cancellationToken);
m_GameMode.Tick();
Stop();
if (cancellationToken.IsCancellationRequested) {
return;
}
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();
}
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Threading;
using Cysharp.Threading.Tasks;
using RebootKit.Engine.Foundation;
namespace RebootKit.Engine.Services.Game {
public interface IGameMode : IDisposable {
UniTask OnInit(CancellationToken cancellationToken);
void OnStart();
void OnStop();
void OnTick();
}
public abstract class GameModeAsset : FactoryAsset<IGameMode> {
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 562c4ff92afe4949b468003a0e997522
timeCreated: 1743456239

View File

@@ -0,0 +1,5 @@
namespace RebootKit.Engine.Services.Game {
public class Player {
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: be94d631484b4bd2a2c9825290b74b36
timeCreated: 1744413325

View File

@@ -1,6 +1,66 @@
using UnityEngine;
using System;
using System.Threading;
using Cysharp.Threading.Tasks;
using RebootKit.Engine.Foundation;
using UnityEngine;
namespace RebootKit.Engine.Services.Simulation {
public class Actor : MonoBehaviour {
[field: SerializeField]
public SerializableGuid ActorGuid { get; private set; } = SerializableGuid.New();
public bool IsInitialized { get; private set; }
bool m_Simulate;
public bool Simulate {
get => m_Simulate;
set {
if (m_Simulate == value) {
return;
}
m_Simulate = value;
if (!IsInitialized) {
return;
}
if (m_Simulate) {
OnBeginPlay();
} else {
OnEndPlay();
}
}
}
async void Start() {
IsInitialized = false;
await InitAsync(destroyCancellationToken);
IsInitialized = true;
if (Simulate) {
OnBeginPlay();
}
}
void Update() {
if (m_Simulate && IsInitialized) {
OnTick();
}
}
protected virtual async UniTask InitAsync(CancellationToken cancellationToken) {
await UniTask.Yield(cancellationToken);
}
public virtual void OnBeginPlay() {
}
public virtual void OnEndPlay() {
}
public virtual void OnTick() {
}
}
}

View File

@@ -1,4 +1,5 @@
using RebootKit.Engine.Extensions;
using System;
using RebootKit.Engine.Extensions;
using UnityEngine;
namespace RebootKit.Engine.Services.Simulation {
@@ -14,12 +15,15 @@ namespace RebootKit.Engine.Services.Simulation {
public Rigidbody Current { get; private set; }
[field: SerializeField]
public Vector3 TargetWorldPosition { get; set; }
public bool IsDragging => Current != null;
public void FixedUpdate() {
if (Current.OrNull() == null) return;
if (Current.OrNull() == null) {
return;
}
Vector3 direction = (TargetWorldPosition - Current.position).normalized;
float distance = Vector3.Distance(TargetWorldPosition, Current.position);
@@ -32,13 +36,22 @@ namespace RebootKit.Engine.Services.Simulation {
Current.angularVelocity = Vector3.MoveTowards(Current.angularVelocity, Vector3.zero, Time.fixedDeltaTime * AngularSlowdown);
}
void OnDrawGizmosSelected() {
Gizmos.color = Color.green;
Gizmos.DrawSphere(TargetWorldPosition, 0.1f);
}
public void Grab(Rigidbody physicsObject) {
Drop();
Current = physicsObject;
Current.linearDamping = 5.0f;
}
public void Drop() {
if (Current == null) return;
if (Current == null) {
return;
}
Current.linearDamping = 0.0f;
Current = null;

View File

@@ -20,9 +20,17 @@ namespace RebootKit.Engine.Services.Simulation {
public async UniTask Load(WorldConfig worldConfig) {
m_Config = worldConfig;
AsyncOperationHandle<SceneInstance> handle = worldConfig.mainScene.LoadSceneAsync(LoadSceneMode.Additive);
AsyncOperationHandle<SceneInstance> handle = worldConfig.mainScene.LoadSceneAsync(LoadSceneMode.Additive, false);
await handle.ToUniTask();
await handle.Result.ActivateAsync();
SceneManager.SetActiveScene(handle.Result.Scene);
foreach (GameObject root in handle.Result.Scene.GetRootGameObjects()) {
foreach (Actor actor in root.GetComponentsInChildren<Actor>()) {
RegisterActor(actor);
}
}
}
public async UniTask<TActor> SpawnActor<TActor>(AssetReferenceT<GameObject> asset, CancellationToken cancellationToken) where TActor : Actor {
@@ -32,15 +40,16 @@ namespace RebootKit.Engine.Services.Simulation {
return null;
}
if (gameObject.TryGetComponent(out TActor actor)) return actor;
if (gameObject.TryGetComponent(out TActor actor)) {
return actor;
}
asset.ReleaseInstance(gameObject);
return null;
}
public async UniTask RegisterActor(Actor actor) {
public void RegisterActor(Actor actor) {
m_Actors.Add(actor);
await UniTask.Yield();
}
public void KillActor(Actor actor) {
@@ -48,7 +57,9 @@ namespace RebootKit.Engine.Services.Simulation {
}
public void KillAllActors() {
foreach (Actor actor in m_Actors) Addressables.ReleaseInstance(actor.gameObject);
foreach (Actor actor in m_Actors) {
Addressables.ReleaseInstance(actor.gameObject);
}
m_Actors.Clear();
}