#168 코뿔소(Rhinoceros) 패턴 작업

This commit is contained in:
NTG 2024-02-13 05:50:24 +09:00
parent 9325a07d1b
commit f4004d2bc2
199 changed files with 38902 additions and 1169 deletions

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: bbf51270609cd8b4fbb496b691c43c61
guid: 11a23da00c57aa641bfb1e0008d6fdd5
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@ -3835,6 +3835,11 @@ PrefabInstance:
propertyPath: m_Name
value: RedOrc2
objectReference: {fileID: 0}
- target: {fileID: 7305287201485691239, guid: fe3183ccc4347734ea166dd7e385a8f7,
type: 3}
propertyPath: m_IsActive
value: 1
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
@ -55876,6 +55881,11 @@ PrefabInstance:
propertyPath: m_Name
value: RedOrc1
objectReference: {fileID: 0}
- target: {fileID: 6294429197787252722, guid: b82511a1823faf14f97c60a0e6984872,
type: 3}
propertyPath: m_IsActive
value: 1
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
@ -161333,6 +161343,7 @@ GameObject:
serializedVersion: 6
m_Component:
- component: {fileID: 751419040}
- component: {fileID: 751419041}
m_Layer: 0
m_Name: CollidableProps
m_TagString: Untagged
@ -161357,6 +161368,25 @@ Transform:
- {fileID: 800400055}
m_Father: {fileID: 777427179}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &751419041
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 751419039}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1e3fdca004f2d45fe8abbed571a8abd5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_OverrideArea: 1
m_Area: 1
m_OverrideGenerateLinks: 0
m_GenerateLinks: 0
m_IgnoreFromBuild: 0
m_ApplyToChildren: 1
m_AffectedAgents: ffffffff
--- !u!1 &752091393
GameObject:
m_ObjectHideFlags: 0
@ -177304,7 +177334,7 @@ MonoBehaviour:
IsHidden: 0
- Type: 0
Name:
GameObject: {fileID: 549059391}
GameObject: {fileID: 0}
Ordinal: 8
Priority: 0
IconType: 138500
@ -177316,7 +177346,7 @@ MonoBehaviour:
IsHidden: 0
- Type: 0
Name:
GameObject: {fileID: 1383322270}
GameObject: {fileID: 549059391}
Ordinal: 9
Priority: 0
IconType: 138500
@ -177328,9 +177358,21 @@ MonoBehaviour:
IsHidden: 0
- Type: 0
Name:
GameObject: {fileID: 85768100}
GameObject: {fileID: 1383322270}
Ordinal: 10
Priority: 0
IconType: 138500
IconTexture: {fileID: 0}
IsIconRecursive: 0
BackgroundType: 13000
BackgroundTexture: {fileID: 0}
IsBackgroundRecursive: 0
IsHidden: 0
- Type: 0
Name:
GameObject: {fileID: 85768100}
Ordinal: 11
Priority: 0
IconType: 169520
IconTexture: {fileID: 0}
IsIconRecursive: 0
@ -177341,18 +177383,6 @@ MonoBehaviour:
- Type: 0
Name:
GameObject: {fileID: 191889754}
Ordinal: 11
Priority: 0
IconType: 290000
IconTexture: {fileID: 0}
IsIconRecursive: 0
BackgroundType: 0
BackgroundTexture: {fileID: 0}
IsBackgroundRecursive: 0
IsHidden: 0
- Type: 0
Name:
GameObject: {fileID: 1322024545}
Ordinal: 12
Priority: 0
IconType: 290000
@ -177364,7 +177394,7 @@ MonoBehaviour:
IsHidden: 0
- Type: 0
Name:
GameObject: {fileID: 2043119554}
GameObject: {fileID: 1322024545}
Ordinal: 13
Priority: 0
IconType: 290000
@ -177376,7 +177406,7 @@ MonoBehaviour:
IsHidden: 0
- Type: 0
Name:
GameObject: {fileID: 285952512}
GameObject: {fileID: 2043119554}
Ordinal: 14
Priority: 0
IconType: 290000
@ -177388,10 +177418,10 @@ MonoBehaviour:
IsHidden: 0
- Type: 0
Name:
GameObject: {fileID: 223154179}
GameObject: {fileID: 285952512}
Ordinal: 15
Priority: 0
IconType: 1000
IconType: 290000
IconTexture: {fileID: 0}
IsIconRecursive: 0
BackgroundType: 0
@ -177400,7 +177430,7 @@ MonoBehaviour:
IsHidden: 0
- Type: 0
Name:
GameObject: {fileID: 1221037476}
GameObject: {fileID: 223154179}
Ordinal: 16
Priority: 0
IconType: 1000
@ -177412,9 +177442,21 @@ MonoBehaviour:
IsHidden: 0
- Type: 0
Name:
GameObject: {fileID: 1033584364}
GameObject: {fileID: 1221037476}
Ordinal: 17
Priority: 0
IconType: 1000
IconTexture: {fileID: 0}
IsIconRecursive: 0
BackgroundType: 0
BackgroundTexture: {fileID: 0}
IsBackgroundRecursive: 0
IsHidden: 0
- Type: 0
Name:
GameObject: {fileID: 1033584364}
Ordinal: 18
Priority: 0
IconType: 161000
IconTexture: {fileID: 0}
IsIconRecursive: 0
@ -177425,7 +177467,7 @@ MonoBehaviour:
- Type: 0
Name:
GameObject: {fileID: 2046550838}
Ordinal: 18
Ordinal: 19
Priority: 0
IconType: 161000
IconTexture: {fileID: 0}
@ -182360,6 +182402,69 @@ MeshFilter:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 845611084}
m_Mesh: {fileID: -2072209373316696021, guid: a4438a8ede1e65045b8f2af44f8e5587, type: 3}
--- !u!1 &847549924
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 847549926}
- component: {fileID: 847549925}
m_Layer: 0
m_Name: NavMeshSurface
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &847549925
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 847549924}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7a5ac11cc976e418e8d13136b07e1f52, type: 3}
m_Name:
m_EditorClassIdentifier:
m_AgentTypeID: -334000983
m_CollectObjects: 3
m_Size: {x: 10, y: 10, z: 10}
m_Center: {x: 0, y: 2, z: 0}
m_LayerMask:
serializedVersion: 2
m_Bits: 4294967295
m_UseGeometry: 0
m_DefaultArea: 0
m_GenerateLinks: 0
m_IgnoreNavMeshAgent: 1
m_IgnoreNavMeshObstacle: 1
m_OverrideTileSize: 0
m_TileSize: 256
m_OverrideVoxelSize: 0
m_VoxelSize: 0.5
m_MinRegionArea: 2
m_NavMeshData: {fileID: 23800000, guid: 67a241bba6326594fad03e9f4778fd67, type: 2}
m_BuildHeightMesh: 0
--- !u!4 &847549926
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 847549924}
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!1001 &847675453
PrefabInstance:
m_ObjectHideFlags: 0
@ -188362,6 +188467,76 @@ MeshFilter:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 871972808}
m_Mesh: {fileID: 877145102505475392, guid: e6acc74d2dca97b4a9d57fb44c4c52e2, type: 3}
--- !u!1 &872439966
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 872439967}
- component: {fileID: 872439969}
- component: {fileID: 872439968}
m_Layer: 21
m_Name: BossPortal
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &872439967
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 872439966}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 150.38, y: 0, z: -163.03}
m_LocalScale: {x: 5.0656, y: 4.2452, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1221037477}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &872439968
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 872439966}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 505719451d226d54ab182554fdd8e664, type: 3}
m_Name:
m_EditorClassIdentifier:
playerSpawnPosObj: {fileID: 0}
bossController: {fileID: 1221037478}
bossEntranceObstacles:
- {fileID: 1780331645}
--- !u!65 &872439969
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 872439966}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 1
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!1 &872441705
GameObject:
m_ObjectHideFlags: 0
@ -191354,7 +191529,7 @@ MonoBehaviour:
m_OverrideTileSize: 0
m_TileSize: 256
m_OverrideVoxelSize: 0
m_VoxelSize: 0.13333334
m_VoxelSize: 0.5
m_MinRegionArea: 2
m_NavMeshData: {fileID: 23800000, guid: 248a5d84e6704f242aaf236a312d9c69, type: 2}
m_BuildHeightMesh: 0
@ -237547,6 +237722,7 @@ GameObject:
serializedVersion: 6
m_Component:
- component: {fileID: 1095906254}
- component: {fileID: 1095906255}
m_Layer: 0
m_Name: Grounds
m_TagString: Untagged
@ -237571,6 +237747,25 @@ Transform:
- {fileID: 678473477}
m_Father: {fileID: 1221037477}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1095906255
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1095906253}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1e3fdca004f2d45fe8abbed571a8abd5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_OverrideArea: 1
m_Area: 0
m_OverrideGenerateLinks: 0
m_GenerateLinks: 0
m_IgnoreFromBuild: 0
m_ApplyToChildren: 1
m_AffectedAgents: ffffffff
--- !u!1 &1095964192
GameObject:
m_ObjectHideFlags: 0
@ -241359,6 +241554,11 @@ PrefabInstance:
propertyPath: m_Name
value: RedOrc1 (1)
objectReference: {fileID: 0}
- target: {fileID: 6294429197787252722, guid: b82511a1823faf14f97c60a0e6984872,
type: 3}
propertyPath: m_IsActive
value: 1
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
@ -264339,6 +264539,11 @@ PrefabInstance:
propertyPath: m_Name
value: RedOrc1 (2)
objectReference: {fileID: 0}
- target: {fileID: 6294429197787252722, guid: b82511a1823faf14f97c60a0e6984872,
type: 3}
propertyPath: m_IsActive
value: 1
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
@ -266703,6 +266908,7 @@ GameObject:
serializedVersion: 6
m_Component:
- component: {fileID: 1221037477}
- component: {fileID: 1221037478}
m_Layer: 0
m_Name: DesertBossArea
m_TagString: Untagged
@ -266726,9 +266932,29 @@ Transform:
- {fileID: 1095906254}
- {fileID: 777427179}
- {fileID: 1695233646}
- {fileID: 1879350455}
- {fileID: 1598597191}
- {fileID: 872439967}
- {fileID: 1780331644}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1221037478
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1221037476}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3ee283b48c3d38c4690a7711c3276571, type: 3}
m_Name:
m_EditorClassIdentifier:
<BossPrefab>k__BackingField: {fileID: 1907803032604947452, guid: 9ea7800dae26e5f4bbbfba64b7e9485a,
type: 3}
<BossSpawnTransform>k__BackingField: {fileID: 1695233646}
<PlayerSpawnTransform>k__BackingField: {fileID: 1879350455}
bossInstantiateLocation: {fileID: 1598597191}
--- !u!1 &1221375644
GameObject:
m_ObjectHideFlags: 0
@ -368506,7 +368732,7 @@ Transform:
m_GameObject: {fileID: 1695233645}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 150.5, y: 0, z: -173}
m_LocalPosition: {x: 150, y: 0, z: -150}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
@ -375293,7 +375519,7 @@ GameObject:
m_Component:
- component: {fileID: 1729365191}
m_Layer: 0
m_Name: ForestSpawnPosition
m_Name: PlayerSpawnPosition
m_TagString: Untagged
m_Icon: {fileID: 5132851093641282708, guid: 0000000000000000d000000000000000, type: 0}
m_NavMeshLayer: 0
@ -385987,6 +386213,59 @@ PrefabInstance:
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 2e8bbf453e01df4419a1c58dc64996be, type: 3}
--- !u!1 &1780331643
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1780331644}
- component: {fileID: 1780331645}
m_Layer: 21
m_Name: BossEntranceObstacle
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1780331644
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1780331643}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 150.38, y: 0, z: -165.39}
m_LocalScale: {x: 5.0656, y: 4.2452, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1221037477}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!65 &1780331645
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1780331643}
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!1 &1780541748
GameObject:
m_ObjectHideFlags: 0
@ -407069,6 +407348,37 @@ MeshFilter:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1879268411}
m_Mesh: {fileID: -6657265976162632719, guid: 6d6fa4529dae6034c922617ae8409407, type: 3}
--- !u!1 &1879350454
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1879350455}
m_Layer: 0
m_Name: PlayerSpawnPosition
m_TagString: Untagged
m_Icon: {fileID: 5132851093641282708, guid: 0000000000000000d000000000000000, type: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1879350455
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1879350454}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 150.5, y: 0, z: -173}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1221037477}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1879875187
GameObject:
m_ObjectHideFlags: 0
@ -479345,7 +479655,8 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
playerSpawnPosObj: {fileID: 432863286}
fieldBoss: {fileID: 6569975607144876776}
bossController: {fileID: 0}
bossEntranceObstacles: []
--- !u!65 &2604109505574073398
BoxCollider:
m_ObjectHideFlags: 0
@ -488786,12 +489097,22 @@ PrefabInstance:
type: 3}
propertyPath: '<MyComponents>k__BackingField.spawnPosition.Array.data[1]'
value:
objectReference: {fileID: 1695233646}
objectReference: {fileID: 1879350455}
- target: {fileID: 2391945466483065398, guid: d9472bd7185627847ae4d5b1d3d3bb8a,
type: 3}
propertyPath: m_Name
value: CombatPlayer
objectReference: {fileID: 0}
- target: {fileID: 2391945466483065398, guid: d9472bd7185627847ae4d5b1d3d3bb8a,
type: 3}
propertyPath: m_TagString
value: CombatPlayer
objectReference: {fileID: 0}
- target: {fileID: 7729150195808218711, guid: d9472bd7185627847ae4d5b1d3d3bb8a,
type: 3}
propertyPath: m_Mass
value: 10
objectReference: {fileID: 0}
- target: {fileID: 8934240191915016273, guid: d9472bd7185627847ae4d5b1d3d3bb8a,
type: 3}
propertyPath: m_LocalPosition.x
@ -492711,18 +493032,6 @@ Transform:
type: 3}
m_PrefabInstance: {fileID: 6569975607144876774}
m_PrefabAsset: {fileID: 0}
--- !u!114 &6569975607144876776 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 7556135373767129943, guid: 211c62e69325b584bb719f236f0e2d5c,
type: 3}
m_PrefabInstance: {fileID: 6569975607144876774}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1160947005}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 53a5952d905610548b93367641aa8244, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!64 &6569975607144876780
MeshCollider:
m_ObjectHideFlags: 0
@ -504340,6 +504649,7 @@ SceneRoots:
- {fileID: 1816611989}
- {fileID: 85768103}
- {fileID: 269653247}
- {fileID: 847549926}
- {fileID: 2046550842}
- {fileID: 1033584370}
- {fileID: 1719893244}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 67a241bba6326594fad03e9f4778fd67
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 23800000
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 31dac17fce1ca4b4ba03670c1a4102d9
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 23800000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c770fc6f65a9f504489a477abd678a56
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 23800000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -7,23 +7,35 @@ namespace BlueWaterProject
{
public class AiWeight : MonoBehaviour
{
/***********************************************************************
* Definitions
***********************************************************************/
#region Definitions
[Serializable]
private struct DirectionInfo
{
public bool hit; // 장애물 충돌 여부
public Vector3 direction; // 방향 노말값
public float interest; // 호기심 수치
public float danger; // 위험 수치
public RaycastHit RaycastHit { get; set; }
[field: SerializeField] public Vector3 Direction { get; set; }
[field: SerializeField] public float Interest { get; set; }
[field: SerializeField] public float Danger { get; set; }
public DirectionInfo(bool hit, Vector3 direction, float interest, float danger)
public DirectionInfo(RaycastHit raycastHit, Vector3 direction, float interest, float danger)
{
this.hit = hit;
this.direction = direction;
this.interest = interest;
this.danger = danger;
RaycastHit = raycastHit;
Direction = direction;
Interest = interest;
Danger = danger;
}
}
#endregion
/***********************************************************************
* Variables
***********************************************************************/
#region Variables
[field: Tooltip("Scene뷰에서의 가중치 시스템 가시화 여부")]
[field: SerializeField] private bool drawGizmo = true;
@ -45,8 +57,27 @@ namespace BlueWaterProject
[field: Tooltip("장애물 최대 인지 거리")]
[field: SerializeField] private float obstacleDist = 5f;
[Range(1, 36), Tooltip("방향의 갯수")]
[SerializeField] private int directionIndex = 24;
public int DirectionIndex
{
get => directionIndex;
set
{
directionIndex = value;
directionInfo = new DirectionInfo[DirectionIndex];
var angle = 360f / directionInfo.Length;
for (var i = 0; i < directionInfo.Length; i++)
{
var direction = Utils.AngleToDir(angle * i);
directionInfo[i] = new DirectionInfo(default, direction, 0, 0);
}
}
}
[field: Tooltip("방향이 가지는 구조체의 배열")]
[field: SerializeField] private DirectionInfo[] directionInfo = new DirectionInfo[24];
[field: SerializeField] private DirectionInfo[] directionInfo;
[field: Tooltip("현재 공전 중일 때, 해당 방향의 위험 수치가 설정한 값 이상일 경우, 반대편 회전")]
[field: SerializeField] private float dangerValue = 0.8f;
@ -68,18 +99,13 @@ namespace BlueWaterProject
[field: SerializeField] public bool isAvoiding;
private bool usedWeighted;
private void Reset()
{
drawGizmo = true;
maxDistance = 10f;
minDistance = 3f;
orbitDistance = 2f;
orbitAllowableValue = 2f;
obstacleDist = 5f;
directionInfo = new DirectionInfo[24];
dangerValue = 0.8f;
}
#endregion
/***********************************************************************
* Unity Methods
***********************************************************************/
#region Unity Methods
#if UNITY_EDITOR
private void OnDrawGizmos()
@ -90,26 +116,41 @@ namespace BlueWaterProject
{
var myPos = transform.position;
Gizmos.color = GetFinalDirectionValue().direction == directionInfo[i].direction
Gizmos.color = GetFinalDirectionValue().Direction == directionInfo[i].Direction
? Color.green
: Color.white;
var resultWeighted = Mathf.Clamp(directionInfo[i].interest - directionInfo[i].danger, 0f, 1f);
Gizmos.DrawLine(myPos, myPos + directionInfo[i].direction * resultWeighted);
var resultWeighted = Mathf.Clamp(directionInfo[i].Interest - directionInfo[i].Danger, 0f, 1f);
Gizmos.DrawLine(myPos, myPos + directionInfo[i].Direction * resultWeighted);
}
}
#endif
private void Awake()
private void Update()
{
var angle = 360f / directionInfo.Length;
for (var i = 0; i < directionInfo.Length; i++)
{
var direction = Utils.AngleToDir(angle * i + 5);
directionInfo[i] = new DirectionInfo(false, direction, 0, 0);
}
GetDirectionRaycastHit(transform.position);
}
private void GetDirectionRaycastHit(Vector3 startPosition)
{
// 각 방향에 대한 raycastHit 정보 받아두기
for (var i = 0; i < directionInfo.Length; i++)
{
Physics.Raycast(startPosition, directionInfo[i].Direction, out var hit, obstacleDist,obstacleWeightLayer, QueryTriggerInteraction.Ignore);
directionInfo[i].RaycastHit = hit;
}
}
#endregion
/***********************************************************************
* Methods
***********************************************************************/
#region Methods
/// <summary>
/// Update()에서 사용하는 Enemy의 가중치 시스템
/// </summary>
@ -131,7 +172,7 @@ namespace BlueWaterProject
usedWeighted = true;
SetWeights(distanceToTarget, directionToTarget, resultDirection);
MoveTowardDirection(agent, transform.position + CalcDirectionInfo().direction, targetTransform,
MoveTowardDirection(agent, transform.position + CalcDirectionInfo().Direction, targetTransform,
rotationTransform, canLookAtTarget);
}
@ -140,21 +181,21 @@ namespace BlueWaterProject
/// </summary>
private void CheckObstacle()
{
for (var i = 0; i < directionInfo.Length; i++)
{
if (Physics.Raycast(transform.position, directionInfo[i].direction, out var hit, obstacleDist,
obstacleWeightLayer))
{
var obstacleFactor = (obstacleDist - hit.distance) / obstacleDist;
directionInfo[i].danger = obstacleFactor;
directionInfo[i].hit = true;
}
else
{
directionInfo[i].danger = 0f;
directionInfo[i].hit = false;
}
}
// for (var i = 0; i < directionInfo.Length; i++)
// {
// if (Physics.Raycast(transform.position, directionInfo[i].Direction, out var hit, obstacleDist,
// obstacleWeightLayer))
// {
// var obstacleFactor = (obstacleDist - hit.distance) / obstacleDist;
// directionInfo[i].Danger = obstacleFactor;
// directionInfo[i].hit = true;
// }
// else
// {
// directionInfo[i].Danger = 0f;
// directionInfo[i].hit = false;
// }
// }
}
/// <summary>
@ -169,9 +210,9 @@ namespace BlueWaterProject
{
usedWeighted = false;
SetBeInOrBitAndIsAvoiding(false, false);
if (Vector3.Dot(directionInfo[i].direction, directionToTarget) > 0.7f)
if (Vector3.Dot(directionInfo[i].Direction, directionToTarget) > 0.7f)
{
directionInfo[i].interest = 1f;
directionInfo[i].Interest = 1f;
}
}
else if ((!beInOrbit && distanceToTarget > minDistance) ||
@ -179,23 +220,23 @@ namespace BlueWaterProject
{
usedWeighted = true;
SetBeInOrBitAndIsAvoiding(false, false);
directionInfo[i].interest =
Mathf.Clamp(Vector3.Dot(directionInfo[i].direction, directionToTarget), 0, 1)
- directionInfo[i].danger;
directionInfo[i].Interest =
Mathf.Clamp(Vector3.Dot(directionInfo[i].Direction, directionToTarget), 0, 1)
- directionInfo[i].Danger;
}
else if (distanceToTarget > orbitDistance)
{
usedWeighted = true;
SetBeInOrBitAndIsAvoiding(true, false);
directionInfo[i].interest = Mathf.Clamp(Vector3.Dot(directionInfo[i].direction, resultDir), 0, 1)
- directionInfo[i].danger;
directionInfo[i].Interest = Mathf.Clamp(Vector3.Dot(directionInfo[i].Direction, resultDir), 0, 1)
- directionInfo[i].Danger;
}
else if (distanceToTarget <= orbitDistance)
{
usedWeighted = true;
SetBeInOrBitAndIsAvoiding(false, true);
directionInfo[i].interest =
Mathf.Clamp(Vector3.Dot(directionInfo[i].direction, -directionToTarget), 0, 1);
directionInfo[i].Interest =
Mathf.Clamp(Vector3.Dot(directionInfo[i].Direction, -directionToTarget), 0, 1);
}
}
}
@ -205,7 +246,7 @@ namespace BlueWaterProject
/// </summary>
private Vector3 CheckTurnAround(Vector3 resultDir, Vector3 directionToTarget)
{
if (beInOrbit || directionInfo[GetDirectionIndex(resultDir)].danger < dangerValue) return resultDir;
if (beInOrbit || directionInfo[GetDirectionIndex(resultDir)].Danger < dangerValue) return resultDir;
isClockwise = !isClockwise;
return SetResultDirection(directionToTarget);
@ -253,9 +294,9 @@ namespace BlueWaterProject
for (var i = 0; i < directionInfo.Length; i++)
{
if (directionInfo[i].interest <= bestWeight) continue;
if (directionInfo[i].Interest <= bestWeight) continue;
bestWeight = directionInfo[i].interest;
bestWeight = directionInfo[i].Interest;
bestDirectionIndex = i;
}
@ -272,7 +313,7 @@ namespace BlueWaterProject
for (var i = 0; i < directionInfo.Length; i++)
{
var finalInterestValue = Mathf.Clamp(directionInfo[i].interest - directionInfo[i].danger, 0f, 1f);
var finalInterestValue = Mathf.Clamp(directionInfo[i].Interest - directionInfo[i].Danger, 0f, 1f);
if (finalInterestValue <= bestWeight) continue;
bestWeight = finalInterestValue;
@ -292,7 +333,7 @@ namespace BlueWaterProject
for (var i = 0; i < directionInfo.Length; i++)
{
var dotValue = Vector3.Dot(directionInfo[i].direction, direction);
var dotValue = Vector3.Dot(directionInfo[i].Direction, direction);
if (maxDotValue >= dotValue) continue;
@ -320,5 +361,16 @@ namespace BlueWaterProject
beInOrbit = beInOrbitValue;
isAvoiding = isAvoidingValue;
}
/// <summary>
/// 각도를 통해 방향값을 반환하는 함수
/// </summary>
private Vector3 AngleToDir(float angle)
{
var radian = angle * Mathf.Deg2Rad;
return new Vector3(Mathf.Sin(radian), 0f, Mathf.Cos(radian)).normalized;
}
#endregion
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e4569d9c2e381c5449ca2d04ff1bd70c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 786e4a88bcdbf714a81520b648e68c91
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,5 +1,4 @@
using System;
using BehaviorDesigner.Runtime;
using BehaviorDesigner.Runtime.Tasks;
using UnityEngine;
using Action = BehaviorDesigner.Runtime.Tasks.Action;
@ -9,25 +8,25 @@ namespace BlueWaterProject
{
[TaskCategory("Custom/FieldBossAction")]
[Serializable]
public class ExecuteSkill : Action
public class ActivateSkill : Action
{
[SerializeField] private SharedInt skillIndex;
[SerializeField] private string skillName;
private FieldBoss fieldBoss;
public override void OnAwake()
{
fieldBoss = GetComponent<FieldBoss>();
fieldBoss = transform.GetComponent<FieldBoss>();
}
public override void OnStart()
{
fieldBoss.ExecuteActiveSkill(fieldBoss.GetActiveSkillList()[skillIndex.Value]);
fieldBoss.ActivateSkill(skillName);
}
public override TaskStatus OnUpdate()
{
return fieldBoss.GetUsedSkillCoroutine() ? TaskStatus.Running : TaskStatus.Success;
return fieldBoss.IsUsingSkill ? TaskStatus.Running : TaskStatus.Success;
}
}
}

View File

@ -0,0 +1,36 @@
// using System;
// using BehaviorDesigner.Runtime.Tasks;
// using UnityEngine;
//
// // ReSharper disable once CheckNamespace
// namespace BlueWaterProject
// {
// [TaskCategory("Custom/FieldBossConditional")]
// [Serializable]
// public class CompareDistance : Conditional
// {
// [SerializeField] private float maxDistance = 3f;
//
// private FieldBoss fieldBoss;
//
// public override void OnAwake()
// {
// fieldBoss = GetComponent<FieldBoss>();
// }
//
// public override TaskStatus OnUpdate()
// {
// var targetBounds = fieldBoss.Target.bounds;
// var targetPos = targetBounds.min;
// targetPos.x = targetBounds.center.x;
// targetPos.z = targetBounds.center.z;
//
// var myBounds = fieldBoss.MyCollider.bounds;
// var myPos = myBounds.min;
// myPos.x = myBounds.center.x;
// myPos.z = myBounds.center.z;
//
// return Vector3.Distance(targetPos, myPos) <= maxDistance ? TaskStatus.Success : TaskStatus.Failure;
// }
// }
// }

View File

@ -0,0 +1,33 @@
using System;
using BehaviorDesigner.Runtime.Tasks;
using UnityEngine;
using Action = BehaviorDesigner.Runtime.Tasks.Action;
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
[TaskCategory("Custom/FieldBossAction")]
[Serializable]
public class MoveTarget : Action
{
[SerializeField] private float stoppingDistance;
[SerializeField] private float limitMovingTime;
private FieldBoss fieldBoss;
public override void OnAwake()
{
fieldBoss = transform.GetComponent<FieldBoss>();
}
public override void OnStart()
{
fieldBoss.MoveTarget(stoppingDistance);
}
public override TaskStatus OnUpdate()
{
return fieldBoss.HasReachedDestination(limitMovingTime) ? TaskStatus.Success : TaskStatus.Running;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1f085fad5a5a7c04da8e1d7f014675a0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a241d2a8708ad744983da8e1b81f7961
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,26 @@
using System;
using BehaviorDesigner.Runtime.Tasks;
using UnityEngine;
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
[TaskCategory("Custom/FieldBossConditional")]
[Serializable]
public class EnableSkill : Conditional
{
[SerializeField] private string skillName;
private FieldBoss fieldBoss;
public override void OnAwake()
{
fieldBoss = transform.GetComponent<FieldBoss>();
}
public override TaskStatus OnUpdate()
{
return fieldBoss.EnableSkill(skillName) ? TaskStatus.Success : TaskStatus.Failure;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 29a10688914e93e41b013ecfdd3db9fb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,48 @@
using System;
using BehaviorDesigner.Runtime.Tasks;
using Sirenix.OdinInspector;
using UnityEngine;
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
[TaskCategory("Custom/FieldBossConditional")]
[Serializable]
public class TargetDistance : Conditional
{
[Title("비교값 float 설정")]
public float compareTo;
[Title("부등호 설정 - Tooltip 참고")]
[BehaviorDesigner.Runtime.Tasks.Tooltip("LessThen : variable < compareTo\n" +
"LessThenOrEqualTo : variable <= compareTo\n" +
"GreaterThen : variable > compareTo\n" +
"GreaterThenOrEqualTo : variable < compareTo\n")]
public Inequality inequality;
private FieldBoss fieldBoss;
public override void OnAwake()
{
fieldBoss = transform.GetComponent<FieldBoss>();
}
public override TaskStatus OnUpdate()
{
return CompareInequality(fieldBoss.GetTargetDistance()) ? TaskStatus.Success : TaskStatus.Failure;
}
private bool CompareInequality(float variable)
{
return inequality switch
{
Inequality.NONE => throw new Exception("부등호 미설정 오류"),
Inequality.LESS_THEN => variable < compareTo,
Inequality.LESS_THEN_OR_EQUAL_TO => variable <= compareTo,
Inequality.GREATER_THEN => variable > compareTo,
Inequality.GREATER_THEN_OR_EQUAL_TO => variable >= compareTo,
_ => throw new ArgumentOutOfRangeException()
};
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 67a3df493f272d34b92f4642d0e7b045
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4bfe6b45d561ba3498fd8ae44568991f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,31 @@
using BehaviorDesigner.Runtime.Tasks;
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
public class PatrolMove : Action
{
private IPatrol iPatrol;
public override void OnAwake()
{
iPatrol = transform.GetComponent<IPatrol>();
}
public override void OnStart()
{
iPatrol.SetMovePoint();
}
public override TaskStatus OnUpdate()
{
if (!iPatrol.HasReachedDestination())
{
iPatrol.UpdatePositionAndRotation();
return TaskStatus.Running;
}
return TaskStatus.Success;
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 6f4fd33f9b745e740b3d5408b7e8cd63

View File

@ -0,0 +1,37 @@
using BehaviorDesigner.Runtime.Tasks;
using UnityEngine;
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
public class PatrolWait : Action
{
private IPatrol iPatrol;
private float currentWaitTime;
private float time;
public override void OnAwake()
{
iPatrol = transform.GetComponent<IPatrol>();
}
public override void OnStart()
{
currentWaitTime = iPatrol.GetCurrentWayPoint().WaitTime;
time = 0f;
}
public override TaskStatus OnUpdate()
{
time += Time.deltaTime;
if (time < currentWaitTime)
{
return TaskStatus.Running;
}
return TaskStatus.Success;
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 1e4d5b048d872fb498c1f979de884213

View File

@ -1,36 +0,0 @@
using System;
using BehaviorDesigner.Runtime.Tasks;
using UnityEngine;
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
[TaskCategory("Custom/FieldBossConditional")]
[Serializable]
public class CompareDistance : Conditional
{
[SerializeField] private float maxDistance = 3f;
private FieldBoss fieldBoss;
public override void OnAwake()
{
fieldBoss = GetComponent<FieldBoss>();
}
public override TaskStatus OnUpdate()
{
var targetBounds = fieldBoss.Target.bounds;
var targetPos = targetBounds.min;
targetPos.x = targetBounds.center.x;
targetPos.z = targetBounds.center.z;
var myBounds = fieldBoss.MyCollider.bounds;
var myPos = myBounds.min;
myPos.x = myBounds.center.x;
myPos.z = myBounds.center.z;
return Vector3.Distance(targetPos, myPos) <= maxDistance ? TaskStatus.Success : TaskStatus.Failure;
}
}
}

View File

@ -0,0 +1,39 @@
using UnityEngine;
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
public class PirateShipAi : MonoBehaviour
{
/***********************************************************************
* Variables
***********************************************************************/
#region Variables
// Components
[SerializeField] private ShipPatrol shipPatrol;
#endregion
/***********************************************************************
* Unity Events
***********************************************************************/
#region Unity Events
private void Start()
{
}
#endregion
/***********************************************************************
* Methods
***********************************************************************/
#region Methods
#endregion
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 64a8cec913e50e74ebca756bee584331

View File

@ -0,0 +1,170 @@
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.AI;
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
public class ShipPatrol : MonoBehaviour, IPatrol
{
/***********************************************************************
* Variables
***********************************************************************/
#region Variables
// 컴포넌트
[Title("컴포넌트")]
[SerializeField] private Rigidbody rb;
// 패트롤 옵션
[Title("패트롤 옵션")]
[SerializeField] private bool showWayPointGizmo = true;
[field: SerializeField] public WayPoint[] WayPoints { get; set; }
[field: SerializeField] public Vector3 OriginalPoint { get; set; }
[field: SerializeField] public int CurrentIndex { get; set; }
[field: SerializeField] public int PreviousIndex { get; set; }
// 기즈모 잠금 기능
[Title("기즈모 잠금 기능")]
[field: SerializeField] public bool LockHandlesOnXAxis { get; set; }
[field: SerializeField] public bool LockHandlesOnYAxis { get; set; }
[field: SerializeField] public bool LockHandlesOnZAxis { get; set; }
#endregion
/***********************************************************************
* Unity Events
***************************************************************m********/
#region Unity Events
private void OnDrawGizmosSelected()
{
if (WayPoints == null || WayPoints.Length <= 0 || !showWayPointGizmo) return;
if (!Application.isPlaying)
{
OriginalPoint = rb.position;
}
for (var i = 0; i < WayPoints.Length; i++)
{
var currentColor = i == CurrentIndex ? Color.blue : Color.yellow;
if ((i + 1) < WayPoints.Length)
{
Gizmos.color = currentColor;
Gizmos.DrawLine(OriginalPoint + WayPoints[i].Point, OriginalPoint + WayPoints[i + 1].Point);
}
if (i == WayPoints.Length - 1)
{
Gizmos.color = currentColor;
Gizmos.DrawLine(OriginalPoint + WayPoints[i].Point, OriginalPoint + WayPoints[0].Point);
}
}
if (!Application.isPlaying) return;
DrawGizmoPoint(OriginalPoint + WayPoints[CurrentIndex].Point,2f, Color.blue);
DrawGizmoPoint(OriginalPoint + WayPoints[PreviousIndex].Point, 2f, Color.red);
}
private static void DrawGizmoPoint(Vector3 pos, float size, Color color)
{
Gizmos.color = color;
Gizmos.DrawWireSphere(pos, size);
}
private void Start()
{
OriginalPoint = transform.position;
}
#endregion
/***********************************************************************
* Methods
***********************************************************************/
#region Methods
public WayPoint GetCurrentWayPoint() => WayPoints[CurrentIndex];
public int GetNextIndex()
{
if (WayPoints == null) return -1;
var maxSize = WayPoints.Length;
var nextIndex = CurrentIndex + 1;
if (nextIndex >= maxSize)
{
nextIndex = 0;
}
return nextIndex;
}
public bool HasReachedDestination()
{
var myPosition = rb.position;
var movePoint = OriginalPoint + WayPoints[CurrentIndex].Point;
var distance = Vector3.Distance(myPosition, movePoint);
print(distance);
if (distance > 3f) return false;
print("도착");
return true;
}
public void SetMovePoint()
{
if (!rb || WayPoints == null || WayPoints.Length <= CurrentIndex) return;
print("다음 목적지");
PreviousIndex = CurrentIndex;
CurrentIndex = GetNextIndex();
}
public void UpdatePositionAndRotation()
{
// // 현재 위치에서 목표지점까지의 방향과 거리 계산
// var myPosition = rb.position;
// var movePoint = OriginalPoint + WayPoints[CurrentIndex].Point;
// var direction = (movePoint - myPosition).normalized;
// var distance = Vector3.Distance(movePoint, myPosition);
//
// // Combine forces with weights
// var currentVelocity = seekForce + avoidForce;
// currentVelocity = Vector3.ClampMagnitude(currentVelocity, maxVelocity);
//
// if (distance < 10f)
// {
// // 목적지에 가까워짐에 따라 속도를 동적으로 조절
// var desiredSpeed = (distance / 10f) * maxSpeed;
// currentVelocity = currentVelocity.normalized * desiredSpeed;
// }
// else
// {
// // 목적지에서 멀리 떨어져 있을 때는 최대 속도로 이동
// currentVelocity = Vector3.ClampMagnitude(currentVelocity, maxSpeed);
// }
//
// rb.AddForce(currentVelocity - rb.velocity, ForceMode.Acceleration);
//
// //rb.AddForce(currentVelocity, ForceMode.Acceleration);
//
// if (rb.velocity.magnitude > 10f)
// {
// rb.velocity = rb.velocity.normalized * 10f;
// }
//
// var targetRotation = Quaternion.LookRotation(direction);
// rb.MoveRotation(Quaternion.RotateTowards(rb.rotation, targetRotation, rotationSpeed * Time.deltaTime));
}
#endregion
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 54f7637ae66462d4ebd40401643172f6

View File

@ -0,0 +1,60 @@
using UnityEngine;
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
public class BossController : MonoBehaviour
{
[field: SerializeField] public GameObject BossPrefab { get; set; }
[field: SerializeField] public Transform BossSpawnTransform { get; set; }
[field: SerializeField] public Transform PlayerSpawnTransform { get; set; }
[SerializeField] private Transform bossInstantiateLocation;
private GameObject instantiatedBoss;
private void Start()
{
InitStart();
}
private void InitStart()
{
if (!instantiatedBoss)
{
instantiatedBoss = Instantiate(BossPrefab, BossSpawnTransform.position, Quaternion.identity, bossInstantiateLocation);
}
instantiatedBoss.SetActive(false);
}
public void ResetBoss()
{
if (instantiatedBoss)
{
if (instantiatedBoss.activeSelf)
{
Destroy(instantiatedBoss);
}
}
}
public void Respawn()
{
if (instantiatedBoss)
{
if (instantiatedBoss.activeSelf)
{
Destroy(instantiatedBoss);
}
else
{
instantiatedBoss.transform.position = BossSpawnTransform.position;
instantiatedBoss.SetActive(true);
return;
}
}
instantiatedBoss = Instantiate(BossPrefab, BossSpawnTransform.position, Quaternion.identity, bossInstantiateLocation);
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 3ee283b48c3d38c4690a7711c3276571

View File

@ -1,5 +1,3 @@
using System;
using Doozy.Editor.EditorUI.Components;
using UnityEngine;
// ReSharper disable once CheckNamespace
@ -8,70 +6,42 @@ namespace BlueWaterProject
public class BossPortal : MonoBehaviour
{
[SerializeField] private GameObject playerSpawnPosObj;
[SerializeField] private FieldBoss fieldBoss;
private Collider myCollider;
private float[] bossMapVertices;
private Collider[] bossEntrances;
[SerializeField] private BossController bossController;
[SerializeField] private Collider[] bossEntranceObstacles;
private bool isIn;
private void Awake()
private void Start()
{
myCollider = GetComponent<Collider>();
var bossEntrance = transform.Find("BossEntrance");
if (!bossEntrance)
{
print("BossEntrance 오브젝트가 null입니다.");
}
else
{
bossEntrances = bossEntrance.GetComponentsInChildren<Collider>();
}
GetColliderVertices(myCollider);
BossEntranceSetActive(false);
}
private void OnTriggerEnter(Collider other)
{
if (isIn || !other.CompareTag("InIslandPlayer")) return;
if (isIn || !other.CompareTag("CombatPlayer")) return;
// TODO : 보스 맵 입장
isIn = true;
other.transform.position = playerSpawnPosObj.transform.position;
if (playerSpawnPosObj)
{
other.transform.position = playerSpawnPosObj.transform.position;
}
BossEntranceSetActive(true);
fieldBoss.BossSpawn(other, bossMapVertices);
bossController.Respawn();
}
private void BossEntranceSetActive(bool value)
{
foreach (var entrance in bossEntrances)
foreach (var entrance in bossEntranceObstacles)
{
entrance.gameObject.SetActive(value);
}
}
private void BossReset()
public void ResetPortal()
{
fieldBoss.gameObject.SetActive(false);
BossEntranceSetActive(false);
isIn = false;
}
private void GetColliderVertices(Collider col)
{
var bounds = col.bounds;
var center = bounds.center;
var size = bounds.size;
bossMapVertices = new float[4];
bossMapVertices[0] = center.x + -size.x * 0.5f;
bossMapVertices[1] = center.x + size.x * 0.5f;
bossMapVertices[2] = center.z + size.z * 0.5f;
bossMapVertices[3] = center.z + -size.z * 0.5f;
BossEntranceSetActive(false);
bossController.ResetBoss();
}
}
}

View File

@ -2,7 +2,6 @@ using System;
using System.Collections;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
// ReSharper disable once CheckNamespace
@ -59,6 +58,7 @@ namespace BlueWaterProject
public bool isAttacking;
public bool isComboPossible;
public bool isComboAttacking;
public bool isUsingSkill;
}
[DisableIf("@true")]
@ -150,10 +150,12 @@ namespace BlueWaterProject
var myCollider = MyComponents.movement.MyComponents.capsuleCollider;
var myRb = MyComponents.movement.MyComponents.rb;
var myVisualLook = MyComponents.visualLook;
var myAnimator = MyComponents.animator;
var targetLayer = MyCharacterOption.targetLayer;
var ui = UiManager.Inst.CombatUi.MainSkillUi;
ui.gameObject.SetActive(true);
mainSkill.SkillInputData.InitInputData(myCollider, myRb, myVisualLook, MyCharacterOption.targetLayer, ui);
mainSkill.SkillInputData.InitInputData(myCollider, myRb, null, myVisualLook, myAnimator, null, targetLayer, ui);
mainSkill.InitData();
}
}
@ -198,7 +200,7 @@ namespace BlueWaterProject
{
if (MyCurrentState.isAttacking || GetIsDashing()) return;
mainSkill.SkillInputData.UpdateInputData(GetCurrentPosition());
mainSkill.SkillInputData.StartPosition = GetCurrentPosition();
if (mainSkill.EnableSkill())
{
SetEnableMoving(false);

View File

@ -1,4 +1,5 @@
using System;
using System.Collections;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.InputSystem;
@ -72,6 +73,7 @@ namespace BlueWaterProject
public bool isOutOfControl;
public bool isDashing;
public bool enableDash = true;
public bool IsStunned { get; set; }
}
[Serializable]
@ -139,7 +141,7 @@ namespace BlueWaterProject
private void FixedUpdate()
{
if (!MyCurrentState.enableMoving) return;
if (!MyCurrentState.enableMoving || MyCurrentState.IsStunned) return;
InputMove();
CheckGround();
@ -354,9 +356,9 @@ namespace BlueWaterProject
Vector3 finalVelocity;
if (MyCurrentState.isOutOfControl || MyCurrentState.isOnSteepSlope || !MyCurrentState.isGrounded)
{
var velocity = MyComponents.rb.velocity;
finalVelocity = MyComponents.rb.position + new Vector3(velocity.x, MyCurrentValue.gravity.y, velocity.z) * Time.fixedDeltaTime;
MyComponents.rb.MovePosition(finalVelocity);
// var velocity = MyComponents.rb.velocity;
// finalVelocity = MyComponents.rb.position + new Vector3(velocity.x, MyCurrentValue.gravity.y, velocity.z) * Time.fixedDeltaTime;
// MyComponents.rb.MovePosition(finalVelocity);
return;
}
if (MyCurrentValue.horizontalVelocity == Vector3.zero)
@ -367,17 +369,31 @@ namespace BlueWaterProject
finalVelocity = MyComponents.rb.position + MyCurrentValue.horizontalVelocity * Time.fixedDeltaTime;
MyComponents.rb.MovePosition(finalVelocity);
}
public void Move(Vector3 velocity)
// finalVelocity = MyCurrentValue.horizontalVelocity;
// MyComponents.rb.velocity = finalVelocity;
}
public void Move(Vector3 position) => MyComponents.rb.position = position;
public void SpawnPlayer(Vector3 position)
{
MyComponents.rb.position = velocity;
Move(position);
var bossPortal = GameObject.Find("DesertBossArea").transform.Find("BossPortal").GetComponent<BossPortal>();
if (bossPortal)
{
bossPortal.ResetPortal();
}
}
public void MoveToCurrentDirection(float speed)
{
var finalVelocity = MyComponents.rb.position + MyCurrentValue.previousMoveDirection * speed * Time.fixedDeltaTime;
MyComponents.rb.MovePosition(finalVelocity);
// var finalVelocity = MyCurrentValue.previousMoveDirection * speed;
// MyComponents.rb.velocity = finalVelocity;
}
public void SetEnableMoving(bool value) => MyCurrentState.enableMoving = value;
@ -517,7 +533,7 @@ namespace BlueWaterProject
{
if (GUI.Button(new Rect(sWidth - 350f, yPos, buttonWidth, buttonHeight), spawnPosition[i].name, buttonStyle))
{
Move(spawnPosition[i].position);
SpawnPlayer(spawnPosition[i].position);
}
yPos += buttonSpacing;
}

View File

@ -22,7 +22,7 @@ namespace BlueWaterProject
}
var animationLength = stateInfo.length;
animator.speed = animationLength / theWaltzOfTheSword.castingTime;
animator.speed = animationLength / theWaltzOfTheSword.CastingTime;
}
public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)

View File

@ -39,7 +39,7 @@ namespace BlueWaterProject
}
var animationLength = stateInfo.length;
animator.speed = animationLength / theWaltzOfTheSword.skillDuration;
animator.speed = animationLength / theWaltzOfTheSword.SkillDuration;
intervalTime = animationLength / animator.speed / 6f;
if (!theWaltzOfTheSword.isMovingCamera)
@ -87,11 +87,11 @@ namespace BlueWaterProject
if (theWaltzOfTheSword.returnToStartPosition)
{
combatPlayerController.Move(theWaltzOfTheSword.SkillInputData.startPosition);
combatPlayerController.Move(theWaltzOfTheSword.SkillInputData.StartPosition);
}
if (!theWaltzOfTheSword.isMovingCamera)
{
var userTransform = theWaltzOfTheSword.SkillInputData.playerCollider.transform;
var userTransform = theWaltzOfTheSword.SkillInputData.PlayerCollider.transform;
CameraManager.Inst.CombatCamera.SetFollowAndLookAt(userTransform);
}

View File

@ -1,100 +1,129 @@
using System;
using System.Collections;
using System.Collections.Generic;
using BehaviorDesigner.Runtime;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.AI;
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
public abstract class FieldBoss : MonoBehaviour, IDamageable
{
#region Properties and variables
// Stat
[field: Title("Stat")]
[field: Tooltip("최대 체력 설정")]
[field: SerializeField] public float MaxHp { get; private set; } = 100f;
[field: Tooltip("현재 체력")]
[field: SerializeField] public float CurrentHp { get; private set; }
[field: Tooltip("이동 속도 설정")]
[field: SerializeField] public float MoveSpd { get; set; } = 5f;
[field: SerializeField] public Collider Target { get; set; }
[field: SerializeField] public LayerMask TargetLayer { get; set; }
[SerializeField] protected List<ActiveSkill> activeSkillList;
[SerializeField] private Slider hpSlider;
[SerializeField] private Slider damageEffectSlider;
[SerializeField] private float damageEffectSpeed = 0.1f;
/***********************************************************************
* Variables
***********************************************************************/
#region Variables
// 컴포넌트
protected Rigidbody rb;
public Collider MyCollider { get; set; }
protected BehaviorTree bt;
protected Transform unitRoot;
protected SkillController skillController;
[Title("컴포넌트")]
[SerializeField] protected Rigidbody rb;
[SerializeField] protected Collider capsuleCollider;
[SerializeField] protected NavMeshAgent agent;
[SerializeField] protected BehaviorTree behaviorTree;
[SerializeField] protected Transform visualLook;
[SerializeField] protected Animator animator;
// 일반 변수
protected bool usedSkillCoroutine;
protected bool isCollisionAttack;
protected float collisionDamage;
protected float[] bossMapVertices;
// 보스 스탯
[Title("보스 스탯")]
[SerializeField] protected float maxHp = 100f;
[SerializeField] protected float moveSpeed = 3f;
[SerializeField] protected LayerMask targetLayer;
// 스킬
[Title("스킬")]
[SerializeField] protected List<SkillBase> skillList = new(6);
protected Dictionary<string, ISkill> skillDictionary = new(6);
private List<SkillBase> instanceSkillList = new(6);
// 실시간 데이터
[field: Title("실시간 데이터")]
[field: SerializeField] public float CurrentHp { get; private set; }
[field: SerializeField] public Collider Target { get; set; }
[field: SerializeField] public bool IsUsingSkill { get; protected set; }
protected Vector3 PreviousDirection { get; set; } = Vector3.right;
private float departureTime = -1f;
protected bool isDead;
// [SerializeField] private Slider hpSlider;
// [SerializeField] private Slider damageEffectSlider;
// [SerializeField] private float damageEffectSpeed = 0.1f;
#endregion
#region Unity built-in methods
/***********************************************************************
* Unity Events
***********************************************************************/
#region Unity Events
protected virtual void Awake()
{
rb = GetComponent<Rigidbody>();
MyCollider = GetComponent<Collider>();
bt = GetComponent<BehaviorTree>();
unitRoot = transform.Find("UnitRoot");
if (unitRoot == null)
{
print("UnitRoot를 찾을 수 없습니다.");
}
skillController = FindAnyObjectByType<SkillController>();
var overlayCanvas = GameObject.Find("OverlayCanvas").transform;
hpSlider = overlayCanvas.Find("FieldBossHpSlider").GetComponent<Slider>();
damageEffectSlider = hpSlider.transform.Find("Fill Area/Background/DamageEffectSlider").GetComponent<Slider>();
gameObject.SetActive(false);
hpSlider.gameObject.SetActive(false);
}
protected virtual void Start()
{
TargetLayer = LayerMask.GetMask("Player");
SetMaxHp();
InitStart();
}
protected void OnCollisionStay(Collision other)
private void OnDestroy()
{
if (!isCollisionAttack || !other.gameObject.CompareTag("InIslandPlayer")) return;
var iDamageable = other.gameObject.GetComponent<IDamageable>();
iDamageable.TakeDamage(collisionDamage);
isCollisionAttack = false;
foreach (var element in instanceSkillList)
{
if (element.gameObject != null)
{
Destroy(element.gameObject);
}
}
}
#endregion
#region Interface
/***********************************************************************
* Init Methods
***********************************************************************/
#region Init Methods
[Button("셋팅 초기화")]
private void Init()
{
rb = GetComponent<Rigidbody>();
capsuleCollider = GetComponent<Collider>();
agent = GetComponent<NavMeshAgent>();
behaviorTree = GetComponent<BehaviorTree>();
visualLook = transform.Find("VisualLook");
animator = visualLook.GetComponent<Animator>();
}
private void InitStart()
{
agent.updateRotation = false;
agent.speed = moveSpeed;
SetCurrentHp(maxHp);
Target = GameObject.FindGameObjectWithTag("CombatPlayer").GetComponent<Collider>();
foreach (var element in skillList)
{
var skill = Instantiate(element, Vector3.zero, Quaternion.identity);
skillDictionary.Add(skill.SkillName, skill);
skill.SkillInputData.InitInputData(capsuleCollider, rb, agent, visualLook, animator, Target, targetLayer, null);
skill.InitData();
instanceSkillList.Add(skill);
}
}
#endregion
/***********************************************************************
* Interfaces
***********************************************************************/
#region Interfaces
// IDamageable
public void TakeDamage(float attackerPower, Vector3? attackPos = null)
{
if (isDead) return;
var changeHp = Mathf.Max(CurrentHp - attackerPower, 0);
SetCurrentHp(changeHp);
@ -108,7 +137,7 @@ namespace BlueWaterProject
// 공격 당함
}
public void Die()
public virtual void Die()
{
Destroy(gameObject, 2f);
}
@ -117,73 +146,124 @@ namespace BlueWaterProject
#endregion
#region Custom methods
public void BossSpawn(Collider target, float[] mapVertices)
/***********************************************************************
* Methods
***********************************************************************/
#region Methods
public void MovePoint(Vector3 point, float stoppingDistance)
{
SetMaxHp();
if (agent)
{
agent.stoppingDistance = stoppingDistance;
agent.SetDestination(point);
}
}
public void MoveTarget(float stoppingDistance)
{
if (agent)
{
agent.isStopped = false;
agent.stoppingDistance = stoppingDistance;
agent.SetDestination(Target.transform.position);
}
}
public bool HasReachedDestination(float limitMovingTime)
{
// 경로 계산 중이면 false
if (!agent || agent.pathPending)
{
departureTime = -1f;
return false;
}
gameObject.SetActive(true);
hpSlider.gameObject.SetActive(true);
Target = target;
bossMapVertices = new float[mapVertices.Length];
bossMapVertices = mapVertices;
Invoke(nameof(EnableBehaviorTree), 2f);
}
private void EnableBehaviorTree() => bt.EnableBehavior();
public virtual void ExecuteActiveSkill(ActiveSkill activeSkill)
{
// activeSkill.Execute(TargetLayer, Target.bounds.center);
// StartCoroutine(CoolDown(myActiveSkill.ActiveSkillData.Cooldown, () => usedActiveSkill = false));
}
private void SetMaxHp()
{
CurrentHp = MaxHp;
if (hpSlider != null)
if (departureTime < 0f)
{
hpSlider.maxValue = MaxHp;
hpSlider.value = MaxHp;
departureTime = Time.time;
}
if (departureTime > 0f && Time.time - departureTime >= limitMovingTime)
{
agent.isStopped = true;
departureTime = -1f;
return true;
}
// 남은 거리가 정지 거리 이상이면 false
if (agent.remainingDistance > agent.stoppingDistance) return false;
// 경로가 있고, 속도가 0이 아니면 false
if (agent.hasPath && agent.velocity.sqrMagnitude != 0f) return false;
agent.velocity = Vector3.zero;
agent.isStopped = true;
departureTime = -1f;
return true;
}
public bool EnableSkill(string skillName)
{
if (IsUsingSkill) return false;
if (skillDictionary.ContainsKey(skillName))
{
return skillDictionary[skillName].EnableSkill();
}
if (damageEffectSlider != null)
{
damageEffectSlider.maxValue = MaxHp;
damageEffectSlider.value = MaxHp;
}
return false;
}
[Button("스킬 사용")]
public virtual void ActivateSkill(string skillName){}
private void SetCurrentHp(float value)
{
CurrentHp = value;
if (hpSlider != null)
{
hpSlider.value = value;
}
StartCoroutine(DamageEffect(CurrentHp));
}
protected void CoolDownCoroutine(float waitTime, Action onCooldownComplete)
public float GetTargetDistance()
{
StartCoroutine(Utils.CoolDown(waitTime, onCooldownComplete));
var distance = Target.transform.position - transform.position;
distance.y = 0f;
return distance.magnitude;
}
private IEnumerator DamageEffect(float currentHp)
public Vector3 GetTargetDirection()
{
while (damageEffectSlider.value > currentHp)
{
damageEffectSlider.value -= damageEffectSpeed;
yield return null;
}
var distance = Target.transform.position - transform.position;
distance.y = 0f;
return distance.normalized;
}
public bool GetUsedSkillCoroutine() => usedSkillCoroutine;
public List<ActiveSkill> GetActiveSkillList() => activeSkillList;
// private void SetCurrentHp(float value)
// {
// CurrentHp = value;
// if (hpSlider != null)
// {
// hpSlider.value = value;
// }
//
// StartCoroutine(DamageEffect(CurrentHp));
// }
//
// protected void CoolDownCoroutine(float waitTime, Action onCooldownComplete)
// {
// StartCoroutine(Utils.CoolDown(waitTime, onCooldownComplete));
// }
//
// private IEnumerator DamageEffect(float currentHp)
// {
// while (damageEffectSlider.value > currentHp)
// {
// damageEffectSlider.value -= damageEffectSpeed;
// yield return null;
// }
// }
//
// public bool GetUsedSkillCoroutine() => usedSkillCoroutine;
// public List<ActiveSkill> GetActiveSkillList() => activeSkillList;
#endregion
}

View File

@ -1,181 +1,181 @@
using System;
using System.Collections;
using Sirenix.OdinInspector;
using UnityEngine;
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
[Serializable]
public class FieldBoss01 : FieldBoss
{
#region Properties and variables
[Title("Extensions Data")]
[SerializeField] private int lavaNumber = 8;
[SerializeField] private int volcanicNumber = 20;
[SerializeField] private int lineRushNumber = 1;
[SerializeField] private int enhancedLineRushNumber = 2;
[SerializeField] private Vector3 lavaBubbleBulletOffset = new(0, 3, 0);
[SerializeField] private float lavaBubbleBulletDelay = 0.3f;
[SerializeField] private int lavaBubbleBulletNumber = 2;
[SerializeField] private int lavaBubbleBulletFastNumber = 3;
private ParticleSystem ghost;
#endregion
#region Unity built-in methods
protected override void Awake()
{
base.Awake();
ghost = transform.Find("Ghost").GetComponent<ParticleSystem>();
}
protected override void Start()
{
base.Start();
activeSkillList.Add(skillController.GetSkillByName("LavaEruption"));
activeSkillList.Add(skillController.GetSkillByName("LineRush"));
activeSkillList.Add(skillController.GetSkillByName("BigLavaEruption"));
activeSkillList.Add(skillController.GetSkillByName("VolcanicEruption"));
activeSkillList.Add(skillController.GetSkillByName("LavaBubbleBullet"));
activeSkillList.Add(skillController.GetSkillByName("LavaBubbleBulletFast"));
collisionDamage = activeSkillList[1].ActiveSkillData.Damage;
}
#endregion
#region Interface
#endregion
#region Custom methods
[Button("스킬 사용")]
public void Test(int index)
{
ExecuteActiveSkill(activeSkillList[index]);
}
public override void ExecuteActiveSkill(ActiveSkill activeSkill)
{
usedSkillCoroutine = true;
var endSkillTime = 0f;
if (activeSkill.ActiveSkillData.Name.Equals("LavaEruption"))
{
for (var i = 0; i < lavaNumber; i++)
{
var lava = Instantiate(activeSkill);
lava.Execute(TargetLayer, Target.transform.position, bossMapVertices);
endSkillTime = lava.GetEndSkillTime();
}
}
else if (activeSkill.ActiveSkillData.Name.Equals("LineRush"))
{
StartCoroutine(LineRushCoroutine(activeSkill));
return;
}
else if (activeSkill.ActiveSkillData.Name.Equals("BigLavaEruption"))
{
var bigLava = Instantiate(activeSkill);
bigLava.Execute(TargetLayer, Target.transform.position);
endSkillTime = bigLava.GetEndSkillTime();
}
else if (activeSkill.ActiveSkillData.Name.Equals("VolcanicEruption"))
{
for (var i = 0; i < volcanicNumber; i++)
{
var lava = Instantiate(activeSkill);
lava.SetUser(MyCollider);
lava.Execute(TargetLayer, Target.transform.position, bossMapVertices);
endSkillTime = lava.GetEndSkillTime();
}
}
else if (activeSkill.ActiveSkillData.Name.Equals("LavaBubbleBullet"))
{
StartCoroutine(LavaBubbleBulletCoroutine(activeSkill));
endSkillTime = 0f;
}
else
{
print("사용할 수 없는 스킬입니다.");
}
CoolDownCoroutine(endSkillTime, () => usedSkillCoroutine = false);
}
private IEnumerator LineRushCoroutine(ActiveSkill activeSkill)
{
var endSkillTime = 0f;
var skillNumber = CurrentHp > MaxHp * 0.5f ? lineRushNumber : enhancedLineRushNumber;
for (var i = 0; i < skillNumber; i++)
{
var skill = Instantiate(activeSkill);
skill.SetUser(MyCollider);
skill.Execute(TargetLayer, Target.transform.position, GhostPlay, GhostStop);
endSkillTime = skill.GetEndSkillTime();
var time = 0f;
while (time < endSkillTime)
{
time += Time.deltaTime;
yield return null;
}
}
CoolDownCoroutine(endSkillTime, () => usedSkillCoroutine = false);
}
private IEnumerator LavaBubbleBulletCoroutine(ActiveSkill activeSkill)
{
for (var i = 0; i < lavaBubbleBulletNumber; i++)
{
var bullet = Instantiate(activeSkill, MyCollider.bounds.center + lavaBubbleBulletOffset, Quaternion.identity);
bullet.Execute(Target);
var time = 0f;
while (time < lavaBubbleBulletDelay)
{
time += Time.deltaTime;
yield return null;
}
}
var activeSkill2 = skillController.GetSkillByName("LavaBubbleBulletFast");
for (var i = 0; i < lavaBubbleBulletFastNumber; i++)
{
var bullet = Instantiate(activeSkill2, MyCollider.bounds.center + lavaBubbleBulletOffset, Quaternion.identity);
bullet.Execute(Target);
var time = 0f;
while (time < lavaBubbleBulletDelay)
{
time += Time.deltaTime;
yield return null;
}
}
}
private void GhostPlay()
{
isCollisionAttack = true;
ghost.Clear();
ghost.Play();
}
private void GhostStop()
{
isCollisionAttack = false;
ghost.Stop();
}
#endregion
}
}
// using System;
// using System.Collections;
// using Sirenix.OdinInspector;
// using UnityEngine;
//
// // ReSharper disable once CheckNamespace
// namespace BlueWaterProject
// {
// [Serializable]
// public class FieldBoss01 : FieldBoss
// {
// #region Properties and variables
//
// [Title("Extensions Data")]
// [SerializeField] private int lavaNumber = 8;
// [SerializeField] private int volcanicNumber = 20;
// [SerializeField] private int lineRushNumber = 1;
// [SerializeField] private int enhancedLineRushNumber = 2;
// [SerializeField] private Vector3 lavaBubbleBulletOffset = new(0, 3, 0);
// [SerializeField] private float lavaBubbleBulletDelay = 0.3f;
// [SerializeField] private int lavaBubbleBulletNumber = 2;
// [SerializeField] private int lavaBubbleBulletFastNumber = 3;
//
// private ParticleSystem ghost;
//
// #endregion
//
// #region Unity built-in methods
//
// protected override void Awake()
// {
// base.Awake();
//
// ghost = transform.Find("Ghost").GetComponent<ParticleSystem>();
// }
//
// protected override void Start()
// {
// base.Start();
//
// activeSkillList.Add(skillController.GetSkillByName("LavaEruption"));
// activeSkillList.Add(skillController.GetSkillByName("LineRush"));
// activeSkillList.Add(skillController.GetSkillByName("BigLavaEruption"));
// activeSkillList.Add(skillController.GetSkillByName("VolcanicEruption"));
// activeSkillList.Add(skillController.GetSkillByName("LavaBubbleBullet"));
// activeSkillList.Add(skillController.GetSkillByName("LavaBubbleBulletFast"));
//
// collisionDamage = activeSkillList[1].ActiveSkillData.Damage;
// }
//
// #endregion
//
// #region Interface
//
//
//
// #endregion
//
// #region Custom methods
//
// [Button("스킬 사용")]
// public void Test(int index)
// {
// ExecuteActiveSkill(activeSkillList[index]);
// }
//
// public override void ExecuteActiveSkill(ActiveSkill activeSkill)
// {
// usedSkillCoroutine = true;
//
// var endSkillTime = 0f;
// if (activeSkill.ActiveSkillData.Name.Equals("LavaEruption"))
// {
// for (var i = 0; i < lavaNumber; i++)
// {
// var lava = Instantiate(activeSkill);
// lava.Execute(TargetLayer, Target.transform.position, bossMapVertices);
// endSkillTime = lava.GetEndSkillTime();
// }
// }
// else if (activeSkill.ActiveSkillData.Name.Equals("LineRush"))
// {
// StartCoroutine(LineRushCoroutine(activeSkill));
// return;
// }
// else if (activeSkill.ActiveSkillData.Name.Equals("BigLavaEruption"))
// {
// var bigLava = Instantiate(activeSkill);
// bigLava.Execute(TargetLayer, Target.transform.position);
// endSkillTime = bigLava.GetEndSkillTime();
// }
// else if (activeSkill.ActiveSkillData.Name.Equals("VolcanicEruption"))
// {
// for (var i = 0; i < volcanicNumber; i++)
// {
// var lava = Instantiate(activeSkill);
// lava.SetUser(MyCollider);
// lava.Execute(TargetLayer, Target.transform.position, bossMapVertices);
// endSkillTime = lava.GetEndSkillTime();
// }
// }
// else if (activeSkill.ActiveSkillData.Name.Equals("LavaBubbleBullet"))
// {
// StartCoroutine(LavaBubbleBulletCoroutine(activeSkill));
// endSkillTime = 0f;
// }
// else
// {
// print("사용할 수 없는 스킬입니다.");
// }
// CoolDownCoroutine(endSkillTime, () => usedSkillCoroutine = false);
// }
//
// private IEnumerator LineRushCoroutine(ActiveSkill activeSkill)
// {
// var endSkillTime = 0f;
// var skillNumber = CurrentHp > MaxHp * 0.5f ? lineRushNumber : enhancedLineRushNumber;
// for (var i = 0; i < skillNumber; i++)
// {
// var skill = Instantiate(activeSkill);
// skill.SetUser(MyCollider);
// skill.Execute(TargetLayer, Target.transform.position, GhostPlay, GhostStop);
// endSkillTime = skill.GetEndSkillTime();
//
// var time = 0f;
// while (time < endSkillTime)
// {
// time += Time.deltaTime;
// yield return null;
// }
// }
//
// CoolDownCoroutine(endSkillTime, () => usedSkillCoroutine = false);
// }
//
// private IEnumerator LavaBubbleBulletCoroutine(ActiveSkill activeSkill)
// {
// for (var i = 0; i < lavaBubbleBulletNumber; i++)
// {
// var bullet = Instantiate(activeSkill, MyCollider.bounds.center + lavaBubbleBulletOffset, Quaternion.identity);
// bullet.Execute(Target);
//
// var time = 0f;
// while (time < lavaBubbleBulletDelay)
// {
// time += Time.deltaTime;
// yield return null;
// }
// }
//
// var activeSkill2 = skillController.GetSkillByName("LavaBubbleBulletFast");
// for (var i = 0; i < lavaBubbleBulletFastNumber; i++)
// {
// var bullet = Instantiate(activeSkill2, MyCollider.bounds.center + lavaBubbleBulletOffset, Quaternion.identity);
// bullet.Execute(Target);
//
// var time = 0f;
// while (time < lavaBubbleBulletDelay)
// {
// time += Time.deltaTime;
// yield return null;
// }
// }
// }
//
// private void GhostPlay()
// {
// isCollisionAttack = true;
// ghost.Clear();
// ghost.Play();
// }
//
// private void GhostStop()
// {
// isCollisionAttack = false;
// ghost.Stop();
// }
//
// #endregion
// }
// }

View File

@ -0,0 +1,125 @@
using System;
using Sirenix.OdinInspector;
using UnityEngine;
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
public class Rhinoceros : FieldBoss
{
/***********************************************************************
* Variables
***********************************************************************/
#region Variables
// 실시간 상태
[Title("실시간 상태")]
[SerializeField] private bool isMoving;
#endregion
/***********************************************************************
* Unity Events
***********************************************************************/
#region Unity Events
private void Update()
{
MoveHandler();
}
#endregion
/***********************************************************************
* Init Methods
***********************************************************************/
#region Init Methods
#endregion
/***********************************************************************
* Interfaces
***********************************************************************/
#region Interfaces
public override void Die()
{
isDead = true;
if (agent && agent.enabled)
{
agent.velocity = Vector3.zero;
agent.isStopped = true;
agent.enabled = false;
}
if (rb)
{
rb.velocity = Vector3.zero;
rb.isKinematic = true;
}
if (capsuleCollider && capsuleCollider.enabled)
{
capsuleCollider.isTrigger = true;
}
animator.SetTrigger("isDead");
Destroy(gameObject, 2f);
}
#endregion
/***********************************************************************
* Methods
***********************************************************************/
#region Methods
public override void ActivateSkill(string skillName)
{
IsUsingSkill = true;
skillDictionary[skillName].SkillInputData.PreviousDirection = PreviousDirection;
skillDictionary[skillName].ActivateSkill(
() => IsUsingSkill = false,
() => PreviousDirection = GetTargetDirection());
}
private void MoveHandler()
{
if (agent)
{
//var localVelocity = transform.InverseTransformDirection(agent.velocity);
//var moveDirection = localVelocity.normalized;
var moveDirection = agent.enabled ? agent.velocity.normalized : rb.velocity.normalized;
isMoving = moveDirection != Vector3.zero;
animator.SetBool("isMoving", isMoving);
if (isMoving)
{
PreviousDirection = moveDirection;
}
animator.SetFloat("xDirection", PreviousDirection.x);
animator.SetFloat("zDirection", PreviousDirection.z);
FlipVisualLook(PreviousDirection.x);
}
}
private void FlipVisualLook(float previousDirectionX)
{
var localScale = visualLook.localScale;
localScale.x = previousDirectionX switch
{
> 0.01f => Mathf.Abs(localScale.x),
< -0.01f => -Mathf.Abs(localScale.x),
_ => localScale.x
};
visualLook.localScale = localScale;
}
#endregion
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 12e4cddc82acd7e4aa0c534bd6db84a9

View File

@ -135,7 +135,13 @@ namespace BlueWaterProject
var boost = isBoosting ? boostPower : 1f;
var speedChange = movementInput != Vector2.zero ? acceleration * boost * Time.fixedDeltaTime : deceleration * Time.fixedDeltaTime;
var targetVelocity = moveDirection * (maxSpeed * boost);
rb.velocity = Vector3.MoveTowards(rb.velocity, targetVelocity, speedChange);
//rb.velocity = Vector3.MoveTowards(rb.velocity, targetVelocity, speedChange);
rb.AddForce(targetVelocity * speedChange, ForceMode.Acceleration);
if (rb.velocity.magnitude > maxSpeed * boost)
{
rb.velocity = rb.velocity.normalized * (maxSpeed * boost);
}
if (moveDirection != Vector3.zero)
{
@ -149,6 +155,29 @@ namespace BlueWaterProject
// rb.rotation = Quaternion.Slerp(rb.rotation, targetRotation, turnSpeed * Time.fixedDeltaTime);
}
}
public void ApplyForceToReachVelocity(Rigidbody rigidbody, Vector3 velocity, float force = 1, ForceMode mode = ForceMode.Force)
{
if (force == 0 || velocity.magnitude == 0)
return;
velocity = velocity + velocity.normalized * (0.2f * rigidbody.drag);
print(velocity);
//force = 1 => need 1 s to reach velocity (if mass is 1) => force can be max 1 / Time.fixedDeltaTime
force = Mathf.Clamp(force, -rigidbody.mass / Time.fixedDeltaTime, rigidbody.mass / Time.fixedDeltaTime);
//dot product is a projection from rhs to lhs with a length of result / lhs.magnitude https://www.youtube.com/watch?v=h0NJK4mEIJU
if (rigidbody.velocity.magnitude == 0)
{
rigidbody.AddForce(velocity * force, mode);
}
else
{
var velocityProjectedToTarget = (velocity.normalized * Vector3.Dot(velocity, rigidbody.velocity) / velocity.magnitude);
rigidbody.AddForce((velocity - velocityProjectedToTarget) * force, mode);
}
}
private void StopShipMovement()
{

View File

@ -16,6 +16,8 @@ namespace BlueWaterProject
private GameObject cinemachineCameras;
private List<CinemachineVirtualCamera> cineCamList;
private float originalRotation;
private const int CINE_CAM_NUM = 1;
@ -65,7 +67,7 @@ namespace BlueWaterProject
public void SetFollowAndLookAt(Transform target)
{
BaseCombatCamera.Follow = target;
BaseCombatCamera.LookAt = target;
//BaseCombatCamera.LookAt = target;
}
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a4449f766bff72748a5afae8e7fb907c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,57 @@
using UnityEditor;
using UnityEngine;
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
[CustomEditor(typeof(ShipPatrol),true)]
public class ShipPatrolEditor : Editor
{
private void OnSceneGUI()
{
Handles.color = Color.green;
var patrol = (ShipPatrol)target;
for (var i = 0; i < patrol.WayPoints.Length; i++)
{
EditorGUI.BeginChangeCheck();
var oldPoint = patrol.OriginalPoint + patrol.WayPoints[i].Point;
var style = new GUIStyle();
style.normal.textColor = Color.yellow;
Handles.Label(patrol.OriginalPoint + patrol.WayPoints[i].Point +
(Vector3.down * 0.4f) + (Vector3.right * 0.4f), "" + i, style);
var newPoint = Handles.FreeMoveHandle(oldPoint, 0.5f,
new Vector3(0.25f, 0.25f, 0.25f), Handles.CircleHandleCap);
newPoint = ApplyAxisLock(oldPoint, newPoint);
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(target, "Free Move Handle");
patrol.WayPoints[i].Point = newPoint - patrol.OriginalPoint;
}
}
}
private Vector3 ApplyAxisLock(Vector3 oldPoint, Vector3 newPoint)
{
var patrolSetting = (ShipPatrol)target;
if (patrolSetting.LockHandlesOnXAxis)
{
newPoint.x = oldPoint.x;
}
if (patrolSetting.LockHandlesOnYAxis)
{
newPoint.y = oldPoint.y;
}
if (patrolSetting.LockHandlesOnZAxis)
{
newPoint.z = oldPoint.z;
}
return newPoint;
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c18603aad4bd6ed4884f225756c0d27e

View File

@ -0,0 +1,9 @@
using VContainer;
using VContainer.Unity;
public class GameLifetimeScope : LifetimeScope
{
protected override void Configure(IContainerBuilder builder)
{
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f6d3174aef91e74449c5585531f446ac

View File

@ -0,0 +1,8 @@
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
public interface ILaunch
{
void ExecuteLaunch();
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 656485857a827954b84f967e8903a637
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,19 @@
using UnityEngine;
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
public interface IPatrol
{
WayPoint[] WayPoints { get; set; }
Vector3 OriginalPoint { get; set; }
int CurrentIndex { get; set; }
int PreviousIndex { get; set; }
WayPoint GetCurrentWayPoint();
int GetNextIndex();
bool HasReachedDestination();
void SetMovePoint();
void UpdatePositionAndRotation();
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 04272c03bcfe62e4486a1826b5065025
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,10 +1,12 @@
using System;
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
public interface ISkill
{
SkillInputData SkillInputData { get; set; }
void ActivateSkill();
void ActivateSkill(params Action[] actions);
bool EnableSkill();
void InitData();
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 17876ba3755c2d44488cc47410de1153
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,97 @@
using System;
using System.Collections;
using BlueWaterProject;
using Sirenix.OdinInspector;
using UnityEngine;
// ReSharper disable once CheckNamespace
namespace RhinocerosSkill
{
public class EarthquakeWave : SkillBase
{
[Title("추가 옵션")]
[SerializeField] private bool isDrawingGizmo = true;
[SerializeField] private float width = 3f;
private Vector3 startPosition;
private Vector3 halfScale;
private RaycastHit[] hits;
private bool isUsingSkill;
private void OnDrawGizmos()
{
if (!isDrawingGizmo || !isUsingSkill) return;
Gizmos.color = Color.red;
var rotation = Quaternion.LookRotation(new Vector3(SkillInputData.PreviousDirection.x, 0, SkillInputData.PreviousDirection.z));
Gizmos.matrix = Matrix4x4.TRS(startPosition + SkillInputData.PreviousDirection * Range * 0.5f, rotation, Vector3.one);
Gizmos.DrawWireCube(Vector3.zero, new Vector3(halfScale.x * 2, halfScale.y * 2, Range));
Gizmos.matrix = Matrix4x4.identity;
}
public override void ActivateSkill(params Action[] actions)
{
ReadySkill = false;
CoolDown(Cooldown, () => ReadySkill = true);
StartCoroutine(SkillCoroutine(actions));
}
public override bool EnableSkill()
{
if (!ReadySkill) return false;
return true;
}
protected override void BasicSetting()
{
base.BasicSetting();
hits = new RaycastHit[5];
}
private IEnumerator SkillCoroutine(params Action[] actions)
{
isUsingSkill = true;
startPosition = SkillInputData.PlayerRb.position;
halfScale = transform.localScale * 0.5f;
transform.position = startPosition;
var angle = Mathf.Atan2(SkillInputData.PreviousDirection.x, SkillInputData.PreviousDirection.z) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0, angle, 0);
transform.localScale = new Vector3(width, 6f, Range * 2);
ShowIndicator();
var elapsedTime = 0f;
var fill = 1 / CastingTime;
while (elapsedTime < CastingTime)
{
elapsedTime += Time.deltaTime;
if (isUsingIndicator && indicator)
{
var fillValue = indicator.material.GetFloat(FillHash) + Time.deltaTime * fill;
indicator.material.SetFloat(FillHash, fillValue);
}
yield return null;
}
var maxSize = Physics.BoxCastNonAlloc(startPosition, halfScale, SkillInputData.PreviousDirection,
hits, Quaternion.identity, 0f, SkillInputData.TargetLayer, QueryTriggerInteraction.Ignore);
for (var i = 0; i < maxSize; i++)
{
var iDamageable = hits[i].transform.GetComponent<IDamageable>();
iDamageable?.TakeDamage(Damage);
}
HideIndicator();
actions[0].Invoke();
isUsingSkill = false;
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 0bc3a312bfa527e45864c7d94466f674

View File

@ -0,0 +1,87 @@
using System;
using System.Collections;
using BlueWaterProject;
using Sirenix.OdinInspector;
using UnityEngine;
// ReSharper disable once CheckNamespace
namespace RhinocerosSkill
{
public class HammerAttack : SkillBase
{
[Title("추가 옵션")]
[SerializeField] private float hammerOffset = 3f;
private Collider[] hitColliders;
public override void ActivateSkill(params Action[] actions)
{
ReadySkill = false;
SkillInputData.PlayerAnimator.SetTrigger("isHammerAttack");
CoolDown(Cooldown, () => ReadySkill = true);
StartCoroutine(SkillCoroutine(actions));
}
public override bool EnableSkill()
{
if (!ReadySkill) return false;
return true;
}
protected override void BasicSetting()
{
base.BasicSetting();
hitColliders = new Collider[5];
}
private IEnumerator SkillCoroutine(params Action[] actions)
{
while (!SkillInputData.PlayerAnimator.GetCurrentAnimatorStateInfo(0).IsName("HammerAttack"))
{
yield return null;
}
var skillPlayerPosition = SkillInputData.PlayerCollider.transform.position;
var targetPosition = SkillInputData.TargetCollider.transform.position;
var targetToDirection = (targetPosition - skillPlayerPosition).normalized;
transform.position = skillPlayerPosition + targetToDirection * hammerOffset;
transform.localScale = Vector3.one * Range;
actions[1].Invoke();
ShowIndicator();
var elapsedTime = 0f;
var fill = 1 / CastingTime;
while (elapsedTime < CastingTime)
{
elapsedTime += Time.deltaTime;
if (isUsingIndicator && indicator)
{
var fillValue = indicator.material.GetFloat(FillHash) + Time.deltaTime * fill;
indicator.material.SetFloat(FillHash, fillValue);
}
yield return null;
}
var maxSize = Physics.OverlapSphereNonAlloc(transform.position, Range, hitColliders, SkillInputData.TargetLayer);
for (var i = 0; i < maxSize; i++)
{
var iDamageable = hitColliders[i].GetComponent<IDamageable>();
iDamageable?.TakeDamage(Damage);
}
HideIndicator();
while (SkillInputData.PlayerAnimator.GetCurrentAnimatorStateInfo(0).IsName("HammerAttack") &&
SkillInputData.PlayerAnimator.GetCurrentAnimatorStateInfo(0).normalizedTime < 1.0f)
{
yield return null;
}
actions[0].Invoke();
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 7f2a50b72621aac4f9178db7ab02867e

View File

@ -0,0 +1,142 @@
using System;
using System.Collections;
using BlueWaterProject;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.Rendering.Universal;
// ReSharper disable once CheckNamespace
namespace RhinocerosSkill
{
public class HammerSwing : SkillBase
{
[Title("추가 옵션")]
[SerializeField] private bool isDrawingGizmo = true;
[SerializeField] private float angle = 180f;
[Title("발사체 옵션")]
[SerializeField] private GameObject projectilePrefab;
[SerializeField] private int projectileNumber = 5;
[SerializeField] private float projectileDamage = 10f;
[SerializeField] private float projectileAngle = 90f;
[SerializeField] private float projectileSpeed = 500f;
private Collider[] hitColliders;
private bool isUsingSkill;
private void OnDrawGizmos()
{
if (!isDrawingGizmo || !isUsingSkill) return;
Gizmos.color = Color.red;
var skillPosition = transform.position;
Gizmos.DrawWireSphere(skillPosition, Range);
if (SkillInputData != null && SkillInputData.TargetCollider != null)
{
var skillPlayerPosition = SkillInputData.PlayerRb.position;
var forward = transform.forward;
var leftBoundary = Quaternion.Euler(0, -angle / 2, 0) * forward;
var rightBoundary = Quaternion.Euler(0, angle / 2, 0) * forward;
Gizmos.color = Color.yellow;
Gizmos.DrawLine(skillPlayerPosition, skillPlayerPosition + leftBoundary * Range);
Gizmos.DrawLine(skillPlayerPosition, skillPlayerPosition + rightBoundary * Range);
}
}
public override void ActivateSkill(params Action[] actions)
{
ReadySkill = false;
SkillInputData.PlayerAnimator.SetTrigger("isHammerSwing");
CoolDown(Cooldown, () => ReadySkill = true);
StartCoroutine(SkillCoroutine(actions));
}
public override bool EnableSkill()
{
if (!ReadySkill) return false;
return true;
}
protected override void BasicSetting()
{
if (isUsingIndicator && indicator)
{
indicator.scaleMode = DecalScaleMode.InheritFromHierarchy;
indicator.material = new Material(indicator.material);
indicator.material.SetFloat(FillHash, 0f);
indicator.material.SetFloat("Angle", angle);
}
hitColliders = new Collider[5];
}
private IEnumerator SkillCoroutine(params Action[] actions)
{
while (!SkillInputData.PlayerAnimator.GetCurrentAnimatorStateInfo(0).IsName("HammerSwing"))
{
yield return null;
}
isUsingSkill = true;
var skillPlayerPosition = SkillInputData.PlayerRb.position;
var targetPosition = SkillInputData.TargetCollider.transform.position;
var targetToDirection = (targetPosition - skillPlayerPosition).normalized;
transform.position = skillPlayerPosition;
var yAngle = Mathf.Atan2(targetToDirection.x, targetToDirection.z) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0, yAngle, 0);
transform.localScale = Vector3.one * (Range * 2);
actions[1].Invoke();
ShowIndicator();
var elapsedTime = 0f;
var fill = 1 / CastingTime;
while (elapsedTime < CastingTime)
{
elapsedTime += Time.deltaTime;
if (isUsingIndicator && indicator)
{
var fillValue = indicator.material.GetFloat(FillHash) + Time.deltaTime * fill;
indicator.material.SetFloat(FillHash, fillValue);
}
yield return null;
}
var maxSize = Physics.OverlapSphereNonAlloc(transform.position, Range, hitColliders, SkillInputData.TargetLayer);
for (var i = 0; i < maxSize; i++)
{
var angleToTarget = Vector3.Angle(skillPlayerPosition, transform.forward);
if (angleToTarget <= angle * 0.5f)
{
var iDamageable = hitColliders[i].GetComponent<IDamageable>();
iDamageable?.TakeDamage(Damage);
}
}
HideIndicator();
var startAngle = yAngle - projectileAngle * 0.5f;
var angleStep = projectileAngle / (projectileNumber - 1);
for (var i = 0; i < projectileNumber; i++)
{
var currentAngle = startAngle + angleStep * i;
var rotation = Quaternion.Euler(0, currentAngle, 0);
var projectile = Instantiate(projectilePrefab, transform.position + Vector3.up, rotation);
var particleWeapon = projectile.GetComponent<ParticleWeapon>();
particleWeapon.SetPower(projectileDamage);
particleWeapon.Rb.AddForce(particleWeapon.transform.forward * projectileSpeed);
}
actions[0].Invoke();
isUsingSkill = false;
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 0fde1b55379e6834585dfbadb4b7c0f2

View File

@ -0,0 +1,247 @@
using System;
using System.Collections;
using BlueWaterProject;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.Rendering.Universal;
// ReSharper disable once CheckNamespace
namespace RhinocerosSkill
{
public class JumpSmash : SkillBase
{
[Title("추가 옵션")]
[SerializeField] private float upTime = 0.1f;
[SerializeField] private float waitTime = 1f;
[SerializeField] private float downTime = 0.1f;
[SerializeField] private float stunTime = 2f;
[SerializeField] protected DecalProjector stunIndicator;
private Collider[] hitColliders;
private void OnDestroy()
{
if (SkillInputData.TargetCollider)
{
SkillInputData.TargetCollider.GetComponent<PhysicsMovement>().MyCurrentState.IsStunned = false;
}
}
public override void ActivateSkill(params Action[] actions)
{
ReadySkill = false;
SkillInputData.PlayerAnimator.SetBool("isJump", true);
CoolDown(Cooldown, () => ReadySkill = true);
StartCoroutine(SkillCoroutine(actions));
}
public override bool EnableSkill()
{
if (!ReadySkill) return false;
return true;
}
protected override void BasicSetting()
{
if (isUsingIndicator)
{
if (indicator)
{
indicator.scaleMode = DecalScaleMode.InheritFromHierarchy;
indicator.material = new Material(indicator.material);
indicator.material.SetFloat(FillHash, 0f);
}
if (stunIndicator)
{
stunIndicator.scaleMode = DecalScaleMode.InheritFromHierarchy;
stunIndicator.material = new Material(stunIndicator.material);
stunIndicator.material.SetFloat(FillHash, 0f);
}
}
hitColliders = new Collider[5];
}
protected override void HideIndicator()
{
if (isUsingIndicator)
{
if (indicator)
{
indicator.enabled = false;
indicator.material.SetFloat(FillHash, 0);
}
if (stunIndicator)
{
stunIndicator.enabled = false;
stunIndicator.material.SetFloat(FillHash, 0);
}
}
}
protected override void ShowIndicator()
{
if (isUsingIndicator)
{
if (indicator)
{
indicator.material.SetFloat(FillHash, 0);
indicator.enabled = true;
}
if (stunIndicator)
{
stunIndicator.material.SetFloat(FillHash, 0);
stunIndicator.enabled = true;
}
}
}
private IEnumerator SkillCoroutine(params Action[] actions)
{
while (!SkillInputData.PlayerAnimator.GetCurrentAnimatorStateInfo(0).IsName("Jump"))
{
yield return null;
}
while (SkillInputData.PlayerAnimator.GetCurrentAnimatorStateInfo(0).IsName("Jump") &&
SkillInputData.PlayerAnimator.GetCurrentAnimatorStateInfo(0).normalizedTime < 1.0f)
{
yield return null;
}
SkillInputData.PlayerAgent.enabled = false;
SkillInputData.PlayerRb.useGravity = false;
var elapsedTime = 0f;
var startPosition = SkillInputData.PlayerRb.transform.position;
var endPosition = startPosition + Vector3.up * 15f;
while (elapsedTime < upTime)
{
elapsedTime += Time.deltaTime;
SkillInputData.PlayerRb.position = Vector3.Lerp(startPosition, endPosition, elapsedTime / upTime);
yield return null;
}
SkillInputData.PlayerRb.position = endPosition;
yield return new WaitForSeconds(waitTime);
var targetPosition = SkillInputData.TargetCollider.transform.position;
transform.position = targetPosition;
transform.localScale = Vector3.one * (Range * 2f);
stunIndicator.transform.localScale = Vector3.one * 4f;
startPosition = targetPosition + Vector3.up * 15f;
endPosition = targetPosition;
ShowIndicator();
elapsedTime = 0f;
var fill = 1 / CastingTime;
while (elapsedTime < CastingTime)
{
elapsedTime += Time.deltaTime;
if (isUsingIndicator)
{
var fillValue = indicator.material.GetFloat(FillHash) + Time.deltaTime * fill;
if (indicator)
{
indicator.material.SetFloat(FillHash, fillValue);
}
if (stunIndicator)
{
stunIndicator.material.SetFloat(FillHash, fillValue);
}
}
yield return null;
}
IgnoreCollision(true);
elapsedTime = 0f;
while (elapsedTime < downTime)
{
elapsedTime += Time.deltaTime;
SkillInputData.PlayerRb.position = Vector3.Lerp(startPosition, endPosition, elapsedTime / downTime);
yield return null;
}
VisualFeedbackManager.Inst.CameraShake(CameraManager.Inst.CombatCamera.BaseCombatCamera, 3f, 1f);
SkillInputData.PlayerRb.useGravity = true;
SkillInputData.PlayerAgent.enabled = true;
SkillInputData.PlayerRb.position = endPosition;
var targetToVector = SkillInputData.TargetCollider.transform.position - SkillInputData.PlayerCollider.transform.position;
targetToVector.y = 0f;
var playerRadius = ((CapsuleCollider)SkillInputData.PlayerCollider).radius;
if (targetToVector.magnitude < playerRadius)
{
var direction = targetToVector.normalized;
direction = direction == Vector3.zero ? Vector3.right : direction;
SkillInputData.TargetCollider.transform.GetComponent<Rigidbody>().AddForce(direction * 70f, ForceMode.Impulse);
CoolDown(1f, () => IgnoreCollision(false));
}
else
{
IgnoreCollision(false);
}
HideIndicator();
var maxSize = Physics.OverlapSphereNonAlloc(transform.position, Range, hitColliders, SkillInputData.TargetLayer);
for (var i = 0; i < maxSize; i++)
{
var iDamageable = hitColliders[i].GetComponent<IDamageable>();
iDamageable?.TakeDamage(Damage);
}
maxSize = Physics.OverlapSphereNonAlloc(transform.position, Range * 2f, hitColliders, SkillInputData.TargetLayer);
for (var i = 0; i < maxSize; i++)
{
var physicsMovement = hitColliders[i].GetComponent<PhysicsMovement>();
if (physicsMovement != null && !physicsMovement.MyCurrentState.isDashing)
{
StartCoroutine(StunCoroutine(physicsMovement));
}
}
SkillInputData.PlayerAnimator.SetBool("isJump", false);
SkillInputData.PlayerAnimator.SetTrigger("isSmash");
actions[0].Invoke();
}
private IEnumerator StunCoroutine(PhysicsMovement physicsMovement)
{
physicsMovement.MyCurrentState.isMoving = false;
physicsMovement.MyCurrentState.IsStunned = true;
var elapsedTime = 0f;
while (elapsedTime < stunTime)
{
elapsedTime += Time.deltaTime;
yield return null;
}
physicsMovement.MyCurrentState.IsStunned = false;
}
private void IgnoreCollision(bool value)
{
Physics.IgnoreCollision(SkillInputData.PlayerCollider, SkillInputData.TargetCollider, value);
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ef339f855b0080641b375baefaddb1d0

View File

@ -0,0 +1,145 @@
using System;
using System.Collections;
using BlueWaterProject;
using Sirenix.OdinInspector;
using UnityEngine;
// ReSharper disable once CheckNamespace
namespace RhinocerosSkill
{
public class LineRush : SkillBase
{
[Title("추가 옵션")]
[SerializeField] private bool isDrawingGizmo = true;
[SerializeField] private float width = 3f;
[SerializeField] private float rushSpeed = 15f;
[SerializeField] private float rushOffset = 3f;
private bool isUsingSkill;
private Vector3 startPosition;
private float distanceToTarget;
private Vector3 direction;
private RaycastHit[] hits;
private bool isAttacked;
private void OnDrawGizmos()
{
if (!isDrawingGizmo || !isUsingSkill) return;
if (SkillInputData.PlayerCollider is CapsuleCollider capsuleCollider)
{
var capsuleRadius = capsuleCollider.radius;
var point1 = SkillInputData.PlayerRb.position + Vector3.up * capsuleRadius;
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(point1, capsuleRadius);
}
}
public override void ActivateSkill(params Action[] actions)
{
ReadySkill = false;
SkillInputData.PlayerAnimator.SetBool("isLineRush", true);
CoolDown(Cooldown, () => ReadySkill = true);
StartCoroutine(SkillCoroutine(actions));
}
public override bool EnableSkill()
{
if (!ReadySkill) return false;
return true;
}
protected override void BasicSetting()
{
base.BasicSetting();
hits = new RaycastHit[5];
}
private IEnumerator SkillCoroutine(params Action[] actions)
{
while (!SkillInputData.PlayerAnimator.GetCurrentAnimatorStateInfo(0).IsName("LineRush"))
{
yield return null;
}
isUsingSkill = true;
isAttacked = false;
startPosition = SkillInputData.PlayerRb.position;
var vectorToTarget = SkillInputData.TargetCollider.transform.position - startPosition;
vectorToTarget.y = 0f;
direction = vectorToTarget.normalized;
distanceToTarget = vectorToTarget.magnitude + rushOffset;
transform.position = startPosition;
transform.localScale = new Vector3(width, 6f, distanceToTarget * 2);
var angle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0, angle, 0);
actions[1].Invoke();
ShowIndicator();
var elapsedTime = 0f;
var fill = 1 / CastingTime;
while (elapsedTime < CastingTime)
{
elapsedTime += Time.deltaTime;
if (isUsingIndicator && indicator)
{
var fillValue = indicator.material.GetFloat(FillHash) + Time.deltaTime * fill;
indicator.material.SetFloat(FillHash, fillValue);
}
yield return null;
}
HideIndicator();
SkillInputData.PlayerAgent.enabled = false;
SkillInputData.PlayerRb.isKinematic = false;
var timeToReachTarget = distanceToTarget / rushSpeed;
elapsedTime = 0f;
var capsuleCollider = (CapsuleCollider)SkillInputData.PlayerCollider;
var capsuleRadius = capsuleCollider.radius;
while (elapsedTime < timeToReachTarget)
{
SkillInputData.PlayerRb.velocity = direction * rushSpeed;
elapsedTime += Time.deltaTime;
var playerPosition = SkillInputData.PlayerRb.position;
var point1 = playerPosition + Vector3.up * capsuleRadius;
var point2 = playerPosition + Vector3.up * (capsuleCollider.height - capsuleRadius);
var maxSize = Physics.CapsuleCastNonAlloc(point1, point2, capsuleRadius, direction, hits,
0f, SkillInputData.TargetLayer, QueryTriggerInteraction.Ignore);
for (var i = 0; i < maxSize; i++)
{
if (!isAttacked)
{
var iDamageable = hits[i].transform.GetComponent<IDamageable>();
iDamageable?.TakeDamage(Damage);
isAttacked = true;
}
}
yield return null;
}
SkillInputData.PlayerRb.velocity = Vector3.zero;
SkillInputData.PlayerAgent.enabled = true;
SkillInputData.PlayerRb.isKinematic = true;
actions[0].Invoke();
isUsingSkill = false;
SkillInputData.PlayerAnimator.SetBool("isLineRush", false);
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 1f6a1d28ac8854842965166f68f3ab4b

Some files were not shown because too many files have changed in this diff Show More