working on actors

This commit is contained in:
2025-07-03 05:52:52 +02:00
parent 315661ed8d
commit 0d69e37385
132 changed files with 63264 additions and 591 deletions

View File

@@ -4,7 +4,7 @@ using RebootReality.jelycho.Main;
using UnityEngine;
namespace RebootReality.jelycho.Abilities {
public class AbilitiesContainer : Actor {
public class AbilitiesContainer {
public AbilitiesContainer() {
}
@@ -14,7 +14,7 @@ namespace RebootReality.jelycho.Abilities {
public void RemoveAbility(AbilityEffect ability) {
}
public override void Tick(float deltaTime) {
public void Tick(float deltaTime) {
}
}

View File

@@ -1,47 +0,0 @@
using System.Collections.Generic;
using RebootKit.Engine.Main;
using Unity.Netcode;
using UnityEngine;
namespace RebootReality.jelycho.Beacons {
public class BaseManager : NetworkBehaviour {
[SerializeField] Beacon m_BeaconPrefab;
[SerializeField] float m_ConnectionRopeLength = 10.0f;
[SerializeField] float m_BeaconSpawnRadius = 15.0f;
readonly List<Beacon> m_Beacons = new List<Beacon>();
public IReadOnlyList<Beacon> Beacons => m_Beacons;
[ServerRpc(RequireOwnership = false)]
public void SpawnBeaconServerRpc(Vector3 position) {
if (!IsServer) {
Debug.LogWarning("Only the server can spawn beacons.");
return;
}
Beacon beacon = Instantiate(m_BeaconPrefab, position, Quaternion.identity);
beacon.NetworkObject.Spawn();
beacon.GrowClientRpc();
foreach (Beacon otherBeacon in m_Beacons) {
if ((otherBeacon.transform.position - beacon.transform.position).sqrMagnitude <
m_BeaconSpawnRadius * m_BeaconSpawnRadius) {
Vector3 startPosition = otherBeacon.RopeConnectionPoint.position;
Vector3 endPosition = beacon.RopeConnectionPoint.position;
SpawnRopeRpc(startPosition, endPosition);
}
}
m_Beacons.Add(beacon);
}
[Rpc(SendTo.Everyone)]
void SpawnRopeRpc(Vector3 startPosition, Vector3 endPosition) {
if (RR.World.Context is WorldContext worldContext) {
worldContext.RopesManager.SpawnLockedRope(m_ConnectionRopeLength, startPosition, endPosition);
}
}
}
}

View File

@@ -0,0 +1,58 @@
using RebootKit.Engine.Main;
using RebootKit.Engine.Simulation;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AddressableAssets;
namespace RebootReality.jelycho.Beacons {
public class BaseManagerActorData : IActorData {
public void Serialize(FastBufferWriter writer) {
}
public void Deserialize(FastBufferReader reader) {
}
}
public enum BaseManagerActorCommands : ushort {
None = 0x0000,
SpawnBeacon = 0x0001,
}
public struct SpawnBeaconCommandData : ISerializableEntity {
public Vector3 Position;
public void Serialize(FastBufferWriter writer) {
writer.WriteValue(Position);
}
public void Deserialize(FastBufferReader reader) {
reader.ReadValue(out Position);
}
}
public class BaseManagerActor : Actor {
[SerializeField] AssetReferenceGameObject m_BeaconPrefab;
[SerializeField] float m_ConnectionRopeLength = 10.0f;
[SerializeField] float m_BeaconSpawnRadius = 15.0f;
protected override IActorData CreateActorData() {
return new BaseManagerActorData();
}
protected override void OnActorCommandServer(ActorCommand actorCommand) {
if (actorCommand.CommandID == (ushort)BaseManagerActorCommands.SpawnBeacon) {
SpawnBeaconCommandData commandData = new SpawnBeaconCommandData();
DataSerializationUtils.Deserialize(actorCommand.Data, ref commandData);
RR.SpawnActor(m_BeaconPrefab, commandData.Position, Quaternion.identity);
}
}
public void TrySpawnBeacon(Vector3 position) {
SpawnBeaconCommandData commandData = new SpawnBeaconCommandData {
Position = position
};
SendActorCommand((ushort)BaseManagerActorCommands.SpawnBeacon, ref commandData);
}
}
}

View File

@@ -1,14 +1,17 @@
using Unity.Netcode;
using RebootKit.Engine.Simulation;
using UnityEngine;
namespace RebootReality.jelycho.Beacons {
public class Beacon : NetworkBehaviour {
public class Beacon : Actor {
[SerializeField] BeaconGraphics m_Graphics;
[field: SerializeField] public Transform RopeConnectionPoint { get; private set; }
[ClientRpc]
public void GrowClientRpc() {
void Start() {
m_Graphics.Grow();
}
protected override IActorData CreateActorData() {
return new NoActorData();
}
}
}

View File

@@ -0,0 +1,54 @@
using System;
using Cysharp.Threading.Tasks;
using RebootKit.Engine.Simulation;
using UnityEngine;
using UnityEngine.Events;
namespace RebootReality.jelycho {
public class ButtonActor : Actor, IInteractable {
[SerializeField] Transform m_Graphics;
public UnityEvent pressed = new UnityEvent();
protected override IActorData CreateActorData() {
return new NoActorData();
}
protected override void OnActorCommandServer(ActorCommand actorCommand) {
if (actorCommand.CommandID == (ushort) ButtonActorCommands.Press) {
SendActorEvent((ushort) ButtonActorEvents.Pressed);
pressed?.Invoke();
}
}
protected override void OnActorEventClient(ActorEvent actorEvent) {
if (actorEvent.EventID == (ushort) ButtonActorEvents.Pressed) {
PlayPressAnimation();
}
}
void PlayPressAnimation() {
PressAsync().Forget();
}
async UniTask PressAsync() {
m_Graphics.localScale = new Vector3(1, 0.1f, 1);
await UniTask.Delay(TimeSpan.FromSeconds(1.0f));
m_Graphics.localScale = new Vector3(1, 1, 1);
}
public void Interact() {
SendActorCommand((ushort) ButtonActorCommands.Press);
}
}
public enum ButtonActorCommands : ushort {
None = 0x0000,
Press = 0x0001,
}
public enum ButtonActorEvents : ushort {
None = 0x0000,
Pressed = 0x0001,
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d10f6d33b0194c67966bb1a1b891ff3e
timeCreated: 1751492558

View File

@@ -1,17 +0,0 @@
using RebootKit.Engine.Services.Simulation;
using RebootKit.Engine.Simulation;
using RebootReality.jelycho.Main;
using UnityEngine;
using UnityEngine.AI;
namespace RebootReality.jelycho.Enemies {
[AddComponentMenu(GameConsts.k_AddComponentMenu + "Zombie Actor")]
public class ZombieActor : Actor {
[SerializeField] NavMeshAgent m_NavMeshAgent;
[SerializeField] Animator m_Animator;
void OnEnable() {
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: efc25d13716540beb6fc3f803e94385e
timeCreated: 1743790224

View File

@@ -0,0 +1,5 @@
namespace RebootReality.jelycho {
public interface IInteractable {
void Interact();
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2078b76220c046a4b6077ab42e8ccaf3
timeCreated: 1751512956

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 20467ab374d04c1ebc21675b520c0dd2
timeCreated: 1751389239

View File

@@ -0,0 +1,19 @@
using RebootKit.Engine.Simulation;
using Unity.Netcode;
namespace RebootReality.jelycho.Items {
public class ItemActor : Actor {
class ItemActorData : IActorData {
public string ItemID;
public void Serialize(FastBufferWriter writer) {
}
public void Deserialize(FastBufferReader reader) {
}
}
protected override IActorData CreateActorData() {
return new ItemActorData();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4ee344364fab4988921fe13bc0bb2784
timeCreated: 1751389377

View File

@@ -0,0 +1,15 @@
using Unity.Netcode;
namespace RebootReality.jelycho.Items {
public class ItemsManager : NetworkBehaviour {
public override void OnNetworkSpawn() {
base.OnNetworkSpawn();
}
public override void OnNetworkDespawn() {
base.OnNetworkDespawn();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f944119563484f089d2efb7e347c1bf4
timeCreated: 1751389244

View File

@@ -0,0 +1,78 @@
using System.Globalization;
using RebootKit.Engine.Main;
using RebootKit.Engine.Simulation;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AddressableAssets;
namespace RebootReality.jelycho.Items {
public class WorkbenchActor : Actor {
class WorkbenchActorData : IActorData {
public int SelectedRecipeIndex;
public void Serialize(FastBufferWriter writer) {
writer.WriteValue(SelectedRecipeIndex);
}
public void Deserialize(FastBufferReader reader) {
reader.ReadValue(out SelectedRecipeIndex);
}
}
[SerializeField] AssetReferenceGameObject m_ItemActorReference;
[SerializeField] Transform m_PreviewSlot;
[SerializeField] Transform m_CraftSpawnPoint;
[SerializeField] TMP_Text m_TimerText;
public override void ServerTick(float deltaTime) {
base.ServerTick(deltaTime);
}
public override void ClientTick(float deltaTime) {
base.ClientTick(deltaTime);
m_TimerText.text = DataAs<WorkbenchActorData>().SelectedRecipeIndex.ToString();
}
protected override void OnActorCommandServer(ActorCommand actorCommand) {
if (actorCommand.CommandID == (ushort) WorkbenchActorCommands.SelectNextRecipe) {
WorkbenchActorData data = DataAs<WorkbenchActorData>();
data.SelectedRecipeIndex += 1;
IsDataDirty = true;
} else if (actorCommand.CommandID == (ushort) WorkbenchActorCommands.SelectPreviousRecipe) {
WorkbenchActorData data = DataAs<WorkbenchActorData>();
data.SelectedRecipeIndex -= 1;
IsDataDirty = true;
} else if (actorCommand.CommandID == (ushort) WorkbenchActorCommands.CraftItem) {
RR.SpawnActor(m_ItemActorReference, m_CraftSpawnPoint.position, Quaternion.identity);
}
}
protected override IActorData CreateActorData() {
return new WorkbenchActorData {
SelectedRecipeIndex = Random.Range(0, 10)
};
}
public void SelectNextRecipe() {
SendActorCommand((ushort)WorkbenchActorCommands.SelectNextRecipe);
}
public void SelectPreviousRecipe() {
SendActorCommand((ushort)WorkbenchActorCommands.SelectPreviousRecipe);
}
public void CraftItem() {
SendActorCommand((ushort) WorkbenchActorCommands.CraftItem);
}
}
public enum WorkbenchActorCommands : ushort {
None = 0x0000,
SelectNextRecipe = 0x0001,
SelectPreviousRecipe = 0x0002,
CraftItem = 0x0003,
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 18679c72768c42b0bfed7d0fdb1a2a4e
timeCreated: 1751400906

View File

@@ -1,35 +0,0 @@
using System;
using RebootKit.Engine.Main;
using RebootReality.jelycho.Beacons;
using Unity.Netcode;
using UnityEngine;
using Logger = RebootKit.Engine.Foundation.Logger;
namespace RebootReality.jelycho.Main {
public class GameWorldController : NetworkWorldController {
static readonly Logger s_Logger = new Logger(nameof(GameWorldController));
public static GameWorldController Instance { get; private set; }
[SerializeField] BaseManager m_BaseManager;
void Awake() {
Instance = this;
}
public override void OnDestroy() {
Instance = null;
base.OnDestroy();
}
[Rpc(SendTo.Server)]
public void RequestBeaconSpawnRpc(Vector3 position) {
if (!IsServer) {
s_Logger.Error("Only the server can spawn beacons.");
return;
}
m_BaseManager.SpawnBeaconServerRpc(position);
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 3d6f280a434549d99d5c2b7f178ba6b6
timeCreated: 1751377186

View File

@@ -22,11 +22,6 @@ namespace RebootReality.jelycho.Main {
public class JelychoGame : Game {
static readonly Logger s_Logger = new Logger(nameof(JelychoGame));
[Header("Gameplay")]
[SerializeField] GameWorldController m_GameWorldControllerPrefab;
public GameWorldController m_GameWorldController;
[Header("Player")]
[SerializeField] PlayerController m_PlayerControllerPrefab;
[SerializeField] PlayerActor m_PlayerActorPrefab;
@@ -38,6 +33,19 @@ namespace RebootReality.jelycho.Main {
public override void OnDestroy() {
base.OnDestroy();
}
protected override void OnPlayerBecameReady(ulong clientID) {
s_Logger.Info($"Player {clientID} became ready");
PlayerActor actor = Instantiate(m_PlayerActorPrefab);
actor.name = $"PlayerActor_{clientID}";
actor.NetworkObject.SpawnAsPlayerObject(clientID);
PlayerState playerState = GetPlayerState(clientID);
Assert.IsNotNull(playerState);
playerState.Actor = actor;
playerState.Controller.SetActorClientRpc(actor.NetworkObjectId);
}
public override void OnNetworkSpawn() {
base.OnNetworkSpawn();
@@ -84,42 +92,6 @@ namespace RebootReality.jelycho.Main {
}
}
public override void OnWorldLoaded() {
base.OnWorldLoaded();
if (IsServer) {
m_GameWorldController = Instantiate(m_GameWorldControllerPrefab);
m_GameWorldController.NetworkObject.Spawn();
}
OnPlayerReadyRpc(NetworkManager.Singleton.LocalClientId);
}
public override void OnWorldUnload() {
base.OnWorldUnload();
if (IsServer) {
m_GameWorldController.NetworkObject.Despawn();
Destroy(m_GameWorldController.gameObject);
}
}
[Rpc(SendTo.Server)]
void OnPlayerReadyRpc(ulong clientID) {
if (!IsServer) {
return;
}
PlayerActor actor = Instantiate(m_PlayerActorPrefab);
actor.name = $"PlayerActor_{clientID}";
actor.NetworkObject.SpawnAsPlayerObject(clientID);
PlayerState playerState = GetPlayerState(clientID);
Assert.IsNotNull(playerState);
playerState.Actor = actor;
playerState.Controller.SetActorClientRpc(actor.NetworkObjectId);
}
PlayerState GetPlayerState(ulong clientID) {
foreach (PlayerState state in m_PlayerStates) {
if (state.clientID == clientID) {
@@ -145,6 +117,12 @@ namespace RebootReality.jelycho.Main {
RR.WriteToConsole($" {worldConfigAsset.Config.name}");
}
}
[RCCMD("connect_dev", "Connects to a local server for development purposes")]
public static void ConnectToLocalServer(string[] args) {
RR.WriteToConsole("Connecting to server...");
RR.Connect();
}
[RCCMD("connect", "Connects to a server with given Steam ID. Usage: connect <steam_id>")]
public static void ConnectToServer(string[] args) {

View File

@@ -1,12 +1,9 @@
using RebootKit.Engine.Extensions;
using System;
using RebootKit.Engine.Extensions;
using RebootKit.Engine.Foundation;
using RebootKit.Engine.Main;
using RebootKit.Engine.Services.Simulation;
using RebootKit.Engine.Services.Simulation.Sensors;
using RebootKit.Engine.Simulation;
using RebootKit.Engine.Simulation.Sensors;
using RebootReality.jelycho.Main;
using Unity.Collections;
using Unity.Mathematics;
using Unity.Netcode;
using UnityEngine;
@@ -29,6 +26,42 @@ namespace RebootReality.jelycho.Player {
}
}
[Serializable]
public struct GenericSensor : ISensor {
[SerializeField] Transform m_Origin;
[SerializeField] LayerMask m_LayerMask;
[SerializeField] float m_MaxDistance;
public GameObject Sense() {
Ray ray = new Ray(m_Origin.position, m_Origin.forward);
if (Physics.Raycast(ray, out RaycastHit hit, m_MaxDistance, m_LayerMask)) {
return hit.collider.gameObject;
}
return null;
}
}
[Serializable]
public struct GenericSensor<T> : ISensor<T> where T : class {
[SerializeField] Transform m_Origin;
[SerializeField] LayerMask m_LayerMask;
[SerializeField] float m_MaxDistance;
public T Sense() {
Ray ray = new Ray(m_Origin.position, m_Origin.forward);
if (Physics.Raycast(ray, out RaycastHit hit, m_MaxDistance, m_LayerMask)) {
if (hit.collider.TryGetComponent(out T component)) {
return component;
}
}
return null;
}
}
public class PlayerActor : NetworkBehaviour {
static readonly Logger s_Logger = new Logger(nameof(PlayerActor));
@@ -75,6 +108,9 @@ namespace RebootReality.jelycho.Player {
[SerializeField] LayerMask m_BeaconPlacementLayerMask = 0;
[SerializeField] float m_BeaconPlacementMaxDistance = 15.0f;
[SerializeField] float m_NormalDotUpThreshold = 0.5f;
[Header("Sensors")]
[SerializeField] GenericSensor<IInteractable> m_InteractablesSensor;
[Header("Network")]
[SerializeField] float m_MinTeleportDistance = 0.5f;
@@ -318,7 +354,9 @@ namespace RebootReality.jelycho.Player {
if (TryGetBeaconPosition(out Vector3 beaconPosition)) {
SetAnimatorTriggerRpc(AnimatorParamHashes.Throw);
GameWorldController.Instance.RequestBeaconSpawnRpc(beaconPosition);
if (RR.World.Context is WorldContext worldContext) {
worldContext.BaseManager.TrySpawnBeacon(beaconPosition);
}
}
}
@@ -331,10 +369,33 @@ namespace RebootReality.jelycho.Player {
m_Animator.SetTrigger(AnimatorParamHashes.Block);
}
public void Interact() {
if (!IsOwner) {
s_Logger.Error("Only the owner can perform interactions.");
return;
}
IInteractable interactable = m_InteractablesSensor.Sense();
if (interactable is not null) {
interactable.Interact();
SetAnimatorTriggerRpc(AnimatorParamHashes.Throw);
}
}
[Rpc(SendTo.Everyone)]
void SetAnimatorTriggerRpc(int hash) {
m_Animator.SetTrigger(hash);
}
bool TryGetInteractable(out IInteractable interactable) {
GameObject pickedGameObject = m_Camera.Sensor.Sense();
if (pickedGameObject != null && pickedGameObject.TryGetComponent(out interactable)) {
return true;
}
interactable = null;
return false;
}
bool TryGetBeaconPosition(out Vector3 position) {
Ray ray = new Ray(m_Camera.Camera.transform.position, m_Camera.Camera.transform.forward);

View File

@@ -97,6 +97,10 @@ namespace RebootReality.jelycho.Player {
if (m_Config.secondaryActionReference.action.WasReleasedThisFrame()) {
m_Actor.SecondaryAction();
}
if (m_Config.interactActionReference.action.WasReleasedThisFrame()) {
m_Actor.Interact();
}
}
[Serializable]
@@ -108,6 +112,7 @@ namespace RebootReality.jelycho.Player {
public InputActionReference dragObjectActionReference;
public InputActionReference primaryActionReference;
public InputActionReference secondaryActionReference;
public InputActionReference interactActionReference;
}
}

View File

@@ -12,11 +12,11 @@ namespace RebootReality.jelycho.Ropes {
public class RopesManager : MonoBehaviour {
[SerializeField] float m_RopeSegmentLength = 0.5f;
[SerializeField] int m_ConstrainIterations = 50;
[SerializeField] bool m_ShowGizmos = true;
readonly List<RopeData> m_Ropes = new List<RopeData>();
public int RopesCount {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get {
@@ -45,9 +45,9 @@ namespace RebootReality.jelycho.Ropes {
RopeConfig ropeConfig = RopeConfig.Default;
ropeConfig.segmentLength = m_RopeSegmentLength;
ropeConfig.numberOfConstrainIterations = m_ConstrainIterations;
float deltaTime = Time.fixedDeltaTime;
Profiler.BeginSample("RopesManager.SimulateRopes");
NativeArray<JobHandle> jobHandles = new NativeArray<JobHandle>(m_Ropes.Count, Allocator.Temp);
@@ -73,21 +73,18 @@ namespace RebootReality.jelycho.Ropes {
Profiler.BeginSample("RopesManager.CalculateRopeBounds");
// @TODO: figure out a way to avoid this job dependency chain.
NativeArray<NativeArray<float3>> boundsArrays = new NativeArray<NativeArray<float3>>(m_Ropes.Count, Allocator.Temp);
NativeArray<NativeArray<float3>> boundsArrays =
new NativeArray<NativeArray<float3>>(m_Ropes.Count, Allocator.Temp);
for (int i = 0; i < m_Ropes.Count; i++) {
boundsArrays[i] = new NativeArray<float3>(2, Allocator.TempJob);
CalculateRopeBoundsJob calculateBoundsJob = new CalculateRopeBoundsJob {
Positions = m_Ropes[i].Positions,
Bounds = boundsArrays[i]
};
// if (i > 0) {
// jobHandles[i] = calculateBoundsJob.Schedule(jobHandles[i - 1]);
// } else {
jobHandles[i] = calculateBoundsJob.Schedule();
// }
jobHandles[i] = calculateBoundsJob.Schedule();
}
JobHandle.CompleteAll(jobHandles);
@@ -100,7 +97,7 @@ namespace RebootReality.jelycho.Ropes {
m_Ropes[i] = rope;
}
Profiler.EndSample();
foreach (NativeArray<float3> boundsArray in boundsArrays) {
boundsArray.Dispose();
}
@@ -111,11 +108,11 @@ namespace RebootReality.jelycho.Ropes {
// @TODO: finish the rope spawning logic.
public void SpawnRope(float3 start, float3 end, bool lockFirst = false, bool lockLast = false) {
int segmentsCount = (int)(math.distance(start, end) / m_RopeSegmentLength) + 1;
int segmentsCount = (int) (math.distance(start, end) / m_RopeSegmentLength) + 1;
NativeArray<float3> positions = new NativeArray<float3>(segmentsCount, Allocator.Temp);
for (int i = 0; i < segmentsCount; ++i) {
float t = (float)i / (segmentsCount - 1);
float t = (float) i / (segmentsCount - 1);
positions[i] = math.lerp(start, end, t);
}
@@ -126,11 +123,11 @@ namespace RebootReality.jelycho.Ropes {
}
public void SpawnLockedRope(float ropeLength, float3 start, float3 end) {
int segmentsCount = (int)(ropeLength / m_RopeSegmentLength) + 1;
int segmentsCount = (int) (ropeLength / m_RopeSegmentLength) + 1;
NativeArray<float3> positions = new NativeArray<float3>(segmentsCount, Allocator.Temp);
for (int i = 0; i < segmentsCount; ++i) {
float t = (float)i / (segmentsCount - 1);
float t = (float) i / (segmentsCount - 1);
positions[i] = math.lerp(start, end, t);
}
@@ -144,7 +141,7 @@ namespace RebootReality.jelycho.Ropes {
public NativeArray<float3> PeekRopePositions(int index) {
return m_Ropes[index].Positions;
}
static readonly Plane[] s_Planes = new Plane[6];
public bool IsRopeBoundsInFrustum(int index, Camera cam) {
@@ -153,11 +150,11 @@ namespace RebootReality.jelycho.Ropes {
GeometryUtility.CalculateFrustumPlanes(cam, s_Planes);
return GeometryUtility.TestPlanesAABB(s_Planes, bound);
}
public Bounds GetRopeBounds(int index) {
return m_Ropes[index].Bounds;
}
void Clear() {
foreach (RopeData rope in m_Ropes) {
rope.Dispose();
@@ -171,7 +168,7 @@ namespace RebootReality.jelycho.Ropes {
public NativeArray<float3> OldPositions;
public NativeArray<bool> IsLocked;
public Bounds Bounds;
public int SegmentCount {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get {
@@ -201,13 +198,13 @@ namespace RebootReality.jelycho.Ropes {
}
}
}
[BurstCompile]
struct SimulateRopeJob : IJobParallelFor {
public NativeArray<float3> Positions;
public NativeArray<float3> OldPositions;
[ReadOnly] public NativeArray<bool> IsLocked;
[ReadOnly] public float DeltaTime;
[ReadOnly] public RopeConfig Config;
@@ -218,7 +215,7 @@ namespace RebootReality.jelycho.Ropes {
float3 position = Positions[index];
float3 segmentPositionBeforeUpdate = position;
position += (position - OldPositions[index]) * Config.dampingFactor;
position.y += Config.gravity * DeltaTime;
@@ -239,7 +236,7 @@ namespace RebootReality.jelycho.Ropes {
for (int i = 0; i < Positions.Length - 1; ++i) {
float3 position = Positions[i];
float3 nextPosition = Positions[i + 1];
float currentDistance = math.distance(position, nextPosition);
float difference = currentDistance - Config.segmentLength;
float3 direction = math.normalize(position - nextPosition);
@@ -254,15 +251,15 @@ namespace RebootReality.jelycho.Ropes {
nextPosition += change;
Positions[i + 1] = nextPosition;
}
}
}
}
}
}
[BurstCompile]
struct CalculateRopeBoundsJob: IJob {
struct CalculateRopeBoundsJob : IJob {
[ReadOnly] public NativeArray<float3> Positions;
public NativeArray<float3> Bounds;
public void Execute() {

View File

@@ -1,4 +1,5 @@
using RebootKit.Engine.Simulation;
using RebootReality.jelycho.Beacons;
using RebootReality.jelycho.Ropes;
using UnityEngine;
@@ -6,5 +7,6 @@ namespace RebootReality.jelycho {
public class WorldContext : MonoBehaviour, IWorldContext {
[field: SerializeField] public Transform PlayerSpawnPoint { get; private set; }
[field: SerializeField] public RopesManager RopesManager { get; private set; }
[field: SerializeField] public BaseManagerActor BaseManager { get; private set; }
}
}