Added leveler

This commit is contained in:
2026-08-07 11:40:20 +03:00
parent d9d7ee49d2
commit e3746e3e9d
22 changed files with 2824 additions and 383 deletions
@@ -51,6 +51,7 @@ GameObject:
- component: {fileID: 1886685762384766033}
- component: {fileID: 6442729922619842682}
- component: {fileID: 5032171862004131710}
- component: {fileID: 5463195673691487104}
m_Layer: 0
m_Name: NetworkPlayer
m_TagString: Untagged
@@ -291,6 +292,19 @@ MonoBehaviour:
m_EditorClassIdentifier:
ShowTopMostFoldoutHeaderGroup: 1
itemSocket: {fileID: 5015619352217801696}
--- !u!114 &5463195673691487104
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2724913065371725993}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5e63651da7abbf744bc45585a2133e6f, type: 3}
m_Name:
m_EditorClassIdentifier:
ShowTopMostFoldoutHeaderGroup: 1
--- !u!1 &4726019310047661441
GameObject:
m_ObjectHideFlags: 0
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4e01366e581614a4b91cd3efb804691a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,258 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &5225331470301378431
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6263994081241283953}
- component: {fileID: 3440513286429880925}
- component: {fileID: 6739897567601242453}
- component: {fileID: 416908812593322597}
- component: {fileID: 3792544786712207931}
- component: {fileID: 4548792826172284241}
- component: {fileID: 791157199313025935}
- component: {fileID: 5227364662085720870}
- component: {fileID: 171915070508416281}
m_Layer: 0
m_Name: HeavyDragCrate
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &6263994081241283953
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5225331470301378431}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1.5, y: 1.25, z: 1.5}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &3440513286429880925
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5225331470301378431}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!65 &6739897567601242453
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5225331470301378431}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Size: {x: 1, y: 1, z: 1}
m_Center: {x: 0, y: 0, z: 0}
--- !u!23 &416908812593322597
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5225331470301378431}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 1
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!54 &3792544786712207931
Rigidbody:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5225331470301378431}
serializedVersion: 4
m_Mass: 75
m_Drag: 0
m_AngularDrag: 0.05
m_CenterOfMass: {x: 0, y: 0, z: 0}
m_InertiaTensor: {x: 1, y: 1, z: 1}
m_InertiaRotation: {x: 0, y: 0, z: 0, w: 1}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_ImplicitCom: 1
m_ImplicitTensor: 1
m_UseGravity: 1
m_IsKinematic: 0
m_Interpolate: 0
m_Constraints: 0
m_CollisionDetection: 0
--- !u!114 &4548792826172284241
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5225331470301378431}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
m_Name:
m_EditorClassIdentifier:
GlobalObjectIdHash: 2465462244
InScenePlacedSourceGlobalObjectIdHash: 0
DeferredDespawnTick: 0
Ownership: 1
AlwaysReplicateAsRoot: 0
SynchronizeTransform: 1
m_InScenePlaced: 0
ActiveSceneSynchronization: 0
SceneMigrationSynchronization: 0
SpawnWithObservers: 1
DontDestroyWithOwner: 0
AutoObjectParentSync: 1
SyncOwnerTransformWhenParented: 1
AllowOwnerToParent: 0
--- !u!114 &791157199313025935
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5225331470301378431}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e96cb6065543e43c4a752faaa1468eb1, type: 3}
m_Name:
m_EditorClassIdentifier:
ShowTopMostFoldoutHeaderGroup: 1
NetworkTransformExpanded: 0
AutoOwnerAuthorityTickOffset: 1
PositionInterpolationType: 0
RotationInterpolationType: 0
ScaleInterpolationType: 0
PositionLerpSmoothing: 1
PositionMaxInterpolationTime: 0.1
RotationLerpSmoothing: 1
RotationMaxInterpolationTime: 0.1
ScaleLerpSmoothing: 1
ScaleMaxInterpolationTime: 0.1
AuthorityMode: 0
TickSyncChildren: 0
UseUnreliableDeltas: 0
SyncPositionX: 1
SyncPositionY: 1
SyncPositionZ: 1
SyncRotAngleX: 1
SyncRotAngleY: 1
SyncRotAngleZ: 1
SyncScaleX: 1
SyncScaleY: 1
SyncScaleZ: 1
PositionThreshold: 0.001
RotAngleThreshold: 0.01
ScaleThreshold: 0.01
UseQuaternionSynchronization: 0
UseQuaternionCompression: 0
UseHalfFloatPrecision: 0
InLocalSpace: 0
SwitchTransformSpaceWhenParented: 0
Interpolate: 1
SlerpPosition: 0
--- !u!114 &5227364662085720870
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5225331470301378431}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f6c0be61502bb534f922ebb746851216, type: 3}
m_Name:
m_EditorClassIdentifier:
ShowTopMostFoldoutHeaderGroup: 1
NetworkRigidbodyBaseExpanded: 0
UseRigidBodyForMotion: 1
AutoUpdateKinematicState: 1
AutoSetKinematicOnDespawn: 1
--- !u!114 &171915070508416281
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5225331470301378431}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e5e737931b3bc22468ea0fe857062359, type: 3}
m_Name:
m_EditorClassIdentifier:
ShowTopMostFoldoutHeaderGroup: 1
interactionLabel: Drag heavy crate
maximumInteractionDistance: 3
weight: 75
pullStrengthPerPlayer: 50
maximumDraggers: 2
dragOffset: {x: 0, y: 1, z: 1.8}
maximumDragSpeed: 3
minimumSpeedMultiplier: 0.35
maximumDraggerDistance: 4.5
keepCurrentHeight: 0
physicsBody: {fileID: 3792544786712207931}
objectColliders:
- {fileID: 6739897567601242453}
collisionRefreshInterval: 0.25
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 43c2ed447ed075a4c9bb39cb8b389c0e
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,258 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &5225331470301378431
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6263994081241283953}
- component: {fileID: 3440513286429880925}
- component: {fileID: 6739897567601242453}
- component: {fileID: 416908812593322597}
- component: {fileID: 3792544786712207931}
- component: {fileID: 4548792826172284241}
- component: {fileID: 791157199313025935}
- component: {fileID: 5227364662085720870}
- component: {fileID: 171915070508416281}
m_Layer: 0
m_Name: LightDragCrate
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &6263994081241283953
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5225331470301378431}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &3440513286429880925
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5225331470301378431}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!65 &6739897567601242453
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5225331470301378431}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Size: {x: 1, y: 1, z: 1}
m_Center: {x: 0, y: 0, z: 0}
--- !u!23 &416908812593322597
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5225331470301378431}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 1
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!54 &3792544786712207931
Rigidbody:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5225331470301378431}
serializedVersion: 4
m_Mass: 30
m_Drag: 0
m_AngularDrag: 0.05
m_CenterOfMass: {x: 0, y: 0, z: 0}
m_InertiaTensor: {x: 1, y: 1, z: 1}
m_InertiaRotation: {x: 0, y: 0, z: 0, w: 1}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_ImplicitCom: 1
m_ImplicitTensor: 1
m_UseGravity: 1
m_IsKinematic: 0
m_Interpolate: 0
m_Constraints: 0
m_CollisionDetection: 0
--- !u!114 &4548792826172284241
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5225331470301378431}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
m_Name:
m_EditorClassIdentifier:
GlobalObjectIdHash: 1192102892
InScenePlacedSourceGlobalObjectIdHash: 0
DeferredDespawnTick: 0
Ownership: 1
AlwaysReplicateAsRoot: 0
SynchronizeTransform: 1
m_InScenePlaced: 0
ActiveSceneSynchronization: 0
SceneMigrationSynchronization: 0
SpawnWithObservers: 1
DontDestroyWithOwner: 0
AutoObjectParentSync: 1
SyncOwnerTransformWhenParented: 1
AllowOwnerToParent: 0
--- !u!114 &791157199313025935
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5225331470301378431}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e96cb6065543e43c4a752faaa1468eb1, type: 3}
m_Name:
m_EditorClassIdentifier:
ShowTopMostFoldoutHeaderGroup: 1
NetworkTransformExpanded: 0
AutoOwnerAuthorityTickOffset: 1
PositionInterpolationType: 0
RotationInterpolationType: 0
ScaleInterpolationType: 0
PositionLerpSmoothing: 1
PositionMaxInterpolationTime: 0.1
RotationLerpSmoothing: 1
RotationMaxInterpolationTime: 0.1
ScaleLerpSmoothing: 1
ScaleMaxInterpolationTime: 0.1
AuthorityMode: 0
TickSyncChildren: 0
UseUnreliableDeltas: 0
SyncPositionX: 1
SyncPositionY: 1
SyncPositionZ: 1
SyncRotAngleX: 1
SyncRotAngleY: 1
SyncRotAngleZ: 1
SyncScaleX: 1
SyncScaleY: 1
SyncScaleZ: 1
PositionThreshold: 0.001
RotAngleThreshold: 0.01
ScaleThreshold: 0.01
UseQuaternionSynchronization: 0
UseQuaternionCompression: 0
UseHalfFloatPrecision: 0
InLocalSpace: 0
SwitchTransformSpaceWhenParented: 0
Interpolate: 1
SlerpPosition: 0
--- !u!114 &5227364662085720870
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5225331470301378431}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f6c0be61502bb534f922ebb746851216, type: 3}
m_Name:
m_EditorClassIdentifier:
ShowTopMostFoldoutHeaderGroup: 1
NetworkRigidbodyBaseExpanded: 0
UseRigidBodyForMotion: 1
AutoUpdateKinematicState: 1
AutoSetKinematicOnDespawn: 1
--- !u!114 &171915070508416281
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5225331470301378431}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e5e737931b3bc22468ea0fe857062359, type: 3}
m_Name:
m_EditorClassIdentifier:
ShowTopMostFoldoutHeaderGroup: 1
interactionLabel: Drag light crate
maximumInteractionDistance: 3
weight: 30
pullStrengthPerPlayer: 50
maximumDraggers: 2
dragOffset: {x: 0, y: 1, z: 1.8}
maximumDragSpeed: 3
minimumSpeedMultiplier: 0.35
maximumDraggerDistance: 4.5
keepCurrentHeight: 0
physicsBody: {fileID: 3792544786712207931}
objectColliders:
- {fileID: 6739897567601242453}
collisionRefreshInterval: 0.25
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8fce593e28d06e54d83ed63d9e60c3c0
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,500 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &1023873631625220400
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7469934142893093605}
- component: {fileID: 2927001865383913474}
- component: {fileID: 8667316428577315048}
- component: {fileID: 1146083900248343034}
m_Layer: 0
m_Name: Base
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &7469934142893093605
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1023873631625220400}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0.3, z: 0}
m_LocalScale: {x: 0.8, y: 0.6, z: 0.8}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 2407670811493793166}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &2927001865383913474
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1023873631625220400}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!65 &8667316428577315048
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1023873631625220400}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Size: {x: 1, y: 1, z: 1}
m_Center: {x: 0, y: 0, z: 0}
--- !u!23 &1146083900248343034
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1023873631625220400}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 1
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!1 &1592568415919095802
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7323185562253079591}
m_Layer: 0
m_Name: LeverPivot
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &7323185562253079591
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1592568415919095802}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0.65, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 413054211318646273}
- {fileID: 9018567234557895278}
m_Father: {fileID: 2407670811493793166}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &3060436709493570404
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 9018567234557895278}
- component: {fileID: 7065961267260340139}
- component: {fileID: 6752593838293933595}
- component: {fileID: 3216989811936523488}
m_Layer: 0
m_Name: Handle
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &9018567234557895278
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3060436709493570404}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 1.35, z: 0}
m_LocalScale: {x: 0.36, y: 0.36, z: 0.36}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7323185562253079591}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &7065961267260340139
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3060436709493570404}
m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
--- !u!135 &6752593838293933595
SphereCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3060436709493570404}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Radius: 0.5
m_Center: {x: 0, y: 0, z: 0}
--- !u!23 &3216989811936523488
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3060436709493570404}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 1
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!1 &6312094898028107579
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 413054211318646273}
- component: {fileID: 9016344377187877216}
- component: {fileID: 6921548535170618678}
- component: {fileID: 8704740599923309004}
m_Layer: 0
m_Name: Arm
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &413054211318646273
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6312094898028107579}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0.65, z: 0}
m_LocalScale: {x: 0.16, y: 1.3, z: 0.16}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7323185562253079591}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &9016344377187877216
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6312094898028107579}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!65 &6921548535170618678
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6312094898028107579}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Size: {x: 1, y: 1, z: 1}
m_Center: {x: 0, y: 0, z: 0}
--- !u!23 &8704740599923309004
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6312094898028107579}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 1
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!1 &8815354352711425077
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2407670811493793166}
- component: {fileID: 8522563728462659335}
- component: {fileID: 1530454800977108524}
- component: {fileID: 2476357789053846530}
m_Layer: 0
m_Name: PhysicalLever
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &2407670811493793166
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8815354352711425077}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 7469934142893093605}
- {fileID: 7323185562253079591}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &8522563728462659335
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8815354352711425077}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
m_Name:
m_EditorClassIdentifier:
GlobalObjectIdHash: 1012607634
InScenePlacedSourceGlobalObjectIdHash: 0
DeferredDespawnTick: 0
Ownership: 1
AlwaysReplicateAsRoot: 0
SynchronizeTransform: 1
m_InScenePlaced: 1
ActiveSceneSynchronization: 0
SceneMigrationSynchronization: 0
SpawnWithObservers: 1
DontDestroyWithOwner: 0
AutoObjectParentSync: 1
SyncOwnerTransformWhenParented: 1
AllowOwnerToParent: 0
--- !u!114 &1530454800977108524
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8815354352711425077}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e96cb6065543e43c4a752faaa1468eb1, type: 3}
m_Name:
m_EditorClassIdentifier:
ShowTopMostFoldoutHeaderGroup: 1
NetworkTransformExpanded: 0
AutoOwnerAuthorityTickOffset: 1
PositionInterpolationType: 0
RotationInterpolationType: 0
ScaleInterpolationType: 0
PositionLerpSmoothing: 1
PositionMaxInterpolationTime: 0.1
RotationLerpSmoothing: 1
RotationMaxInterpolationTime: 0.1
ScaleLerpSmoothing: 1
ScaleMaxInterpolationTime: 0.1
AuthorityMode: 0
TickSyncChildren: 0
UseUnreliableDeltas: 0
SyncPositionX: 1
SyncPositionY: 1
SyncPositionZ: 1
SyncRotAngleX: 1
SyncRotAngleY: 1
SyncRotAngleZ: 1
SyncScaleX: 1
SyncScaleY: 1
SyncScaleZ: 1
PositionThreshold: 0.001
RotAngleThreshold: 0.01
ScaleThreshold: 0.01
UseQuaternionSynchronization: 0
UseQuaternionCompression: 0
UseHalfFloatPrecision: 0
InLocalSpace: 0
SwitchTransformSpaceWhenParented: 0
Interpolate: 1
SlerpPosition: 0
--- !u!114 &2476357789053846530
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8815354352711425077}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 262775fc01b9c8a47a82f30b50d7b12a, type: 3}
m_Name:
m_EditorClassIdentifier:
ShowTopMostFoldoutHeaderGroup: 1
interactionLabel: Pull lever
maximumInteractionDistance: 3
leverVisual: {fileID: 7323185562253079591}
neutralLocalEulerAngles: {x: 0, y: 0, z: 0}
localRotationAxis: {x: 1, y: 0, z: 0}
localHandleDirection: {x: 0, y: 1, z: 0}
minimumAngle: -55
maximumAngle: 55
movementSpeed: 140
maximumControlDistance: 4
returnToRestOnRelease: 0
restValue: 0
activationThreshold: 0.85
deactivationThreshold: 0.15
leverValueChanged:
m_PersistentCalls:
m_Calls: []
leverStateChanged:
m_PersistentCalls:
m_Calls: []
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 593b09321d7982e48a7d65a32da0d96a
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,46 @@
using System.Collections.Generic;
using UnityEngine;
public interface IPlayerInteractionSession
{
string ReleasePrompt { get; }
bool IsControlledBy(ulong clientId);
void RequestRelease();
}
public static class PlayerInteractionSessionRegistry
{
private static readonly HashSet<IPlayerInteractionSession> Sessions = new();
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void ResetRegistry() => Sessions.Clear();
public static void Register(IPlayerInteractionSession session)
{
if (session != null)
Sessions.Add(session);
}
public static void Unregister(IPlayerInteractionSession session)
{
if (session != null)
Sessions.Remove(session);
}
public static bool TryGetControlledSession(
ulong clientId,
out IPlayerInteractionSession session)
{
foreach (IPlayerInteractionSession candidate in Sessions)
{
if (candidate != null && candidate.IsControlledBy(clientId))
{
session = candidate;
return true;
}
}
session = null;
return false;
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 766a505389ebff84cb581f905b9736dd
@@ -2,7 +2,7 @@ using UnityEngine;
public sealed class NetworkCarryableInteractable : NetworkHeldInteractable
{
[SerializeField] private Vector3 carryOffset = new(0f, 1.15f, 0.75f);
[SerializeField] private Vector3 carryOffset = new(0f, -0.3f, 1.25f);
protected override Vector3 HoldingOffset => carryOffset;
protected override string DropPrompt => "Put down";
@@ -1,9 +1,282 @@
using System.Collections.Generic;
using Unity.Netcode;
using Unity.Netcode.Components;
using UnityEngine;
public sealed class NetworkDraggableInteractable : NetworkHeldInteractable
[RequireComponent(typeof(Rigidbody), typeof(NetworkRigidbody))]
public sealed class NetworkDraggableInteractable : NetworkInteractable
{
[SerializeField] private Vector3 dragOffset = new(0f, 0.35f, 1.8f);
private const ulong NoDragger = ulong.MaxValue;
protected override Vector3 HoldingOffset => dragOffset;
protected override string DropPrompt => "Release";
[Header("Weight")]
[SerializeField, Min(0.1f)] private float weight = 35f;
[SerializeField, Min(0.1f)] private float pullStrengthPerPlayer = 50f;
[SerializeField, Range(1, 2)] private int maximumDraggers = 2;
[Header("Dragging")]
[SerializeField] private Vector3 dragOffset = new(0f, 1f, 1.8f);
[SerializeField, Min(0.1f)] private float maximumDragSpeed = 3f;
[SerializeField, Range(0.05f, 1f)] private float minimumSpeedMultiplier = 0.35f;
[SerializeField, Min(0.5f)] private float maximumDraggerDistance = 4.5f;
[SerializeField] private bool keepCurrentHeight;
[Header("Physics")]
[SerializeField] private Rigidbody physicsBody;
[SerializeField] private Collider[] objectColliders;
[SerializeField, Min(0.05f)] private float collisionRefreshInterval = 0.25f;
private readonly NetworkVariable<ulong> firstDraggerClientId = new(
NoDragger,
NetworkVariableReadPermission.Everyone,
NetworkVariableWritePermission.Server);
private readonly NetworkVariable<ulong> secondDraggerClientId = new(
NoDragger,
NetworkVariableReadPermission.Everyone,
NetworkVariableWritePermission.Server);
private readonly HashSet<Collider> ignoredPlayerColliders = new();
private float nextCollisionRefreshTime;
public float Weight => weight;
public int ActiveDraggerCount
{
get
{
int count = firstDraggerClientId.Value == NoDragger ? 0 : 1;
if (secondDraggerClientId.Value != NoDragger)
count++;
return count;
}
}
public int RequiredDraggerCount => Mathf.Max(1, Mathf.CeilToInt(weight / pullStrengthPerPlayer));
public bool HasEnoughPullStrength => ActiveDraggerCount >= RequiredDraggerCount;
private bool HasAnyDragger => ActiveDraggerCount > 0;
private bool IsDraggedByLocalPlayer =>
NetworkManager != null && IsDragger(NetworkManager.LocalClientId);
public override string InteractionPrompt
{
get
{
if (IsDraggedByLocalPlayer)
return "Release";
int activeDraggers = ActiveDraggerCount;
if (activeDraggers == 0)
return $"{InteractionLabel} ({weight:0.#} kg)";
if (activeDraggers < maximumDraggers)
return !HasEnoughPullStrength
? $"Help drag ({activeDraggers}/{RequiredDraggerCount})"
: $"Join drag ({activeDraggers}/{maximumDraggers})";
return HasEnoughPullStrength ? "In use" : "Too heavy";
}
}
public override bool IsInteractionAvailable => base.IsInteractionAvailable &&
(IsDraggedByLocalPlayer || ActiveDraggerCount < maximumDraggers);
private void Awake()
{
ResolvePhysicsReferences();
ApplyWeight();
}
private void OnValidate()
{
ResolvePhysicsReferences();
ApplyWeight();
}
public override void OnNetworkSpawn()
{
firstDraggerClientId.OnValueChanged += HandleDraggerChanged;
secondDraggerClientId.OnValueChanged += HandleDraggerChanged;
ApplyDraggingState();
}
public override void OnNetworkDespawn()
{
firstDraggerClientId.OnValueChanged -= HandleDraggerChanged;
secondDraggerClientId.OnValueChanged -= HandleDraggerChanged;
RestorePlayerCollisions();
}
private void Update()
{
if (!HasAnyDragger || Time.time < nextCollisionRefreshTime)
return;
nextCollisionRefreshTime = Time.time + collisionRefreshInterval;
IgnoreCollisionsWithPlayers();
}
private void FixedUpdate()
{
if (!IsServer || !IsSpawned || physicsBody == null)
return;
RemoveInvalidDraggers();
if (!HasEnoughPullStrength || !TryGetCombinedDragTarget(out Vector3 target))
return;
if (keepCurrentHeight)
target.y = physicsBody.position.y;
float totalStrength = ActiveDraggerCount * pullStrengthPerPlayer;
float loadRatio = Mathf.Clamp01(weight / totalStrength);
float speedMultiplier = Mathf.Lerp(1f, minimumSpeedMultiplier, loadRatio);
float movementStep = maximumDragSpeed * speedMultiplier * Time.fixedDeltaTime;
Vector3 nextPosition = Vector3.MoveTowards(physicsBody.position, target, movementStep);
physicsBody.MovePosition(nextPosition);
}
protected override bool CanInteractOnServer(ulong senderClientId) =>
IsDragger(senderClientId) ||
ActiveDraggerCount < maximumDraggers;
protected override void InteractOnServer(ulong senderClientId, NetworkObject playerObject)
{
if (IsDragger(senderClientId))
RemoveDragger(senderClientId);
else
AddDragger(senderClientId);
}
private void AddDragger(ulong clientId)
{
if (firstDraggerClientId.Value == NoDragger)
firstDraggerClientId.Value = clientId;
else if (maximumDraggers > 1 && secondDraggerClientId.Value == NoDragger)
secondDraggerClientId.Value = clientId;
}
private void RemoveDragger(ulong clientId)
{
if (firstDraggerClientId.Value == clientId)
{
firstDraggerClientId.Value = secondDraggerClientId.Value;
secondDraggerClientId.Value = NoDragger;
}
else if (secondDraggerClientId.Value == clientId)
{
secondDraggerClientId.Value = NoDragger;
}
}
private void RemoveInvalidDraggers()
{
ulong first = firstDraggerClientId.Value;
ulong second = secondDraggerClientId.Value;
if (first != NoDragger && !IsDraggerValid(first))
RemoveDragger(first);
if (second != NoDragger && !IsDraggerValid(second))
RemoveDragger(second);
}
private bool IsDraggerValid(ulong clientId)
{
if (!TryGetPlayerObject(clientId, out NetworkObject playerObject))
return false;
float maximumDistanceSquared = maximumDraggerDistance * maximumDraggerDistance;
return (playerObject.transform.position - physicsBody.position).sqrMagnitude <= maximumDistanceSquared;
}
private bool TryGetCombinedDragTarget(out Vector3 target)
{
target = Vector3.zero;
int validTargets = 0;
AddDragTarget(firstDraggerClientId.Value, ref target, ref validTargets);
AddDragTarget(secondDraggerClientId.Value, ref target, ref validTargets);
if (validTargets == 0)
return false;
target /= validTargets;
return true;
}
private void AddDragTarget(ulong clientId, ref Vector3 target, ref int validTargets)
{
if (clientId == NoDragger || !TryGetPlayerObject(clientId, out NetworkObject playerObject))
return;
target += playerObject.transform.TransformPoint(dragOffset);
validTargets++;
}
private bool IsDragger(ulong clientId) =>
firstDraggerClientId.Value == clientId || secondDraggerClientId.Value == clientId;
private void HandleDraggerChanged(ulong _, ulong __) => ApplyDraggingState();
private void ApplyDraggingState()
{
if (physicsBody != null)
{
physicsBody.isKinematic = HasAnyDragger || !IsServer;
physicsBody.linearVelocity = Vector3.zero;
physicsBody.angularVelocity = Vector3.zero;
}
if (HasAnyDragger)
IgnoreCollisionsWithPlayers();
else
RestorePlayerCollisions();
}
private void ResolvePhysicsReferences()
{
if (physicsBody == null)
physicsBody = GetComponent<Rigidbody>();
if (objectColliders == null || objectColliders.Length == 0)
objectColliders = GetComponentsInChildren<Collider>(true);
}
private void ApplyWeight()
{
if (physicsBody != null)
physicsBody.mass = Mathf.Max(0.1f, weight);
}
private void IgnoreCollisionsWithPlayers()
{
foreach (CharacterController playerCollider in FindObjectsByType<CharacterController>(
FindObjectsInactive.Exclude,
FindObjectsSortMode.None))
{
foreach (Collider objectCollider in objectColliders)
{
if (objectCollider != null && playerCollider != null)
Physics.IgnoreCollision(objectCollider, playerCollider, true);
}
ignoredPlayerColliders.Add(playerCollider);
}
}
private void RestorePlayerCollisions()
{
foreach (Collider playerCollider in ignoredPlayerColliders)
{
if (playerCollider == null)
continue;
foreach (Collider objectCollider in objectColliders)
{
if (objectCollider != null)
Physics.IgnoreCollision(objectCollider, playerCollider, false);
}
}
ignoredPlayerColliders.Clear();
}
}
@@ -1,16 +1,23 @@
using System.Collections.Generic;
using Unity.Netcode;
using Unity.Netcode.Components;
using UnityEngine;
[RequireComponent(typeof(Rigidbody), typeof(NetworkRigidbody))]
public abstract class NetworkHeldInteractable : NetworkInteractable
{
protected const ulong NoHolder = ulong.MaxValue;
private static readonly HashSet<NetworkHeldInteractable> SpawnedHeldObjects = new();
[Header("Physics")]
[SerializeField] private Rigidbody physicsBody;
[SerializeField] private Collider[] objectColliders;
[SerializeField, Min(0.05f)] private float collisionRefreshInterval = 0.25f;
[Header("Throw")]
[SerializeField, Min(0f)] private float throwForce = 6f;
[SerializeField, Min(0f)] private float throwUpwardForce = 0.5f;
private readonly NetworkVariable<ulong> holderClientId = new(
NoHolder,
NetworkVariableReadPermission.Everyone,
@@ -22,9 +29,10 @@ public abstract class NetworkHeldInteractable : NetworkInteractable
protected abstract Vector3 HoldingOffset { get; }
protected abstract string DropPrompt { get; }
private bool IsHeld => holderClientId.Value != NoHolder;
private bool IsHeldByLocalPlayer =>
public bool IsHeld => holderClientId.Value != NoHolder;
public bool IsHeldByLocalPlayer =>
NetworkManager != null && holderClientId.Value == NetworkManager.LocalClientId;
public string HeldObjectName => InteractionLabel;
public override string InteractionPrompt => !IsHeld
? InteractionLabel
@@ -46,6 +54,7 @@ public abstract class NetworkHeldInteractable : NetworkInteractable
public override void OnNetworkSpawn()
{
SpawnedHeldObjects.Add(this);
holderClientId.OnValueChanged += HandleHolderChanged;
ApplyHoldingState(IsHeld);
}
@@ -53,6 +62,7 @@ public abstract class NetworkHeldInteractable : NetworkInteractable
public override void OnNetworkDespawn()
{
holderClientId.OnValueChanged -= HandleHolderChanged;
SpawnedHeldObjects.Remove(this);
ApplyHoldingState(false);
}
@@ -69,9 +79,10 @@ public abstract class NetworkHeldInteractable : NetworkInteractable
return;
}
Transform anchor = ResolveHoldingAnchor(holder);
transform.SetPositionAndRotation(
holder.transform.TransformPoint(HoldingOffset),
holder.transform.rotation);
anchor.TransformPoint(HoldingOffset),
anchor.rotation);
if (Time.time >= nextCollisionRefreshTime)
{
@@ -80,8 +91,38 @@ public abstract class NetworkHeldInteractable : NetworkInteractable
}
}
protected override bool CanInteractOnServer(ulong senderClientId) =>
!IsHeld || holderClientId.Value == senderClientId;
public void RequestThrow()
{
if (IsSpawned && IsHeldByLocalPlayer)
RequestThrowServerRpc();
}
public static bool TryGetHeldObject(
ulong clientId,
out NetworkHeldInteractable heldObject)
{
foreach (NetworkHeldInteractable candidate in SpawnedHeldObjects)
{
if (candidate != null && candidate.holderClientId.Value == clientId)
{
heldObject = candidate;
return true;
}
}
heldObject = null;
return false;
}
protected override bool CanInteractOnServer(ulong senderClientId)
{
if (holderClientId.Value == senderClientId)
return true;
return !IsHeld &&
!TryGetHeldObject(senderClientId, out _) &&
!NetworkHandItemInteractable.TryGetHeldItem(senderClientId, out _);
}
protected override void InteractOnServer(ulong senderClientId, NetworkObject playerObject)
{
@@ -91,6 +132,30 @@ public abstract class NetworkHeldInteractable : NetworkInteractable
StartHolding(senderClientId);
}
[Rpc(SendTo.Server, InvokePermission = RpcInvokePermission.Everyone)]
private void RequestThrowServerRpc(RpcParams rpcParams = default)
{
ulong senderClientId = rpcParams.Receive.SenderClientId;
if (holderClientId.Value != senderClientId ||
!TryGetPlayerObject(senderClientId, out NetworkObject playerObject))
{
return;
}
FirstPersonCameraController cameraController =
playerObject.GetComponent<FirstPersonCameraController>();
Vector3 throwDirection = cameraController != null
? cameraController.AimForward
: playerObject.transform.forward;
Vector3 throwVelocity = throwDirection * throwForce +
Vector3.up * throwUpwardForce;
StopHolding();
if (physicsBody != null)
physicsBody.linearVelocity = throwVelocity;
}
private void StartHolding(ulong clientId)
{
holderClientId.Value = clientId;
@@ -103,6 +168,13 @@ public abstract class NetworkHeldInteractable : NetworkInteractable
ApplyHoldingState(false);
}
private Transform ResolveHoldingAnchor(NetworkObject holder)
{
FirstPersonCameraController cameraController =
holder.GetComponent<FirstPersonCameraController>();
return cameraController != null ? cameraController.AimTransform : holder.transform;
}
private void HandleHolderChanged(ulong _, ulong currentHolder) =>
ApplyHoldingState(currentHolder != NoHolder);
@@ -110,9 +182,9 @@ public abstract class NetworkHeldInteractable : NetworkInteractable
{
if (physicsBody != null)
{
physicsBody.isKinematic = isHeld;
if (!isHeld)
physicsBody.linearVelocity = Vector3.zero;
physicsBody.isKinematic = isHeld || !IsServer;
physicsBody.linearVelocity = Vector3.zero;
physicsBody.angularVelocity = Vector3.zero;
}
if (isHeld)
@@ -129,10 +201,8 @@ public abstract class NetworkHeldInteractable : NetworkInteractable
{
foreach (Collider objectCollider in objectColliders)
{
if (objectCollider == null || playerCollider == null)
continue;
Physics.IgnoreCollision(objectCollider, playerCollider, true);
if (objectCollider != null && playerCollider != null)
Physics.IgnoreCollision(objectCollider, playerCollider, true);
}
ignoredPlayerColliders.Add(playerCollider);
@@ -0,0 +1,267 @@
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;
public sealed class NetworkPhysicalLeverInteractable :
NetworkInteractable,
IPlayerInteractionSession
{
private const ulong NoController = ulong.MaxValue;
[Header("Lever visual")]
[SerializeField] private Transform leverVisual;
[SerializeField] private Vector3 neutralLocalEulerAngles;
[SerializeField] private Vector3 localRotationAxis = Vector3.right;
[SerializeField] private Vector3 localHandleDirection = Vector3.up;
[SerializeField, Range(-179f, 179f)] private float minimumAngle = -50f;
[SerializeField, Range(-179f, 179f)] private float maximumAngle = 50f;
[SerializeField, Min(1f)] private float movementSpeed = 180f;
[Header("Control")]
[SerializeField, Min(0.5f)] private float maximumControlDistance = 4f;
[SerializeField] private bool returnToRestOnRelease;
[SerializeField, Range(0f, 1f)] private float restValue;
[Header("Activation")]
[SerializeField, Range(0f, 1f)] private float activationThreshold = 0.85f;
[SerializeField, Range(0f, 1f)] private float deactivationThreshold = 0.15f;
[SerializeField] private UnityEvent<float> leverValueChanged;
[SerializeField] private UnityEvent<bool> leverStateChanged;
private readonly NetworkVariable<ulong> controllingClientId = new(
NoController,
NetworkVariableReadPermission.Everyone,
NetworkVariableWritePermission.Server);
private readonly NetworkVariable<float> synchronizedValue = new(
0f,
NetworkVariableReadPermission.Everyone,
NetworkVariableWritePermission.Server);
private readonly NetworkVariable<bool> isActivated = new(
false,
NetworkVariableReadPermission.Everyone,
NetworkVariableWritePermission.Server);
public float Value => synchronizedValue.Value;
public bool IsActivated => isActivated.Value;
public bool IsControlled => controllingClientId.Value != NoController;
public bool IsControlledByLocalPlayer =>
NetworkManager != null && IsControlledBy(NetworkManager.LocalClientId);
public string ReleasePrompt => "[Hold E] Pulling lever";
public override string InteractionPrompt => IsControlledByLocalPlayer
? ReleasePrompt
: IsControlled
? "Lever in use"
: InteractionLabel;
public override bool IsInteractionAvailable =>
base.IsInteractionAvailable && (!IsControlled || IsControlledByLocalPlayer);
private Quaternion NeutralLocalRotation => Quaternion.Euler(neutralLocalEulerAngles);
private Vector3 RotationAxis => localRotationAxis.sqrMagnitude > 0.0001f
? localRotationAxis.normalized
: Vector3.right;
private Vector3 HandleDirection => localHandleDirection.sqrMagnitude > 0.0001f
? localHandleDirection.normalized
: Vector3.up;
private void Reset()
{
leverVisual = transform;
neutralLocalEulerAngles = leverVisual.localEulerAngles;
}
private void OnValidate()
{
if (maximumAngle < minimumAngle)
maximumAngle = minimumAngle;
deactivationThreshold = Mathf.Min(deactivationThreshold, activationThreshold);
}
public override void OnNetworkSpawn()
{
PlayerInteractionSessionRegistry.Register(this);
synchronizedValue.OnValueChanged += HandleValueChanged;
isActivated.OnValueChanged += HandleActivationChanged;
ApplyVisual(synchronizedValue.Value);
leverValueChanged?.Invoke(synchronizedValue.Value);
leverStateChanged?.Invoke(isActivated.Value);
}
public override void OnNetworkDespawn()
{
PlayerInteractionSessionRegistry.Unregister(this);
synchronizedValue.OnValueChanged -= HandleValueChanged;
isActivated.OnValueChanged -= HandleActivationChanged;
}
private void FixedUpdate()
{
if (!IsServer || !IsSpawned || leverVisual == null)
return;
if (IsControlled)
{
if (!TryGetPlayerObject(controllingClientId.Value, out NetworkObject playerObject) ||
!IsPlayerWithinControlDistance(playerObject))
{
controllingClientId.Value = NoController;
return;
}
if (TryCalculateTargetValue(playerObject, out float targetValue))
MoveTowardsValue(targetValue);
}
else if (returnToRestOnRelease)
{
MoveTowardsValue(restValue);
}
}
public bool IsControlledBy(ulong clientId) =>
controllingClientId.Value == clientId;
public void RequestRelease()
{
if (IsSpawned && IsControlledByLocalPlayer)
RequestReleaseServerRpc();
}
protected override bool CanInteractOnServer(ulong senderClientId) =>
!IsControlled || IsControlledBy(senderClientId);
protected override void InteractOnServer(
ulong senderClientId,
NetworkObject playerObject)
{
controllingClientId.Value = IsControlledBy(senderClientId)
? NoController
: senderClientId;
}
[Rpc(SendTo.Server, InvokePermission = RpcInvokePermission.Everyone)]
private void RequestReleaseServerRpc(RpcParams rpcParams = default)
{
if (IsControlledBy(rpcParams.Receive.SenderClientId))
controllingClientId.Value = NoController;
}
private bool IsPlayerWithinControlDistance(NetworkObject playerObject)
{
float maximumDistanceSquared = maximumControlDistance * maximumControlDistance;
return (playerObject.transform.position - leverVisual.position).sqrMagnitude <=
maximumDistanceSquared;
}
private bool TryCalculateTargetValue(
NetworkObject playerObject,
out float targetValue)
{
targetValue = synchronizedValue.Value;
FirstPersonCameraController cameraController =
playerObject.GetComponent<FirstPersonCameraController>();
Transform aimTransform = cameraController != null
? cameraController.AimTransform
: playerObject.transform;
Transform leverParent = leverVisual.parent;
Quaternion neutralRotation = NeutralLocalRotation;
Vector3 axisWorld = leverParent != null
? leverParent.TransformDirection(neutralRotation * RotationAxis)
: neutralRotation * RotationAxis;
Vector3 neutralDirectionWorld = leverParent != null
? leverParent.TransformDirection(neutralRotation * HandleDirection)
: neutralRotation * HandleDirection;
Ray aimRay = new(aimTransform.position, aimTransform.forward);
Plane movementPlane = new(axisWorld, leverVisual.position);
Vector3 targetPoint;
if (movementPlane.Raycast(aimRay, out float enter) && enter >= 0f)
{
targetPoint = aimRay.GetPoint(enter);
}
else
{
float distanceAlongRay = Mathf.Max(
0.25f,
Vector3.Dot(leverVisual.position - aimRay.origin, aimRay.direction));
targetPoint = aimRay.GetPoint(distanceAlongRay);
}
Vector3 desiredDirection = Vector3.ProjectOnPlane(
targetPoint - leverVisual.position,
axisWorld);
if (desiredDirection.sqrMagnitude < 0.0001f)
return false;
float desiredAngle = Vector3.SignedAngle(
neutralDirectionWorld,
desiredDirection.normalized,
axisWorld);
desiredAngle = Mathf.Clamp(desiredAngle, minimumAngle, maximumAngle);
targetValue = Mathf.InverseLerp(minimumAngle, maximumAngle, desiredAngle);
return true;
}
private void MoveTowardsValue(float targetValue)
{
float angleRange = Mathf.Max(0.01f, maximumAngle - minimumAngle);
float valueStep = movementSpeed / angleRange * Time.fixedDeltaTime;
float nextValue = Mathf.MoveTowards(
synchronizedValue.Value,
Mathf.Clamp01(targetValue),
valueStep);
if (Mathf.Approximately(nextValue, synchronizedValue.Value))
return;
synchronizedValue.Value = nextValue;
UpdateActivationState(nextValue);
}
private void UpdateActivationState(float currentValue)
{
bool nextState = isActivated.Value;
if (!nextState && currentValue >= activationThreshold)
nextState = true;
else if (nextState && currentValue <= deactivationThreshold)
nextState = false;
if (nextState != isActivated.Value)
isActivated.Value = nextState;
}
private void HandleValueChanged(float _, float currentValue)
{
ApplyVisual(currentValue);
leverValueChanged?.Invoke(currentValue);
}
private void HandleActivationChanged(bool _, bool currentState) =>
leverStateChanged?.Invoke(currentState);
private void ApplyVisual(float value)
{
if (leverVisual == null)
return;
float angle = Mathf.Lerp(minimumAngle, maximumAngle, Mathf.Clamp01(value));
leverVisual.localRotation = NeutralLocalRotation *
Quaternion.AngleAxis(angle, RotationAxis);
}
[ContextMenu("Preview/Minimum")]
private void PreviewMinimum() => ApplyVisual(0f);
[ContextMenu("Preview/Rest")]
private void PreviewRest() => ApplyVisual(restValue);
[ContextMenu("Preview/Maximum")]
private void PreviewMaximum() => ApplyVisual(1f);
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 262775fc01b9c8a47a82f30b50d7b12a
@@ -92,7 +92,9 @@ public abstract class NetworkHandItemInteractable : NetworkInteractable, IUsable
}
protected override bool CanInteractOnServer(ulong senderClientId) =>
!IsHeld && !TryGetHeldItem(senderClientId, out _);
!IsHeld &&
!TryGetHeldItem(senderClientId, out _) &&
!NetworkHeldInteractable.TryGetHeldObject(senderClientId, out _);
protected override void InteractOnServer(ulong senderClientId, NetworkObject playerObject)
{
@@ -123,7 +125,12 @@ public abstract class NetworkHandItemInteractable : NetworkInteractable, IUsable
return;
}
Vector3 throwVelocity = playerObject.transform.forward * throwForce +
FirstPersonCameraController cameraController =
playerObject.GetComponent<FirstPersonCameraController>();
Vector3 throwDirection = cameraController != null
? cameraController.AimForward
: playerObject.transform.forward;
Vector3 throwVelocity = throwDirection * throwForce +
Vector3.up * throwUpwardForce;
holderClientId.Value = NoHolder;
@@ -5,12 +5,20 @@ public sealed class FirstPersonCameraController : NetworkBehaviour, IPlayerSyste
{
[SerializeField, Range(1f, 89f)] private float verticalLookLimit = 80f;
private readonly NetworkVariable<float> synchronizedPitch = new(
0f,
NetworkVariableReadPermission.Everyone,
NetworkVariableWritePermission.Owner);
private Camera playerCamera;
private AudioListener audioListener;
private MeshRenderer playerRenderer;
private float pitch;
private bool isInitialized;
public Transform AimTransform => playerCamera != null ? playerCamera.transform : transform;
public Vector3 AimForward => AimTransform.forward;
public void Initialize(PlayerFacade facade)
{
playerCamera = GetComponentInChildren<Camera>(true);
@@ -24,6 +32,9 @@ public sealed class FirstPersonCameraController : NetworkBehaviour, IPlayerSyste
bool isLocalPlayer = IsOwner;
playerCamera.gameObject.SetActive(isLocalPlayer);
if (!isLocalPlayer)
ApplyCameraPitch(synchronizedPitch.Value);
if (!isLocalPlayer)
return;
@@ -43,21 +54,48 @@ public sealed class FirstPersonCameraController : NetworkBehaviour, IPlayerSyste
Cursor.visible = false;
}
public override void OnNetworkSpawn()
{
synchronizedPitch.OnValueChanged += HandleSynchronizedPitchChanged;
if (isInitialized && !IsOwner)
ApplyCameraPitch(synchronizedPitch.Value);
}
public void ApplyPitch(float pitchDelta)
{
if (!isInitialized || !IsOwner)
return;
pitch = Mathf.Clamp(pitch - pitchDelta, -verticalLookLimit, verticalLookLimit);
playerCamera.transform.localRotation = Quaternion.Euler(pitch, 0f, 0f);
ApplyCameraPitch(pitch);
if (IsSpawned)
synchronizedPitch.Value = pitch;
}
public override void OnNetworkDespawn()
{
synchronizedPitch.OnValueChanged -= HandleSynchronizedPitchChanged;
if (IsOwner)
{
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
}
}
private void HandleSynchronizedPitchChanged(float _, float currentPitch)
{
if (!IsOwner)
ApplyCameraPitch(currentPitch);
}
private void ApplyCameraPitch(float currentPitch)
{
pitch = currentPitch;
if (playerCamera != null)
playerCamera.transform.localRotation = Quaternion.Euler(pitch, 0f, 0f);
}
}
@@ -0,0 +1,27 @@
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
public sealed class PlayerCarryController : NetworkBehaviour, IPlayerSystem
{
private bool isInitialized;
public void Initialize(PlayerFacade facade)
{
isInitialized = true;
}
private void Update()
{
if (!isInitialized || !IsOwner || Keyboard.current == null)
return;
if (Keyboard.current.gKey.wasPressedThisFrame &&
NetworkHeldInteractable.TryGetHeldObject(
OwnerClientId,
out NetworkHeldInteractable heldObject))
{
heldObject.RequestThrow();
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 5e63651da7abbf744bc45585a2133e6f
@@ -9,6 +9,8 @@ public sealed class PlayerInteractionController : NetworkBehaviour, IPlayerSyste
private Camera playerCamera;
private IInteractable focusedInteractable;
private IPlayerInteractionSession activeSession;
private bool activeSessionReleaseRequested;
private bool isInitialized;
public void Initialize(PlayerFacade facade)
@@ -22,6 +24,23 @@ public sealed class PlayerInteractionController : NetworkBehaviour, IPlayerSyste
if (!isInitialized || !IsOwner || Keyboard.current == null)
return;
if (PlayerInteractionSessionRegistry.TryGetControlledSession(
OwnerClientId,
out activeSession))
{
focusedInteractable = null;
if (!Keyboard.current.eKey.isPressed && !activeSessionReleaseRequested)
{
activeSessionReleaseRequested = true;
activeSession.RequestRelease();
}
return;
}
activeSession = null;
activeSessionReleaseRequested = false;
focusedInteractable = FindFocusedInteractable();
if (Keyboard.current.eKey.wasPressedThisFrame &&
@@ -49,9 +68,26 @@ public sealed class PlayerInteractionController : NetworkBehaviour, IPlayerSyste
private void OnGUI()
{
if (!IsOwner || focusedInteractable == null)
if (!IsOwner)
return;
if (activeSession != null)
{
DrawPrompt(activeSession.ReleasePrompt);
return;
}
if (focusedInteractable == null)
return;
string prompt = focusedInteractable.IsInteractionAvailable
? "[E] " + focusedInteractable.InteractionPrompt
: "In use";
DrawPrompt(prompt);
}
private static void DrawPrompt(string prompt)
{
GUIStyle style = new(GUI.skin.label)
{
alignment = TextAnchor.MiddleCenter,
@@ -59,12 +95,7 @@ public sealed class PlayerInteractionController : NetworkBehaviour, IPlayerSyste
normal = { textColor = Color.white }
};
string prompt = focusedInteractable.IsInteractionAvailable
? "[E] " + focusedInteractable.InteractionPrompt
: "In use";
Rect area = new(0f, Screen.height * 0.62f, Screen.width, 28f);
GUI.Label(area, prompt, style);
}
}
File diff suppressed because one or more lines are too long
+15
View File
@@ -29,3 +29,18 @@ MonoBehaviour:
SourcePrefabToOverride: {fileID: 0}
SourceHashToOverride: 0
OverridingTargetPrefab: {fileID: 0}
- Override: 0
Prefab: {fileID: 5225331470301378431, guid: 8fce593e28d06e54d83ed63d9e60c3c0, type: 3}
SourcePrefabToOverride: {fileID: 0}
SourceHashToOverride: 0
OverridingTargetPrefab: {fileID: 0}
- Override: 0
Prefab: {fileID: 5225331470301378431, guid: 43c2ed447ed075a4c9bb39cb8b389c0e, type: 3}
SourcePrefabToOverride: {fileID: 0}
SourceHashToOverride: 0
OverridingTargetPrefab: {fileID: 0}
- Override: 0
Prefab: {fileID: 8815354352711425077, guid: 593b09321d7982e48a7d65a32da0d96a, type: 3}
SourcePrefabToOverride: {fileID: 0}
SourceHashToOverride: 0
OverridingTargetPrefab: {fileID: 0}