working on actors
This commit is contained in:
@@ -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) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
58
Assets/jelycho/Code/Beacons/BaseManagerActor.cs
Normal file
58
Assets/jelycho/Code/Beacons/BaseManagerActor.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
54
Assets/jelycho/Code/ButtonActor.cs
Normal file
54
Assets/jelycho/Code/ButtonActor.cs
Normal 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,
|
||||
}
|
||||
}
|
||||
3
Assets/jelycho/Code/ButtonActor.cs.meta
Normal file
3
Assets/jelycho/Code/ButtonActor.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d10f6d33b0194c67966bb1a1b891ff3e
|
||||
timeCreated: 1751492558
|
||||
@@ -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() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: efc25d13716540beb6fc3f803e94385e
|
||||
timeCreated: 1743790224
|
||||
5
Assets/jelycho/Code/IInteractable.cs
Normal file
5
Assets/jelycho/Code/IInteractable.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
namespace RebootReality.jelycho {
|
||||
public interface IInteractable {
|
||||
void Interact();
|
||||
}
|
||||
}
|
||||
3
Assets/jelycho/Code/IInteractable.cs.meta
Normal file
3
Assets/jelycho/Code/IInteractable.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2078b76220c046a4b6077ab42e8ccaf3
|
||||
timeCreated: 1751512956
|
||||
3
Assets/jelycho/Code/Items.meta
Normal file
3
Assets/jelycho/Code/Items.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 20467ab374d04c1ebc21675b520c0dd2
|
||||
timeCreated: 1751389239
|
||||
19
Assets/jelycho/Code/Items/ItemActor.cs
Normal file
19
Assets/jelycho/Code/Items/ItemActor.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/jelycho/Code/Items/ItemActor.cs.meta
Normal file
3
Assets/jelycho/Code/Items/ItemActor.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4ee344364fab4988921fe13bc0bb2784
|
||||
timeCreated: 1751389377
|
||||
15
Assets/jelycho/Code/Items/ItemsManager.cs
Normal file
15
Assets/jelycho/Code/Items/ItemsManager.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/jelycho/Code/Items/ItemsManager.cs.meta
Normal file
3
Assets/jelycho/Code/Items/ItemsManager.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f944119563484f089d2efb7e347c1bf4
|
||||
timeCreated: 1751389244
|
||||
78
Assets/jelycho/Code/Items/WorkbenchActor.cs
Normal file
78
Assets/jelycho/Code/Items/WorkbenchActor.cs
Normal 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,
|
||||
}
|
||||
}
|
||||
3
Assets/jelycho/Code/Items/WorkbenchActor.cs.meta
Normal file
3
Assets/jelycho/Code/Items/WorkbenchActor.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18679c72768c42b0bfed7d0fdb1a2a4e
|
||||
timeCreated: 1751400906
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d6f280a434549d99d5c2b7f178ba6b6
|
||||
timeCreated: 1751377186
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user