전장의 안개 기능 개선
미탐험 구역의 모든 오브젝트는 보이지 않음 적이 시야를 제공하는 문제 수정 높은 장애물은 더 먼 거리에서부터 보일 수 있음
This commit is contained in:
@@ -60,6 +60,7 @@
|
||||
<Compile Include="Assets\FlatKit\Shaders\GradientSkybox\Editor\GradientSkyboxEditor.cs" />
|
||||
<Compile Include="Assets\FlatKit\Shaders\Editor\Tooltips.cs" />
|
||||
<Compile Include="Assets\FlatKit\Shaders\Editor\StylizedSurfaceEditor.cs" />
|
||||
<Compile Include="Assets\Scripts\Editor\FogOfWarVisibilitySetup.cs" />
|
||||
<Compile Include="Assets\FlatKit\Shaders\Editor\MaterialPropertyExtensions.cs" />
|
||||
<Compile Include="Assets\FlatKit\Shaders\Editor\TerrainEditor.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Assets\Scripts\NetworkManagerUI.cs" />
|
||||
<Compile Include="Assets\Data\Scripts\DataClasses\WaveMasterData.cs" />
|
||||
<Compile Include="Assets\FlatKit\Demos\[Demo] Desert\Scripts\FloatingMotion.cs" />
|
||||
<Compile Include="Assets\Scripts\PlayerResourceInventory.cs" />
|
||||
<Compile Include="Assets\Scripts\ITeamMember.cs" />
|
||||
@@ -82,6 +83,7 @@
|
||||
<Compile Include="Assets\FlatKit\Demos\Common\Scripts\UvScroller.cs" />
|
||||
<Compile Include="Assets\Scripts\GlobalTimer.cs" />
|
||||
<Compile Include="Assets\InputSystem_Actions.cs" />
|
||||
<Compile Include="Assets\Data\Scripts\DataClasses\MonsterMasterData.cs" />
|
||||
<Compile Include="Assets\FlatKit\Demos\[Demo] Desert\Scripts\BillboardLineRendererCircle.cs" />
|
||||
<Compile Include="Assets\Scripts\BuildingHealthBar.cs" />
|
||||
<Compile Include="Assets\Scripts\PlayerSpawnPoint.cs" />
|
||||
@@ -100,6 +102,7 @@
|
||||
<Compile Include="Assets\Scripts\IAction.cs" />
|
||||
<Compile Include="Assets\Scripts\NetworkPlayerController.cs" />
|
||||
<Compile Include="Assets\Scripts\PlayerInteraction.cs" />
|
||||
<Compile Include="Assets\Scripts\FogOfWarVisibility.cs" />
|
||||
<Compile Include="Assets\Scripts\EnemyAIState.cs" />
|
||||
<Compile Include="Assets\Scripts\EquipmentData.cs" />
|
||||
<Compile Include="Assets\Scripts\NetworkConnectionHandler.cs" />
|
||||
|
||||
@@ -13,6 +13,7 @@ GameObject:
|
||||
- component: {fileID: 1287070985890992582}
|
||||
- component: {fileID: 2964705630284685173}
|
||||
- component: {fileID: 2236804103334722056}
|
||||
- component: {fileID: -7963177287827765112}
|
||||
m_Layer: 7
|
||||
m_Name: Core
|
||||
m_TagString: Untagged
|
||||
@@ -48,7 +49,7 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Unity.Netcode.Runtime::Unity.Netcode.NetworkObject
|
||||
GlobalObjectIdHash: 3998537868
|
||||
GlobalObjectIdHash: 615747208
|
||||
InScenePlacedSourceGlobalObjectIdHash: 615747208
|
||||
DeferredDespawnTick: 0
|
||||
Ownership: 1
|
||||
@@ -87,6 +88,9 @@ MonoBehaviour:
|
||||
equipmentPrefab: {fileID: 0}
|
||||
attachOnStart: 1
|
||||
detachOnEnd: 1
|
||||
keepEquipped: 0
|
||||
attachDelay: 0
|
||||
detachDelay: 0
|
||||
depositEffectPrefab: {fileID: 0}
|
||||
effectSpawnPoint: {fileID: 0}
|
||||
--- !u!114 &2964705630284685173
|
||||
@@ -136,6 +140,23 @@ BoxCollider:
|
||||
serializedVersion: 3
|
||||
m_Size: {x: 10, y: 10, z: 10}
|
||||
m_Center: {x: 0, y: 5, z: 0}
|
||||
--- !u!114 &-7963177287827765112
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8124290768227340041}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 760137a2fd0da7f458ac4b0ee7f485d6, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.FogOfWarVisibility
|
||||
showInExploredAreas: 1
|
||||
updateInterval: 0.2
|
||||
renderers: []
|
||||
useExploredMaterial: 0
|
||||
exploredMaterial: {fileID: 0}
|
||||
--- !u!1001 &1237105051606736037
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -78,6 +78,7 @@ GameObject:
|
||||
- component: {fileID: 6336968390548483685}
|
||||
- component: {fileID: 1893682255695519596}
|
||||
- component: {fileID: 2622677457934171119}
|
||||
- component: {fileID: 5472556851078681728}
|
||||
m_Layer: 9
|
||||
m_Name: Gate
|
||||
m_TagString: Untagged
|
||||
@@ -152,7 +153,7 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Unity.Netcode.Runtime::Unity.Netcode.NetworkObject
|
||||
GlobalObjectIdHash: 2819059600
|
||||
GlobalObjectIdHash: 1171432577
|
||||
InScenePlacedSourceGlobalObjectIdHash: 1171432577
|
||||
DeferredDespawnTick: 0
|
||||
Ownership: 1
|
||||
@@ -259,6 +260,23 @@ BoxCollider:
|
||||
serializedVersion: 3
|
||||
m_Size: {x: 8, y: 8, z: 1}
|
||||
m_Center: {x: 0, y: 0, z: 2}
|
||||
--- !u!114 &5472556851078681728
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2998551506809628252}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 760137a2fd0da7f458ac4b0ee7f485d6, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.FogOfWarVisibility
|
||||
showInExploredAreas: 1
|
||||
updateInterval: 0.2
|
||||
renderers: []
|
||||
useExploredMaterial: 0
|
||||
exploredMaterial: {fileID: 0}
|
||||
--- !u!1001 &665699090875585891
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -9,7 +9,8 @@ GameObject:
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 6371576195603730939}
|
||||
m_Layer: 0
|
||||
- component: {fileID: -3907047637289204963}
|
||||
m_Layer: 10
|
||||
m_Name: Rock1
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
@@ -32,6 +33,24 @@ Transform:
|
||||
- {fileID: 314330220483351248}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &-3907047637289204963
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7867287811520877109}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 760137a2fd0da7f458ac4b0ee7f485d6, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.FogOfWarVisibility
|
||||
showInExploredAreas: 1
|
||||
updateInterval: 0.2
|
||||
renderers: []
|
||||
debugLogging: 1
|
||||
useExploredMaterial: 0
|
||||
exploredMaterial: {fileID: 0}
|
||||
--- !u!1001 &276409350290535739
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -84,13 +103,47 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: Rock_1_K_Color1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 919132149155446097, guid: 084e4f5c77bba9b48becc0b4a57b6d07, type: 3}
|
||||
propertyPath: m_Layer
|
||||
value: 10
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_AddedComponents:
|
||||
- targetCorrespondingSourceObject: {fileID: 919132149155446097, guid: 084e4f5c77bba9b48becc0b4a57b6d07, type: 3}
|
||||
insertIndex: -1
|
||||
addedObject: {fileID: 5391599427288743647}
|
||||
m_SourcePrefab: {fileID: 100100000, guid: 084e4f5c77bba9b48becc0b4a57b6d07, type: 3}
|
||||
--- !u!4 &314330220483351248 stripped
|
||||
Transform:
|
||||
m_CorrespondingSourceObject: {fileID: -8679921383154817045, guid: 084e4f5c77bba9b48becc0b4a57b6d07, type: 3}
|
||||
m_PrefabInstance: {fileID: 276409350290535739}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!1 &1087453314165295210 stripped
|
||||
GameObject:
|
||||
m_CorrespondingSourceObject: {fileID: 919132149155446097, guid: 084e4f5c77bba9b48becc0b4a57b6d07, type: 3}
|
||||
m_PrefabInstance: {fileID: 276409350290535739}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!64 &5391599427288743647
|
||||
MeshCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1087453314165295210}
|
||||
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: 5
|
||||
m_Convex: 1
|
||||
m_CookingOptions: 30
|
||||
m_Mesh: {fileID: 7314371461370138683, guid: 084e4f5c77bba9b48becc0b4a57b6d07, type: 3}
|
||||
|
||||
@@ -9,7 +9,8 @@ GameObject:
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 5791990943856352332}
|
||||
m_Layer: 0
|
||||
- component: {fileID: 6386629597168169889}
|
||||
m_Layer: 10
|
||||
m_Name: Rock2
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
@@ -32,6 +33,24 @@ Transform:
|
||||
- {fileID: 1472743191925282593}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &6386629597168169889
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7245241003860522441}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 760137a2fd0da7f458ac4b0ee7f485d6, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.FogOfWarVisibility
|
||||
showInExploredAreas: 1
|
||||
updateInterval: 0.2
|
||||
renderers: []
|
||||
debugLogging: 1
|
||||
useExploredMaterial: 0
|
||||
exploredMaterial: {fileID: 0}
|
||||
--- !u!1001 &1439609661864653002
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -84,13 +103,47 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: Rock_1_E_Color1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 919132149155446097, guid: aba4f064ac8baf04580049a218a20437, type: 3}
|
||||
propertyPath: m_Layer
|
||||
value: 10
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_AddedComponents:
|
||||
- targetCorrespondingSourceObject: {fileID: 919132149155446097, guid: aba4f064ac8baf04580049a218a20437, type: 3}
|
||||
insertIndex: -1
|
||||
addedObject: {fileID: 8876585294901404683}
|
||||
m_SourcePrefab: {fileID: 100100000, guid: aba4f064ac8baf04580049a218a20437, type: 3}
|
||||
--- !u!4 &1472743191925282593 stripped
|
||||
Transform:
|
||||
m_CorrespondingSourceObject: {fileID: -8679921383154817045, guid: aba4f064ac8baf04580049a218a20437, type: 3}
|
||||
m_PrefabInstance: {fileID: 1439609661864653002}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!1 &2250652532536020379 stripped
|
||||
GameObject:
|
||||
m_CorrespondingSourceObject: {fileID: 919132149155446097, guid: aba4f064ac8baf04580049a218a20437, type: 3}
|
||||
m_PrefabInstance: {fileID: 1439609661864653002}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!64 &8876585294901404683
|
||||
MeshCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2250652532536020379}
|
||||
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: 5
|
||||
m_Convex: 1
|
||||
m_CookingOptions: 30
|
||||
m_Mesh: {fileID: 7799962653386975686, guid: aba4f064ac8baf04580049a218a20437, type: 3}
|
||||
|
||||
@@ -9,7 +9,8 @@ GameObject:
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 5832127839780190644}
|
||||
m_Layer: 0
|
||||
- component: {fileID: 6163423706184354979}
|
||||
m_Layer: 10
|
||||
m_Name: Rock3
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
@@ -32,6 +33,24 @@ Transform:
|
||||
- {fileID: 8122136182644622076}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &6163423706184354979
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7773749726967315046}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 760137a2fd0da7f458ac4b0ee7f485d6, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.FogOfWarVisibility
|
||||
showInExploredAreas: 1
|
||||
updateInterval: 0.2
|
||||
renderers: []
|
||||
debugLogging: 1
|
||||
useExploredMaterial: 0
|
||||
exploredMaterial: {fileID: 0}
|
||||
--- !u!1001 &8592066193955497239
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -84,13 +103,47 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: Rock_1_M_Color1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 919132149155446097, guid: d6003d5fcbb3d9447ad32f79faa595ae, type: 3}
|
||||
propertyPath: m_Layer
|
||||
value: 10
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_AddedComponents:
|
||||
- targetCorrespondingSourceObject: {fileID: 919132149155446097, guid: d6003d5fcbb3d9447ad32f79faa595ae, type: 3}
|
||||
insertIndex: -1
|
||||
addedObject: {fileID: 7064843664758881414}
|
||||
m_SourcePrefab: {fileID: 100100000, guid: d6003d5fcbb3d9447ad32f79faa595ae, type: 3}
|
||||
--- !u!4 &8122136182644622076 stripped
|
||||
Transform:
|
||||
m_CorrespondingSourceObject: {fileID: -8679921383154817045, guid: d6003d5fcbb3d9447ad32f79faa595ae, type: 3}
|
||||
m_PrefabInstance: {fileID: 8592066193955497239}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!1 &8934103170449217606 stripped
|
||||
GameObject:
|
||||
m_CorrespondingSourceObject: {fileID: 919132149155446097, guid: d6003d5fcbb3d9447ad32f79faa595ae, type: 3}
|
||||
m_PrefabInstance: {fileID: 8592066193955497239}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!64 &7064843664758881414
|
||||
MeshCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8934103170449217606}
|
||||
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: 5
|
||||
m_Convex: 1
|
||||
m_CookingOptions: 30
|
||||
m_Mesh: {fileID: -675721469606841765, guid: d6003d5fcbb3d9447ad32f79faa595ae, type: 3}
|
||||
|
||||
@@ -9,7 +9,9 @@ GameObject:
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 7011000049316995908}
|
||||
m_Layer: 0
|
||||
- component: {fileID: 1948217933253124379}
|
||||
- component: {fileID: 1861572095783484933}
|
||||
m_Layer: 10
|
||||
m_Name: Tree1
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
@@ -32,6 +34,45 @@ Transform:
|
||||
- {fileID: 6530377170908411445}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!65 &1948217933253124379
|
||||
BoxCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1559926009631082787}
|
||||
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: 0.5, y: 10, z: 0.5}
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &1861572095783484933
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1559926009631082787}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 760137a2fd0da7f458ac4b0ee7f485d6, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.FogOfWarVisibility
|
||||
showInExploredAreas: 1
|
||||
updateInterval: 0.2
|
||||
renderers: []
|
||||
debugLogging: 1
|
||||
useExploredMaterial: 0
|
||||
exploredMaterial: {fileID: 0}
|
||||
--- !u!1001 &6713237626157896158
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -84,6 +125,10 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: Tree_2_A_Color1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 919132149155446097, guid: 308f3ac9346795e41acc026a7f417f0c, type: 3}
|
||||
propertyPath: m_Layer
|
||||
value: 10
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
|
||||
@@ -9,7 +9,9 @@ GameObject:
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 2594114534543661658}
|
||||
m_Layer: 0
|
||||
- component: {fileID: 6161783292885910878}
|
||||
- component: {fileID: 5630203293812958152}
|
||||
m_Layer: 10
|
||||
m_Name: Tree2
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
@@ -32,6 +34,45 @@ Transform:
|
||||
- {fileID: 7851729353721699034}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!65 &6161783292885910878
|
||||
BoxCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4345146930867537194}
|
||||
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: 0.6, y: 10, z: 0.6}
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &5630203293812958152
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4345146930867537194}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 760137a2fd0da7f458ac4b0ee7f485d6, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.FogOfWarVisibility
|
||||
showInExploredAreas: 1
|
||||
updateInterval: 0.2
|
||||
renderers: []
|
||||
debugLogging: 1
|
||||
useExploredMaterial: 0
|
||||
exploredMaterial: {fileID: 0}
|
||||
--- !u!1001 &7745148207212772657
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -42,7 +83,7 @@ PrefabInstance:
|
||||
m_Modifications:
|
||||
- target: {fileID: -8679921383154817045, guid: f8d701cc811c2074dbddce4df7348e70, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 1.17
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -8679921383154817045, guid: f8d701cc811c2074dbddce4df7348e70, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
@@ -84,6 +125,10 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: Tree_2_D_Color1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 919132149155446097, guid: f8d701cc811c2074dbddce4df7348e70, type: 3}
|
||||
propertyPath: m_Layer
|
||||
value: 10
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
|
||||
@@ -13,6 +13,7 @@ GameObject:
|
||||
- component: {fileID: 2599592318476693256}
|
||||
- component: {fileID: 1907881863544148932}
|
||||
- component: {fileID: 3214893598090363914}
|
||||
- component: {fileID: 9023294375343742146}
|
||||
m_Layer: 9
|
||||
m_Name: Wall
|
||||
m_TagString: Untagged
|
||||
@@ -124,6 +125,23 @@ MonoBehaviour:
|
||||
effectSpawnPoint: {fileID: 0}
|
||||
showGridBounds: 1
|
||||
gridBoundsColor: {r: 0, g: 1, b: 1, a: 1}
|
||||
--- !u!114 &9023294375343742146
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 351020651857757465}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 760137a2fd0da7f458ac4b0ee7f485d6, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.FogOfWarVisibility
|
||||
showInExploredAreas: 1
|
||||
updateInterval: 0.2
|
||||
renderers: []
|
||||
useExploredMaterial: 0
|
||||
exploredMaterial: {fileID: 0}
|
||||
--- !u!1001 &8926581783111832504
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -1504,6 +1504,15 @@ MonoBehaviour:
|
||||
cellSize: 1
|
||||
worldOrigin: {x: -50, y: 0, z: -200}
|
||||
updateInterval: 0.2
|
||||
enableLineOfSight: 1
|
||||
visionBlockingLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
raycastAngularStep: 6
|
||||
useDetailedRaycasting: 0
|
||||
enableHeightBlocking: 1
|
||||
viewerEyeHeight: 1.5
|
||||
minBlockingHeight: 2
|
||||
--- !u!4 &946527919
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -1999,6 +2008,29 @@ Transform:
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &1277246857 stripped
|
||||
GameObject:
|
||||
m_CorrespondingSourceObject: {fileID: 8774623643640324048, guid: c92c9f1bf0ae6364f85409ecdc4aeaf3, type: 3}
|
||||
m_PrefabInstance: {fileID: 2264374033617737844}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!114 &1277246864
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1277246857}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 760137a2fd0da7f458ac4b0ee7f485d6, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.FogOfWarVisibility
|
||||
showInExploredAreas: 0
|
||||
updateInterval: 0.2
|
||||
renderers: []
|
||||
debugLogging: 0
|
||||
useExploredMaterial: 0
|
||||
exploredMaterial: {fileID: 0}
|
||||
--- !u!1 &1433142230
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -2418,7 +2450,7 @@ MonoBehaviour:
|
||||
serializedVersion: 2
|
||||
m_Bits: 896
|
||||
collisionCheckRadius: 1
|
||||
spawnOnStart: 1
|
||||
spawnOnStart: 0
|
||||
groupUnderParent: 1
|
||||
--- !u!4 &1572384099
|
||||
Transform:
|
||||
@@ -2849,6 +2881,63 @@ Transform:
|
||||
m_CorrespondingSourceObject: {fileID: 5749230937810543840, guid: 88f7f1e8a019b674498ab5fd494c1d34, type: 3}
|
||||
m_PrefabInstance: {fileID: 1862165056}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!1001 &1912551706
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications:
|
||||
- target: {fileID: 5791990943856352332, guid: 2c33c67d086286d4a929d533b4e26863, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: -8.854406
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5791990943856352332, guid: 2c33c67d086286d4a929d533b4e26863, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 1.0000119
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5791990943856352332, guid: 2c33c67d086286d4a929d533b4e26863, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: -60.088272
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5791990943856352332, guid: 2c33c67d086286d4a929d533b4e26863, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5791990943856352332, guid: 2c33c67d086286d4a929d533b4e26863, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5791990943856352332, guid: 2c33c67d086286d4a929d533b4e26863, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5791990943856352332, guid: 2c33c67d086286d4a929d533b4e26863, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5791990943856352332, guid: 2c33c67d086286d4a929d533b4e26863, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5791990943856352332, guid: 2c33c67d086286d4a929d533b4e26863, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5791990943856352332, guid: 2c33c67d086286d4a929d533b4e26863, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7245241003860522441, guid: 2c33c67d086286d4a929d533b4e26863, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: Rock2
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: 2c33c67d086286d4a929d533b4e26863, type: 3}
|
||||
--- !u!1001 &1975225896
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -3122,7 +3211,10 @@ PrefabInstance:
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_AddedComponents:
|
||||
- targetCorrespondingSourceObject: {fileID: 8774623643640324048, guid: c92c9f1bf0ae6364f85409ecdc4aeaf3, type: 3}
|
||||
insertIndex: -1
|
||||
addedObject: {fileID: 1277246864}
|
||||
m_SourcePrefab: {fileID: 100100000, guid: c92c9f1bf0ae6364f85409ecdc4aeaf3, type: 3}
|
||||
--- !u!1001 &2588157855179843872
|
||||
PrefabInstance:
|
||||
@@ -3564,3 +3656,4 @@ SceneRoots:
|
||||
- {fileID: 1442785555}
|
||||
- {fileID: 1440648431994998967}
|
||||
- {fileID: 1061936651}
|
||||
- {fileID: 1912551706}
|
||||
|
||||
@@ -205,6 +205,14 @@ namespace Northbound
|
||||
GameObject buildingObj = Instantiate(data.prefab, snappedPosition + data.placementOffset, Quaternion.Euler(0, rotation * 90f, 0));
|
||||
NetworkObject netObj = buildingObj.GetComponent<NetworkObject>();
|
||||
|
||||
// Add FogOfWarVisibility component to hide buildings in unexplored areas
|
||||
if (buildingObj.GetComponent<FogOfWarVisibility>() == null)
|
||||
{
|
||||
var visibility = buildingObj.AddComponent<FogOfWarVisibility>();
|
||||
visibility.showInExploredAreas = true; // Buildings remain visible in explored areas
|
||||
visibility.updateInterval = 0.2f;
|
||||
}
|
||||
|
||||
if (netObj != null)
|
||||
{
|
||||
// 건물의 소유자를 설정
|
||||
@@ -359,6 +367,14 @@ namespace Northbound
|
||||
GameObject foundationObj = Instantiate(foundationPrefab, snappedPosition + data.placementOffset, Quaternion.Euler(0, rotation * 90f, 0));
|
||||
NetworkObject netObj = foundationObj.GetComponent<NetworkObject>();
|
||||
|
||||
// Add FogOfWarVisibility component to hide foundations in unexplored areas
|
||||
if (foundationObj.GetComponent<FogOfWarVisibility>() == null)
|
||||
{
|
||||
var visibility = foundationObj.AddComponent<FogOfWarVisibility>();
|
||||
visibility.showInExploredAreas = true; // Foundations remain visible in explored areas
|
||||
visibility.updateInterval = 0.2f;
|
||||
}
|
||||
|
||||
if (netObj != null)
|
||||
{
|
||||
netObj.SpawnWithOwnership(requestingClientId);
|
||||
@@ -425,6 +441,14 @@ namespace Northbound
|
||||
GameObject buildingObj = Instantiate(data.prefab, worldPosition + data.placementOffset, Quaternion.Euler(0, rotation * 90f, 0));
|
||||
NetworkObject netObj = buildingObj.GetComponent<NetworkObject>();
|
||||
|
||||
// Add FogOfWarVisibility component to hide buildings in unexplored areas
|
||||
if (buildingObj.GetComponent<FogOfWarVisibility>() == null)
|
||||
{
|
||||
var visibility = buildingObj.AddComponent<FogOfWarVisibility>();
|
||||
visibility.showInExploredAreas = true; // Buildings remain visible in explored areas
|
||||
visibility.updateInterval = 0.2f;
|
||||
}
|
||||
|
||||
if (netObj != null)
|
||||
{
|
||||
netObj.SpawnWithOwnership(ownerId);
|
||||
|
||||
170
Assets/Scripts/Editor/FogOfWarVisibilitySetup.cs
Normal file
170
Assets/Scripts/Editor/FogOfWarVisibilitySetup.cs
Normal file
@@ -0,0 +1,170 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace Northbound.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// Editor utility to add FogOfWarVisibility to all obstacles and buildings
|
||||
/// </summary>
|
||||
public static class FogOfWarVisibilitySetup
|
||||
{
|
||||
[MenuItem("Tools/Fog of War/Add Visibility to All Obstacles")]
|
||||
public static void AddVisibilityToObstacles()
|
||||
{
|
||||
string[] obstaclePaths = new string[]
|
||||
{
|
||||
"Assets/Prefabs/Obstacles/Rock1.prefab",
|
||||
"Assets/Prefabs/Obstacles/Rock2.prefab",
|
||||
"Assets/Prefabs/Obstacles/Rock3.prefab",
|
||||
"Assets/Prefabs/Obstacles/Tree1.prefab",
|
||||
"Assets/Prefabs/Obstacles/Tree2.prefab"
|
||||
};
|
||||
|
||||
int count = 0;
|
||||
foreach (string path in obstaclePaths)
|
||||
{
|
||||
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
|
||||
if (prefab != null)
|
||||
{
|
||||
// Check if already has component
|
||||
if (prefab.GetComponent<FogOfWarVisibility>() == null)
|
||||
{
|
||||
// Add component
|
||||
var visibility = prefab.AddComponent<FogOfWarVisibility>();
|
||||
visibility.showInExploredAreas = false; // Hide obstacles when not visible
|
||||
visibility.updateInterval = 0.2f;
|
||||
|
||||
EditorUtility.SetDirty(prefab);
|
||||
count++;
|
||||
Debug.Log($"Added FogOfWarVisibility to {prefab.name}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log($"{prefab.name} already has FogOfWarVisibility");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"Could not find prefab at {path}");
|
||||
}
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
Debug.Log($"<color=green>FogOfWarVisibility added to {count} obstacle prefabs!</color>");
|
||||
}
|
||||
|
||||
[MenuItem("Tools/Fog of War/Add Visibility to All Buildings")]
|
||||
public static void AddVisibilityToBuildings()
|
||||
{
|
||||
// Find all Building prefabs
|
||||
string[] guids = AssetDatabase.FindAssets("t:Prefab", new[] { "Assets/Prefabs" });
|
||||
|
||||
int count = 0;
|
||||
foreach (string guid in guids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
|
||||
|
||||
if (prefab != null && prefab.GetComponent<Building>() != null)
|
||||
{
|
||||
// Check if already has component
|
||||
if (prefab.GetComponent<FogOfWarVisibility>() == null)
|
||||
{
|
||||
var visibility = prefab.AddComponent<FogOfWarVisibility>();
|
||||
visibility.showInExploredAreas = true; // Show buildings in explored areas (greyed out)
|
||||
visibility.updateInterval = 0.2f;
|
||||
|
||||
EditorUtility.SetDirty(prefab);
|
||||
count++;
|
||||
Debug.Log($"Added FogOfWarVisibility to building: {prefab.name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
Debug.Log($"<color=green>FogOfWarVisibility added to {count} building prefabs!</color>");
|
||||
}
|
||||
|
||||
[MenuItem("Tools/Fog of War/Add Visibility to Scene Obstacles")]
|
||||
public static void AddVisibilityToSceneObstacles()
|
||||
{
|
||||
GameObject[] allObjects = GameObject.FindObjectsOfType<GameObject>();
|
||||
int count = 0;
|
||||
|
||||
foreach (GameObject obj in allObjects)
|
||||
{
|
||||
// Skip if it's a prefab instance - those will be handled by prefab updates
|
||||
if (PrefabUtility.IsPartOfPrefabInstance(obj))
|
||||
continue;
|
||||
|
||||
// Check if it has renderers but no FogOfWarVisibility
|
||||
if (obj.GetComponent<Renderer>() != null && obj.GetComponent<FogOfWarVisibility>() == null)
|
||||
{
|
||||
// Check if it's an obstacle (has MeshCollider and no other components)
|
||||
if (obj.name.Contains("Rock") || obj.name.Contains("Tree") || obj.name.Contains("Obstacle"))
|
||||
{
|
||||
var visibility = obj.AddComponent<FogOfWarVisibility>();
|
||||
visibility.showInExploredAreas = false;
|
||||
visibility.updateInterval = 0.2f;
|
||||
|
||||
EditorUtility.SetDirty(obj);
|
||||
count++;
|
||||
Debug.Log($"Added FogOfWarVisibility to scene object: {obj.name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log($"<color=green>FogOfWarVisibility added to {count} scene objects!</color>");
|
||||
}
|
||||
|
||||
[MenuItem("Tools/Fog of War/Remove Visibility from All")]
|
||||
public static void RemoveVisibilityFromAll()
|
||||
{
|
||||
if (!EditorUtility.DisplayDialog("Remove FogOfWarVisibility",
|
||||
"This will remove FogOfWarVisibility from all prefabs and scene objects. Continue?",
|
||||
"Yes", "Cancel"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove from prefabs
|
||||
string[] guids = AssetDatabase.FindAssets("t:Prefab", new[] { "Assets/Prefabs" });
|
||||
int prefabCount = 0;
|
||||
|
||||
foreach (string guid in guids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
|
||||
|
||||
if (prefab != null)
|
||||
{
|
||||
var visibility = prefab.GetComponent<FogOfWarVisibility>();
|
||||
if (visibility != null)
|
||||
{
|
||||
Object.DestroyImmediate(visibility, true);
|
||||
EditorUtility.SetDirty(prefab);
|
||||
prefabCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove from scene objects
|
||||
FogOfWarVisibility[] sceneComponents = GameObject.FindObjectsOfType<FogOfWarVisibility>();
|
||||
int sceneCount = sceneComponents.Length;
|
||||
|
||||
foreach (var comp in sceneComponents)
|
||||
{
|
||||
Object.DestroyImmediate(comp);
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
Debug.Log($"<color=yellow>Removed FogOfWarVisibility from {prefabCount} prefabs and {sceneCount} scene objects</color>");
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Editor/FogOfWarVisibilitySetup.cs.meta
Normal file
2
Assets/Scripts/Editor/FogOfWarVisibilitySetup.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5d15a430ea206c447ad60e74293d5dc1
|
||||
@@ -22,6 +22,15 @@ public class EnemyPortal : MonoBehaviour
|
||||
foreach (GameObject obj in Enemies)
|
||||
{
|
||||
GameObject enemy = Instantiate(obj, transform);
|
||||
|
||||
// Add FogOfWarVisibility component to hide enemies in unexplored areas
|
||||
if (enemy.GetComponent<FogOfWarVisibility>() == null)
|
||||
{
|
||||
var visibility = enemy.AddComponent<FogOfWarVisibility>();
|
||||
visibility.showInExploredAreas = false; // Enemies hidden when not visible
|
||||
visibility.updateInterval = 0.2f;
|
||||
}
|
||||
|
||||
enemy.GetComponent<NetworkObject>().Spawn();
|
||||
Debug.Log(enemy);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Northbound
|
||||
/// 적대 유닛 (적대세력 또는 몬스터)
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(Collider))]
|
||||
public class EnemyUnit : NetworkBehaviour, IDamageable, ITeamMember, IVisionProvider
|
||||
public class EnemyUnit : NetworkBehaviour, IDamageable, ITeamMember
|
||||
{
|
||||
[Header("Team Settings")]
|
||||
[Tooltip("이 유닛의 팀 (Hostile = 적대세력, Monster = 몬스터)")]
|
||||
@@ -15,7 +15,6 @@ namespace Northbound
|
||||
|
||||
[Header("Combat")]
|
||||
public int maxHealth = 100;
|
||||
public float visionRange = 10f;
|
||||
|
||||
[Header("Visual")]
|
||||
public GameObject damageEffectPrefab;
|
||||
@@ -41,20 +40,12 @@ namespace Northbound
|
||||
{
|
||||
_currentHealth.Value = maxHealth;
|
||||
_team.Value = enemyTeam;
|
||||
|
||||
// FogOfWar 시스템에 등록
|
||||
FogOfWarSystem.Instance?.RegisterVisionProvider(this);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnNetworkDespawn()
|
||||
{
|
||||
base.OnNetworkDespawn();
|
||||
|
||||
if (IsServer)
|
||||
{
|
||||
FogOfWarSystem.Instance?.UnregisterVisionProvider(this);
|
||||
}
|
||||
}
|
||||
|
||||
#region IDamageable Implementation
|
||||
@@ -97,9 +88,6 @@ namespace Northbound
|
||||
// 파괴 이펙트
|
||||
ShowDestroyEffectClientRpc();
|
||||
|
||||
// FogOfWar 시스템에서 제거
|
||||
FogOfWarSystem.Instance?.UnregisterVisionProvider(this);
|
||||
|
||||
// 네트워크 오브젝트 파괴
|
||||
Invoke(nameof(DespawnUnit), 0.5f);
|
||||
}
|
||||
@@ -146,28 +134,8 @@ namespace Northbound
|
||||
|
||||
#endregion
|
||||
|
||||
#region IVisionProvider Implementation
|
||||
|
||||
public ulong GetOwnerId() => OwnerClientId;
|
||||
|
||||
public float GetVisionRange() => visionRange;
|
||||
|
||||
public Transform GetTransform() => transform;
|
||||
|
||||
public bool IsActive() => IsSpawned && _currentHealth.Value > 0;
|
||||
|
||||
#endregion
|
||||
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
// 팀 색상으로 시야 범위 표시
|
||||
Color teamColor = Application.isPlaying
|
||||
? TeamManager.GetTeamColor(_team.Value)
|
||||
: TeamManager.GetTeamColor(enemyTeam);
|
||||
|
||||
Gizmos.color = new Color(teamColor.r, teamColor.g, teamColor.b, 0.3f);
|
||||
Gizmos.DrawWireSphere(transform.position, visionRange);
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
|
||||
@@ -14,6 +14,14 @@ namespace Northbound
|
||||
public float updateInterval = 0.1f;
|
||||
public float fogHeight = 5f; // 안개 높이 (지형보다 약간 위)
|
||||
|
||||
[Header("Smoothing")]
|
||||
[Tooltip("Enable smooth circular vision edges")]
|
||||
public bool enableSmoothing = true;
|
||||
|
||||
[Tooltip("Smoothing strength (higher = smoother but more blurry)")]
|
||||
[Range(1, 5)]
|
||||
public int smoothingPasses = 2;
|
||||
|
||||
[Header("Colors")]
|
||||
public Color unexploredColor = new Color(0, 0, 0, 1f); // 완전히 어두움
|
||||
public Color exploredColor = new Color(0, 0, 0, 0.6f); // 반투명
|
||||
@@ -51,11 +59,12 @@ namespace Northbound
|
||||
return;
|
||||
}
|
||||
|
||||
// 텍스처 생성
|
||||
// 텍스처 생성 (Bilinear filtering for smooth edges)
|
||||
_fogTexture = new Texture2D(fogSystem.gridWidth, fogSystem.gridHeight)
|
||||
{
|
||||
filterMode = FilterMode.Bilinear,
|
||||
wrapMode = TextureWrapMode.Clamp
|
||||
wrapMode = TextureWrapMode.Clamp,
|
||||
anisoLevel = 0 // Disable anisotropic filtering for fog overlay
|
||||
};
|
||||
_colors = new Color[fogSystem.gridWidth * fogSystem.gridHeight];
|
||||
|
||||
@@ -133,10 +142,66 @@ namespace Northbound
|
||||
}
|
||||
}
|
||||
|
||||
// Apply smoothing if enabled
|
||||
if (enableSmoothing)
|
||||
{
|
||||
SmoothFogTexture(fogSystem.gridWidth, fogSystem.gridHeight);
|
||||
}
|
||||
|
||||
_fogTexture.SetPixels(_colors);
|
||||
_fogTexture.Apply();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply box blur smoothing to create smooth circular vision edges
|
||||
/// </summary>
|
||||
private void SmoothFogTexture(int width, int height)
|
||||
{
|
||||
Color[] smoothed = new Color[_colors.Length];
|
||||
|
||||
for (int pass = 0; pass < smoothingPasses; pass++)
|
||||
{
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
int index = y * width + x;
|
||||
|
||||
// Box blur: average with neighbors
|
||||
float r = 0, g = 0, b = 0, a = 0;
|
||||
int samples = 0;
|
||||
|
||||
// Sample 3x3 kernel
|
||||
for (int dy = -1; dy <= 1; dy++)
|
||||
{
|
||||
for (int dx = -1; dx <= 1; dx++)
|
||||
{
|
||||
int nx = x + dx;
|
||||
int ny = y + dy;
|
||||
|
||||
if (nx >= 0 && nx < width && ny >= 0 && ny < height)
|
||||
{
|
||||
int nIndex = ny * width + nx;
|
||||
Color c = _colors[nIndex];
|
||||
r += c.r;
|
||||
g += c.g;
|
||||
b += c.b;
|
||||
a += c.a;
|
||||
samples++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Average
|
||||
smoothed[index] = new Color(r / samples, g / samples, b / samples, a / samples);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy smoothed back to colors for next pass
|
||||
System.Array.Copy(smoothed, _colors, _colors.Length);
|
||||
}
|
||||
}
|
||||
|
||||
private void CreatePlaneMesh(FogOfWarSystem fogSystem)
|
||||
{
|
||||
MeshFilter meshFilter = GetComponent<MeshFilter>();
|
||||
|
||||
@@ -4,6 +4,179 @@ using UnityEngine;
|
||||
|
||||
namespace Northbound
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper class for efficient line-of-sight calculations using sector-based raycasting
|
||||
/// </summary>
|
||||
public class LineOfSightCalculator
|
||||
{
|
||||
private struct SectorData
|
||||
{
|
||||
public float angle; // Angle in degrees (0-360)
|
||||
public float blockedDistance; // Distance where vision is blocked (float.MaxValue if clear)
|
||||
public bool hasObstacle; // True if this sector has an obstacle
|
||||
public float obstacleHeight; // Height of blocking obstacle
|
||||
public Vector3 obstaclePosition; // World position of obstacle hit point
|
||||
}
|
||||
|
||||
private FogOfWarSystem _fogSystem;
|
||||
private SectorData[] _sectors;
|
||||
private int _sectorCount;
|
||||
|
||||
public LineOfSightCalculator(FogOfWarSystem fogSystem)
|
||||
{
|
||||
_fogSystem = fogSystem;
|
||||
RecalculateSectors();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recalculate sector count based on angular step
|
||||
/// </summary>
|
||||
public void RecalculateSectors()
|
||||
{
|
||||
_sectorCount = Mathf.CeilToInt(360f / _fogSystem.raycastAngularStep);
|
||||
_sectors = new SectorData[_sectorCount];
|
||||
|
||||
for (int i = 0; i < _sectorCount; i++)
|
||||
{
|
||||
_sectors[i].angle = i * _fogSystem.raycastAngularStep;
|
||||
_sectors[i].blockedDistance = float.MaxValue;
|
||||
_sectors[i].hasObstacle = false;
|
||||
_sectors[i].obstacleHeight = 0f;
|
||||
_sectors[i].obstaclePosition = Vector3.zero;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform raycasting to determine blocked sectors with height awareness
|
||||
/// </summary>
|
||||
public void CalculateVisibleSectors(Vector3 viewerPosition, float visionRange)
|
||||
{
|
||||
// Reset sectors
|
||||
for (int i = 0; i < _sectorCount; i++)
|
||||
{
|
||||
_sectors[i].blockedDistance = float.MaxValue;
|
||||
_sectors[i].hasObstacle = false;
|
||||
_sectors[i].obstacleHeight = 0f;
|
||||
_sectors[i].obstaclePosition = Vector3.zero;
|
||||
}
|
||||
|
||||
// Raycast origin at viewer eye height
|
||||
Vector3 rayOrigin = viewerPosition + Vector3.up * _fogSystem.viewerEyeHeight;
|
||||
|
||||
for (int i = 0; i < _sectorCount; i++)
|
||||
{
|
||||
float angleRad = _sectors[i].angle * Mathf.Deg2Rad;
|
||||
Vector3 direction = new Vector3(Mathf.Cos(angleRad), 0, Mathf.Sin(angleRad));
|
||||
|
||||
if (Physics.Raycast(rayOrigin, direction, out RaycastHit hit, visionRange, _fogSystem.visionBlockingLayers))
|
||||
{
|
||||
_sectors[i].blockedDistance = hit.distance;
|
||||
_sectors[i].hasObstacle = true;
|
||||
_sectors[i].obstaclePosition = hit.point;
|
||||
|
||||
// Determine obstacle height
|
||||
if (_fogSystem.enableHeightBlocking)
|
||||
{
|
||||
_sectors[i].obstacleHeight = GetObstacleHeight(hit.collider);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the height of an obstacle for vision blocking calculations
|
||||
/// </summary>
|
||||
private float GetObstacleHeight(Collider obstacle)
|
||||
{
|
||||
// Check if it's a building
|
||||
Building building = obstacle.GetComponent<Building>();
|
||||
if (building != null && building.buildingData != null)
|
||||
{
|
||||
return building.buildingData.height;
|
||||
}
|
||||
|
||||
// For non-buildings (rocks, trees, terrain), use collider bounds
|
||||
return obstacle.bounds.size.y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if a grid cell is visible from viewer position (with height awareness)
|
||||
/// </summary>
|
||||
public bool IsCellVisible(Vector3 viewerPosition, Vector2Int cellGridPos, float visionRange)
|
||||
{
|
||||
Vector3 cellWorldPos = _fogSystem.GridToWorld(cellGridPos.x, cellGridPos.y);
|
||||
|
||||
Vector3 viewerEye = viewerPosition + Vector3.up * _fogSystem.viewerEyeHeight;
|
||||
Vector3 toCell = cellWorldPos - viewerPosition;
|
||||
float horizontalDistance = new Vector2(toCell.x, toCell.z).magnitude;
|
||||
|
||||
// Outside vision range
|
||||
if (horizontalDistance > visionRange)
|
||||
return false;
|
||||
|
||||
// Calculate angle to cell
|
||||
float angle = Mathf.Atan2(toCell.z, toCell.x) * Mathf.Rad2Deg;
|
||||
if (angle < 0) angle += 360f;
|
||||
|
||||
// Find corresponding sector
|
||||
int sectorIndex = Mathf.FloorToInt(angle / _fogSystem.raycastAngularStep) % _sectorCount;
|
||||
|
||||
// Check if blocked by obstacle in this sector
|
||||
if (_sectors[sectorIndex].hasObstacle)
|
||||
{
|
||||
// Dynamic tolerance to handle large mesh colliders
|
||||
// Large rocks can be hit several units before their center
|
||||
// Use cell size + generous buffer for very large obstacles
|
||||
float distanceTolerance = _fogSystem.cellSize * 5.0f + 3.0f;
|
||||
|
||||
// Height-based blocking check
|
||||
if (_fogSystem.enableHeightBlocking && _sectors[sectorIndex].obstacleHeight >= _fogSystem.minBlockingHeight)
|
||||
{
|
||||
float obstacleDistance = _sectors[sectorIndex].blockedDistance;
|
||||
|
||||
// If cell is beyond obstacle (with tolerance), check if obstacle blocks the sight line
|
||||
if (horizontalDistance > obstacleDistance + distanceTolerance)
|
||||
{
|
||||
// Calculate sight line angle to cell
|
||||
float verticalAngleToCell = Mathf.Atan2(cellWorldPos.y - viewerEye.y, horizontalDistance);
|
||||
|
||||
// Calculate obstacle top height
|
||||
float obstacleTopHeight = _sectors[sectorIndex].obstaclePosition.y + _sectors[sectorIndex].obstacleHeight;
|
||||
|
||||
// Calculate angle to obstacle top
|
||||
float verticalAngleToObstacleTop = Mathf.Atan2(obstacleTopHeight - viewerEye.y, obstacleDistance);
|
||||
|
||||
// If sight line passes below obstacle top, it's blocked
|
||||
if (verticalAngleToCell <= verticalAngleToObstacleTop)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Simple distance-based blocking (no height consideration)
|
||||
// Use tolerance to allow objects at the obstacle position to be visible
|
||||
if (horizontalDistance > _sectors[sectorIndex].blockedDistance + distanceTolerance)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Detailed raycasting for edge cases
|
||||
if (_fogSystem.useDetailedRaycasting)
|
||||
{
|
||||
float distanceTolerance = _fogSystem.cellSize * 3.0f + 2.0f;
|
||||
int prevSector = (sectorIndex - 1 + _sectorCount) % _sectorCount;
|
||||
int nextSector = (sectorIndex + 1) % _sectorCount;
|
||||
|
||||
if (_sectors[prevSector].hasObstacle && horizontalDistance > _sectors[prevSector].blockedDistance + distanceTolerance)
|
||||
return false;
|
||||
if (_sectors[nextSector].hasObstacle && horizontalDistance > _sectors[nextSector].blockedDistance + distanceTolerance)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 전장의 안개 시스템 - 플레이어별 시야 관리
|
||||
/// </summary>
|
||||
@@ -19,7 +192,31 @@ namespace Northbound
|
||||
|
||||
[Header("Visibility Settings")]
|
||||
public float updateInterval = 0.2f;
|
||||
|
||||
|
||||
[Header("Line of Sight Settings")]
|
||||
[Tooltip("Enable line-of-sight blocking by obstacles")]
|
||||
public bool enableLineOfSight = true;
|
||||
|
||||
[Tooltip("Layers that block vision (buildings, obstacles, terrain)")]
|
||||
public LayerMask visionBlockingLayers = ~0;
|
||||
|
||||
[Tooltip("Angular resolution for raycasting (degrees). Lower = more accurate, higher = better performance")]
|
||||
[Range(1f, 15f)]
|
||||
public float raycastAngularStep = 6f;
|
||||
|
||||
[Tooltip("Use detailed raycasting (more accurate but slower)")]
|
||||
public bool useDetailedRaycasting = false;
|
||||
|
||||
[Header("Height-Based Visibility")]
|
||||
[Tooltip("Enable height-based vision blocking (tall obstacles block vision)")]
|
||||
public bool enableHeightBlocking = true;
|
||||
|
||||
[Tooltip("Viewer eye height for line-of-sight calculations")]
|
||||
public float viewerEyeHeight = 1.5f;
|
||||
|
||||
[Tooltip("Minimum obstacle height to block vision")]
|
||||
public float minBlockingHeight = 2.0f;
|
||||
|
||||
// 서버: 각 플레이어별 가시성 맵
|
||||
private Dictionary<ulong, FogOfWarData> _serverFogData = new Dictionary<ulong, FogOfWarData>();
|
||||
|
||||
@@ -28,6 +225,7 @@ namespace Northbound
|
||||
|
||||
private List<IVisionProvider> _visionProviders = new List<IVisionProvider>();
|
||||
private float _updateTimer;
|
||||
private LineOfSightCalculator _losCalculator;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
@@ -37,12 +235,19 @@ namespace Northbound
|
||||
return;
|
||||
}
|
||||
Instance = this;
|
||||
_losCalculator = new LineOfSightCalculator(this);
|
||||
}
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
base.OnNetworkSpawn();
|
||||
|
||||
|
||||
if (IsServer)
|
||||
{
|
||||
// Server: Register client connected callback to initialize fog data
|
||||
NetworkManager.Singleton.OnClientConnectedCallback += OnClientConnected;
|
||||
}
|
||||
|
||||
if (IsClient && !IsServer)
|
||||
{
|
||||
// 클라이언트는 로컬 데이터 초기화
|
||||
@@ -51,6 +256,28 @@ namespace Northbound
|
||||
}
|
||||
}
|
||||
|
||||
private void OnClientConnected(ulong clientId)
|
||||
{
|
||||
if (!IsServer) return;
|
||||
|
||||
// Ensure fog data exists for this client
|
||||
if (!_serverFogData.ContainsKey(clientId))
|
||||
{
|
||||
_serverFogData[clientId] = new FogOfWarData(gridWidth, gridHeight);
|
||||
Debug.Log($"<color=cyan>[FogOfWar] 클라이언트 {clientId} 안개 데이터 초기화</color>");
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnNetworkDespawn()
|
||||
{
|
||||
base.OnNetworkDespawn();
|
||||
|
||||
if (IsServer && NetworkManager.Singleton != null)
|
||||
{
|
||||
NetworkManager.Singleton.OnClientConnectedCallback -= OnClientConnected;
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!IsServer) return;
|
||||
@@ -167,7 +394,7 @@ namespace Northbound
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 특정 영역을 밝힘 (서버만)
|
||||
/// 특정 영역을 밝힘 (서버만) - Line-of-Sight 지원
|
||||
/// </summary>
|
||||
private void RevealArea(ulong clientId, Vector3 worldPosition, float radius)
|
||||
{
|
||||
@@ -176,11 +403,19 @@ namespace Northbound
|
||||
|
||||
int cellRadius = Mathf.CeilToInt(radius / cellSize);
|
||||
|
||||
// Line-of-sight raycasting if enabled
|
||||
if (enableLineOfSight)
|
||||
{
|
||||
_losCalculator.CalculateVisibleSectors(worldPosition, radius);
|
||||
}
|
||||
|
||||
for (int x = -cellRadius; x <= cellRadius; x++)
|
||||
{
|
||||
for (int y = -cellRadius; y <= cellRadius; y++)
|
||||
{
|
||||
if (x * x + y * y > cellRadius * cellRadius) continue;
|
||||
// Basic circular range check
|
||||
if (x * x + y * y > cellRadius * cellRadius)
|
||||
continue;
|
||||
|
||||
int gridX = gridPos.x + x;
|
||||
int gridY = gridPos.y + y;
|
||||
@@ -188,6 +423,14 @@ namespace Northbound
|
||||
if (gridX < 0 || gridX >= gridWidth || gridY < 0 || gridY >= gridHeight)
|
||||
continue;
|
||||
|
||||
// Line-of-sight check
|
||||
if (enableLineOfSight)
|
||||
{
|
||||
Vector2Int cellPos = new Vector2Int(gridX, gridY);
|
||||
if (!_losCalculator.IsCellVisible(worldPosition, cellPos, radius))
|
||||
continue;
|
||||
}
|
||||
|
||||
// 현재 시야에 표시 + 방문한 적 있음으로 기록
|
||||
fogData.SetVisible(gridX, gridY, true);
|
||||
fogData.SetExplored(gridX, gridY, true);
|
||||
|
||||
349
Assets/Scripts/FogOfWarVisibility.cs
Normal file
349
Assets/Scripts/FogOfWarVisibility.cs
Normal file
@@ -0,0 +1,349 @@
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Northbound
|
||||
{
|
||||
/// <summary>
|
||||
/// Controls object visibility based on fog of war state
|
||||
/// Attach to buildings, obstacles, enemies, or any object that should be hidden in fog
|
||||
/// </summary>
|
||||
public class FogOfWarVisibility : MonoBehaviour
|
||||
{
|
||||
[Header("Visibility Settings")]
|
||||
[Tooltip("Show this object in explored areas (greyed out) or only when visible")]
|
||||
public bool showInExploredAreas = false;
|
||||
|
||||
[Tooltip("Update frequency for checking fog state (seconds)")]
|
||||
public float updateInterval = 0.2f;
|
||||
|
||||
[Tooltip("Renderers to show/hide (auto-detected if empty)")]
|
||||
public Renderer[] renderers;
|
||||
|
||||
[Tooltip("Enable debug logging for this object")]
|
||||
public bool debugLogging = false;
|
||||
|
||||
[Header("Height-Based Distant Visibility")]
|
||||
[Tooltip("Enable visibility from farther away based on object height")]
|
||||
public bool enableDistantVisibility = true;
|
||||
|
||||
[Tooltip("Visibility range multiplier per unit of height (default: 2x vision per 1m height)")]
|
||||
public float heightVisibilityMultiplier = 2.0f;
|
||||
|
||||
[Tooltip("Minimum height to get extended visibility (meters)")]
|
||||
public float minHeightForDistantVisibility = 3.0f;
|
||||
|
||||
[Header("Explored State Visual (Optional)")]
|
||||
[Tooltip("Apply grey/desaturated material when in explored state")]
|
||||
public bool useExploredMaterial = false;
|
||||
|
||||
[Tooltip("Material to use in explored state (optional)")]
|
||||
public Material exploredMaterial;
|
||||
|
||||
private Material[] _originalMaterials;
|
||||
private bool _isVisible = false;
|
||||
private float _updateTimer;
|
||||
private ulong _localClientId;
|
||||
private bool _isInitialized = false;
|
||||
private float _objectHeight = 0f;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// Auto-detect renderers if not set
|
||||
if (renderers == null || renderers.Length == 0)
|
||||
{
|
||||
renderers = GetComponentsInChildren<Renderer>();
|
||||
|
||||
if (debugLogging)
|
||||
{
|
||||
Debug.Log($"[FogOfWarVisibility] {gameObject.name}: Auto-detected {renderers.Length} renderers");
|
||||
}
|
||||
}
|
||||
|
||||
if (renderers == null || renderers.Length == 0)
|
||||
{
|
||||
Debug.LogWarning($"[FogOfWarVisibility] {gameObject.name}: No renderers found! Component will not work.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Store original materials for explored state
|
||||
if (useExploredMaterial && renderers != null && renderers.Length > 0)
|
||||
{
|
||||
_originalMaterials = new Material[renderers.Length];
|
||||
for (int i = 0; i < renderers.Length; i++)
|
||||
{
|
||||
if (renderers[i] != null)
|
||||
{
|
||||
_originalMaterials[i] = renderers[i].sharedMaterial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate object height for distant visibility
|
||||
_objectHeight = CalculateObjectHeight();
|
||||
|
||||
if (debugLogging)
|
||||
{
|
||||
Debug.Log($"[FogOfWarVisibility] {gameObject.name}: Object height = {_objectHeight}m");
|
||||
}
|
||||
|
||||
// CRITICAL: Start hidden and stay hidden until fog system confirms visibility
|
||||
if (debugLogging)
|
||||
{
|
||||
Debug.Log($"[FogOfWarVisibility] {gameObject.name}: START - Setting all {renderers.Length} renderers to HIDDEN");
|
||||
}
|
||||
|
||||
// Force initial hide - don't use SetVisible because _isVisible defaults to false
|
||||
// which would cause early return
|
||||
_isVisible = true; // Set to true first so SetVisible(false) actually runs
|
||||
SetVisible(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the height of this object for distant visibility
|
||||
/// </summary>
|
||||
private float CalculateObjectHeight()
|
||||
{
|
||||
// Try to get height from Building component
|
||||
var building = GetComponent<Building>();
|
||||
if (building != null && building.buildingData != null)
|
||||
{
|
||||
return building.buildingData.height;
|
||||
}
|
||||
|
||||
// Fallback: Use renderer bounds
|
||||
if (renderers != null && renderers.Length > 0)
|
||||
{
|
||||
float maxHeight = 0f;
|
||||
foreach (var renderer in renderers)
|
||||
{
|
||||
if (renderer != null)
|
||||
{
|
||||
maxHeight = Mathf.Max(maxHeight, renderer.bounds.size.y);
|
||||
}
|
||||
}
|
||||
return maxHeight;
|
||||
}
|
||||
|
||||
// Last resort: Use collider bounds
|
||||
var collider = GetComponent<Collider>();
|
||||
if (collider != null)
|
||||
{
|
||||
return collider.bounds.size.y;
|
||||
}
|
||||
|
||||
return 0f;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// Only run on clients, not on dedicated server
|
||||
if (NetworkManager.Singleton != null && NetworkManager.Singleton.IsServer && !NetworkManager.Singleton.IsClient)
|
||||
{
|
||||
// Dedicated server - don't process visibility
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize when network is ready
|
||||
if (!_isInitialized)
|
||||
{
|
||||
if (NetworkManager.Singleton != null && NetworkManager.Singleton.IsClient)
|
||||
{
|
||||
_localClientId = NetworkManager.Singleton.LocalClientId;
|
||||
_isInitialized = true;
|
||||
|
||||
// Force immediate visibility update on initialization
|
||||
UpdateVisibility();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Network not ready - stay hidden
|
||||
SetVisible(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_updateTimer += Time.deltaTime;
|
||||
if (_updateTimer >= updateInterval)
|
||||
{
|
||||
_updateTimer = 0f;
|
||||
UpdateVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateVisibility()
|
||||
{
|
||||
var fogSystem = FogOfWarSystem.Instance;
|
||||
if (fogSystem == null)
|
||||
{
|
||||
// No fog system - stay hidden for safety
|
||||
SetVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait for fog data to be initialized
|
||||
var fogData = fogSystem.GetPlayerFogData(_localClientId);
|
||||
if (fogData == null)
|
||||
{
|
||||
// Fog data not ready yet - stay hidden
|
||||
SetVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
FogOfWarState fogState = fogSystem.GetVisibilityState(_localClientId, transform.position);
|
||||
|
||||
// Check for distant visibility based on height
|
||||
bool isDistantVisible = false;
|
||||
if (enableDistantVisibility && _objectHeight >= minHeightForDistantVisibility)
|
||||
{
|
||||
isDistantVisible = CheckDistantVisibility(fogSystem);
|
||||
}
|
||||
|
||||
if (debugLogging)
|
||||
{
|
||||
Debug.Log($"[FogOfWarVisibility] {gameObject.name} at {transform.position}: State={fogState}, DistantVisible={isDistantVisible}, Height={_objectHeight}m");
|
||||
}
|
||||
|
||||
switch (fogState)
|
||||
{
|
||||
case FogOfWarState.Visible:
|
||||
// Currently visible - show with original materials
|
||||
if (debugLogging) Debug.Log($"[FogOfWarVisibility] {gameObject.name}: Setting VISIBLE");
|
||||
SetVisible(true);
|
||||
SetExploredVisual(false);
|
||||
break;
|
||||
|
||||
case FogOfWarState.Explored:
|
||||
// Previously seen but not currently visible
|
||||
// BUT: Tall objects can be seen from farther away
|
||||
if (showInExploredAreas || isDistantVisible)
|
||||
{
|
||||
if (debugLogging) Debug.Log($"[FogOfWarVisibility] {gameObject.name}: Setting EXPLORED (visible) - distantVisible={isDistantVisible}");
|
||||
SetVisible(true);
|
||||
SetExploredVisual(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (debugLogging) Debug.Log($"[FogOfWarVisibility] {gameObject.name}: Setting EXPLORED (hidden)");
|
||||
SetVisible(false);
|
||||
}
|
||||
break;
|
||||
|
||||
case FogOfWarState.Unexplored:
|
||||
// Never seen - hide unless tall enough to see from distance
|
||||
if (isDistantVisible)
|
||||
{
|
||||
if (debugLogging) Debug.Log($"[FogOfWarVisibility] {gameObject.name}: Setting UNEXPLORED but DISTANT VISIBLE");
|
||||
SetVisible(true);
|
||||
SetExploredVisual(true); // Show as explored/distant
|
||||
}
|
||||
else
|
||||
{
|
||||
if (debugLogging) Debug.Log($"[FogOfWarVisibility] {gameObject.name}: Setting UNEXPLORED (hidden)");
|
||||
SetVisible(false);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// Unknown state - hide completely
|
||||
SetVisible(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if this object should be visible from a distance based on its height
|
||||
/// </summary>
|
||||
private bool CheckDistantVisibility(FogOfWarSystem fogSystem)
|
||||
{
|
||||
// Find the closest vision provider (player)
|
||||
if (NetworkManager.Singleton == null || !NetworkManager.Singleton.IsClient)
|
||||
return false;
|
||||
|
||||
// Get local player object
|
||||
var localPlayer = NetworkManager.Singleton.LocalClient?.PlayerObject;
|
||||
if (localPlayer == null)
|
||||
return false;
|
||||
|
||||
// Calculate distance to player
|
||||
float distanceToPlayer = Vector3.Distance(transform.position, localPlayer.transform.position);
|
||||
|
||||
// Calculate extended visibility range based on height
|
||||
// Taller objects can be seen from farther away
|
||||
// Formula: Base range + (height - minHeight) * multiplier
|
||||
float extendedRange = (_objectHeight - minHeightForDistantVisibility) * heightVisibilityMultiplier;
|
||||
|
||||
// Get player's vision range (assume average vision provider has ~15 unit range)
|
||||
float baseVisionRange = 15f; // You can make this configurable
|
||||
float totalRange = baseVisionRange + extendedRange;
|
||||
|
||||
if (debugLogging)
|
||||
{
|
||||
Debug.Log($"[FogOfWarVisibility] {gameObject.name}: Distance={distanceToPlayer:F1}m, ExtendedRange={totalRange:F1}m (height bonus: +{extendedRange:F1}m)");
|
||||
}
|
||||
|
||||
return distanceToPlayer <= totalRange;
|
||||
}
|
||||
|
||||
private void SetVisible(bool visible)
|
||||
{
|
||||
if (_isVisible == visible) return;
|
||||
|
||||
_isVisible = visible;
|
||||
|
||||
if (renderers == null || renderers.Length == 0)
|
||||
{
|
||||
if (debugLogging)
|
||||
{
|
||||
Debug.LogWarning($"[FogOfWarVisibility] {gameObject.name}: SetVisible({visible}) called but no renderers!");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (debugLogging)
|
||||
{
|
||||
Debug.Log($"[FogOfWarVisibility] {gameObject.name}: SetVisible({visible}) - updating {renderers.Length} renderers");
|
||||
}
|
||||
|
||||
foreach (var renderer in renderers)
|
||||
{
|
||||
if (renderer != null)
|
||||
{
|
||||
renderer.enabled = visible;
|
||||
|
||||
if (debugLogging)
|
||||
{
|
||||
Debug.Log($"[FogOfWarVisibility] {gameObject.name}: Renderer '{renderer.name}' enabled = {visible}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetExploredVisual(bool explored)
|
||||
{
|
||||
if (!useExploredMaterial || renderers == null || exploredMaterial == null)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < renderers.Length; i++)
|
||||
{
|
||||
if (renderers[i] != null)
|
||||
{
|
||||
if (explored)
|
||||
{
|
||||
renderers[i].material = exploredMaterial;
|
||||
}
|
||||
else if (_originalMaterials != null && i < _originalMaterials.Length)
|
||||
{
|
||||
renderers[i].material = _originalMaterials[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
// Visualize fog state check position
|
||||
Gizmos.color = _isVisible ? Color.green : Color.red;
|
||||
Gizmos.DrawWireSphere(transform.position, 0.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/FogOfWarVisibility.cs.meta
Normal file
2
Assets/Scripts/FogOfWarVisibility.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 760137a2fd0da7f458ac4b0ee7f485d6
|
||||
@@ -254,6 +254,14 @@ namespace Northbound
|
||||
obstacle.transform.localScale *= scale;
|
||||
}
|
||||
|
||||
// Add FogOfWarVisibility component to hide obstacles in unexplored areas
|
||||
if (obstacle.GetComponent<FogOfWarVisibility>() == null)
|
||||
{
|
||||
var visibility = obstacle.AddComponent<FogOfWarVisibility>();
|
||||
visibility.showInExploredAreas = false; // Obstacles hidden when not visible
|
||||
visibility.updateInterval = 0.2f;
|
||||
}
|
||||
|
||||
_spawnedPositions.Add(randomPos);
|
||||
Debug.Log($"<color=green>[Spawn] 장애물 배치 성공: {obstacleEntry.prefab.name} at {randomPos}</color>");
|
||||
return true;
|
||||
|
||||
@@ -15,9 +15,9 @@ TagManager:
|
||||
- Interactable
|
||||
- Enemy
|
||||
- Player
|
||||
-
|
||||
-
|
||||
-
|
||||
- Obstacle
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
|
||||
Reference in New Issue
Block a user