add voxel world runtime navmesh sidecar
Introduce a DI-wired NavMesh sidecar for voxel chunks so world streaming stays actor-driven and world state remains the canonical source for navigation rebuilds.
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
using InfiniteWorld.VoxelWorld;
|
||||
using InfiniteWorld.VoxelWorld.Contracts;
|
||||
using InfiniteWorld.VoxelWorld.NavMesh;
|
||||
using MessagePipe;
|
||||
using UnityEngine;
|
||||
using VContainer;
|
||||
using VContainer.Unity;
|
||||
|
||||
namespace VoxelWorldScene
|
||||
{
|
||||
[DisallowMultipleComponent]
|
||||
[RequireComponent(typeof(VoxelWorldGenerator))]
|
||||
public sealed class VoxelWorldNavMeshLifetimeScope : LifetimeScope
|
||||
{
|
||||
[SerializeField] private bool enableRuntimeNavMesh = true;
|
||||
[SerializeField] private VoxelWorldGenerator worldGenerator;
|
||||
[SerializeField] private VoxelWorldNavMeshConfig config = new VoxelWorldNavMeshConfig();
|
||||
|
||||
protected override void Configure(IContainerBuilder builder)
|
||||
{
|
||||
if (!enableRuntimeNavMesh)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (worldGenerator == null)
|
||||
{
|
||||
worldGenerator = GetComponent<VoxelWorldGenerator>();
|
||||
}
|
||||
|
||||
builder.RegisterMessagePipe();
|
||||
builder.RegisterInstance(config);
|
||||
builder.RegisterInstance(worldGenerator).As<IChunkNavSourceReader>().As<IWorldInterestReader>().AsSelf();
|
||||
builder.RegisterEntryPoint<VoxelWorldNavMeshService>();
|
||||
builder.RegisterBuildCallback(ResolvePublishers);
|
||||
}
|
||||
|
||||
private void ResolvePublishers(IObjectResolver resolver)
|
||||
{
|
||||
if (!enableRuntimeNavMesh || worldGenerator == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
worldGenerator.BindWorldContracts(
|
||||
resolver.Resolve<IPublisher<ChunkNavGeometryReadyMessage>>(),
|
||||
resolver.Resolve<IPublisher<ChunkNavGeometryRemovedMessage>>(),
|
||||
resolver.Resolve<IPublisher<WorldInterestChangedMessage>>());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2dfd0b7ddf3a419f91ce891210f85d4b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,75 @@
|
||||
using InfiniteWorld.VoxelWorld;
|
||||
using Players;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VoxelWorldScene
|
||||
{
|
||||
[DisallowMultipleComponent]
|
||||
[RequireComponent(typeof(VoxelWorldGenerator))]
|
||||
public sealed class VoxelWorldPlayerStreamTargetBinding : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private VoxelWorldGenerator worldGenerator;
|
||||
[SerializeField] private Transform explicitStreamTarget;
|
||||
|
||||
private Transform currentStreamTarget;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (worldGenerator == null)
|
||||
{
|
||||
worldGenerator = GetComponent<VoxelWorldGenerator>();
|
||||
}
|
||||
|
||||
ApplyResolvedTarget(ResolveTarget());
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
ApplyResolvedTarget(ResolveTarget());
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
ApplyResolvedTarget(null);
|
||||
}
|
||||
|
||||
private Transform ResolveTarget()
|
||||
{
|
||||
if (explicitStreamTarget != null)
|
||||
{
|
||||
return explicitStreamTarget;
|
||||
}
|
||||
|
||||
if (currentStreamTarget != null)
|
||||
{
|
||||
return currentStreamTarget;
|
||||
}
|
||||
|
||||
CameraFollow[] cameraFollows = FindObjectsByType<CameraFollow>(FindObjectsInactive.Exclude, FindObjectsSortMode.None);
|
||||
for (int i = 0; i < cameraFollows.Length; i++)
|
||||
{
|
||||
CameraFollow follow = cameraFollows[i];
|
||||
if (follow != null && follow.IsOwner)
|
||||
{
|
||||
return follow.Target;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void ApplyResolvedTarget(Transform resolvedTarget)
|
||||
{
|
||||
if (currentStreamTarget == resolvedTarget)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
currentStreamTarget = resolvedTarget;
|
||||
if (worldGenerator != null)
|
||||
{
|
||||
worldGenerator.SetStreamTarget(currentStreamTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c52a16bd6e44739b6bb1b4471a7a5a9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user