From cf2d0d1ba3eea4f181f8b6ef579dc7ab6c61d997 Mon Sep 17 00:00:00 2001 From: Code_Cube Date: Thu, 3 Oct 2019 20:03:03 -0700 Subject: [PATCH 01/14] Loaded project. --- .vscode/settings.json | 56 +++++++++++++++++++ .../SteamVR/Resources/SteamVR_Settings.asset | 4 +- 2 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..4edd970 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,56 @@ +{ + "files.exclude": + { + "**/.DS_Store":true, + "**/.git":true, + "**/.gitignore":true, + "**/.gitmodules":true, + "**/*.booproj":true, + "**/*.pidb":true, + "**/*.suo":true, + "**/*.user":true, + "**/*.userprefs":true, + "**/*.unityproj":true, + "**/*.dll":true, + "**/*.exe":true, + "**/*.pdf":true, + "**/*.mid":true, + "**/*.midi":true, + "**/*.wav":true, + "**/*.gif":true, + "**/*.ico":true, + "**/*.jpg":true, + "**/*.jpeg":true, + "**/*.png":true, + "**/*.psd":true, + "**/*.tga":true, + "**/*.tif":true, + "**/*.tiff":true, + "**/*.3ds":true, + "**/*.3DS":true, + "**/*.fbx":true, + "**/*.FBX":true, + "**/*.lxo":true, + "**/*.LXO":true, + "**/*.ma":true, + "**/*.MA":true, + "**/*.obj":true, + "**/*.OBJ":true, + "**/*.asset":true, + "**/*.cubemap":true, + "**/*.flare":true, + "**/*.mat":true, + "**/*.meta":true, + "**/*.prefab":true, + "**/*.unity":true, + "build/":true, + "Build/":true, + "Library/":true, + "library/":true, + "obj/":true, + "Obj/":true, + "ProjectSettings/":true, + "temp/":true, + "Temp/":true + } +} \ No newline at end of file diff --git a/Assets/SteamVR/Resources/SteamVR_Settings.asset b/Assets/SteamVR/Resources/SteamVR_Settings.asset index 532c853..9b8722d 100644 --- a/Assets/SteamVR/Resources/SteamVR_Settings.asset +++ b/Assets/SteamVR/Resources/SteamVR_Settings.asset @@ -24,7 +24,7 @@ MonoBehaviour: autoEnableVR: 1 legacyMixedRealityCamera: 1 mixedRealityCameraPose: - actionPath: /actions//in/ExternalCamera - needsReinit: 1 + actionPath: /actions/mixedreality/in/ExternalCamera + needsReinit: 0 mixedRealityCameraInputSource: 11 mixedRealityActionSetAutoEnable: 1 From d3e42bf6912c17748af54711d76745b1ac893adc Mon Sep 17 00:00:00 2001 From: Code_Cube Date: Thu, 3 Oct 2019 22:10:58 -0700 Subject: [PATCH 02/14] Got things to play nice on linux / vs code. --- .vscode/settings.json | 82 ++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 51 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 4edd970..2820d35 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,56 +1,36 @@ { "files.exclude": { - "**/.DS_Store":true, - "**/.git":true, - "**/.gitignore":true, - "**/.gitmodules":true, - "**/*.booproj":true, - "**/*.pidb":true, - "**/*.suo":true, - "**/*.user":true, - "**/*.userprefs":true, - "**/*.unityproj":true, - "**/*.dll":true, - "**/*.exe":true, - "**/*.pdf":true, - "**/*.mid":true, - "**/*.midi":true, - "**/*.wav":true, - "**/*.gif":true, - "**/*.ico":true, - "**/*.jpg":true, - "**/*.jpeg":true, - "**/*.png":true, - "**/*.psd":true, - "**/*.tga":true, - "**/*.tif":true, - "**/*.tiff":true, - "**/*.3ds":true, - "**/*.3DS":true, - "**/*.fbx":true, - "**/*.FBX":true, - "**/*.lxo":true, - "**/*.LXO":true, - "**/*.ma":true, - "**/*.MA":true, - "**/*.obj":true, - "**/*.OBJ":true, - "**/*.asset":true, - "**/*.cubemap":true, - "**/*.flare":true, - "**/*.mat":true, - "**/*.meta":true, - "**/*.prefab":true, - "**/*.unity":true, - "build/":true, - "Build/":true, - "Library/":true, - "library/":true, - "obj/":true, - "Obj/":true, - "ProjectSettings/":true, - "temp/":true, - "Temp/":true + "**/.DS_Store": true, + "**/.git": false, + "**/.git/": true, + "**/.gitattributes": true, + "**/.gitmodules": true, + "**/*.meta": true, + "build/": true, + "Build/": true, + "library/": true, + "Library/": true, + "obj/": true, + "Obj/": true, + "ProjectSettings/": true, + "temp/": true, + "Temp/": true + }, + "files.watcherExclude": { + "**/.git/**": true, + "**/.git/objects/**": false, + "**/.git/subtree-cache/**": false, + "**/*.meta": true, + "**/build/**": true, + "**/Build/**": true, + "**/library/**": true, + "**/Library/**": true, + "**/obj/**": true, + "**/Obj/**": true, + "**/ProjectSettings/**": true, + "**/SteamVR*/**": true, + "**/temp/**": true, + "**/Temp/**": true } } \ No newline at end of file From 5dbab92b364f78a1df808a1322e9b2fea41e2989 Mon Sep 17 00:00:00 2001 From: Code_Cube Date: Thu, 3 Oct 2019 22:33:32 -0700 Subject: [PATCH 03/14] Added basic grid world. --- Assets/Prefabs.meta | 8 + Assets/Prefabs/Grid World.prefab | 49 +++++ Assets/Prefabs/Grid World.prefab.meta | 7 + Assets/Scenes/GridTest.unity | 296 ++++++++++++++++++++++++++ Assets/Scenes/GridTest.unity.meta | 7 + Assets/Scripts.meta | 8 + Assets/Scripts/GridWorld.cs | 62 ++++++ Assets/Scripts/GridWorld.cs.meta | 11 + 8 files changed, 448 insertions(+) create mode 100644 Assets/Prefabs.meta create mode 100644 Assets/Prefabs/Grid World.prefab create mode 100644 Assets/Prefabs/Grid World.prefab.meta create mode 100644 Assets/Scenes/GridTest.unity create mode 100644 Assets/Scenes/GridTest.unity.meta create mode 100644 Assets/Scripts.meta create mode 100644 Assets/Scripts/GridWorld.cs create mode 100644 Assets/Scripts/GridWorld.cs.meta diff --git a/Assets/Prefabs.meta b/Assets/Prefabs.meta new file mode 100644 index 0000000..ef75d7f --- /dev/null +++ b/Assets/Prefabs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d0dcdbe3b3317acc981af26ab72c85d4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/Grid World.prefab b/Assets/Prefabs/Grid World.prefab new file mode 100644 index 0000000..cf01a1e --- /dev/null +++ b/Assets/Prefabs/Grid World.prefab @@ -0,0 +1,49 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &6466675777360773743 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6159513309455308054} + - component: {fileID: 5166608720900095202} + m_Layer: 0 + m_Name: Grid World + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &6159513309455308054 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6466675777360773743} + 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_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &5166608720900095202 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6466675777360773743} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0c1492f8fc8e71355ae6643b3dba3cdf, type: 3} + m_Name: + m_EditorClassIdentifier: + cellSize: 1 + neutralZone: 4 + width: 4 + length: 4 diff --git a/Assets/Prefabs/Grid World.prefab.meta b/Assets/Prefabs/Grid World.prefab.meta new file mode 100644 index 0000000..b137e04 --- /dev/null +++ b/Assets/Prefabs/Grid World.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: cc76d76453b9adefe9c6bb2dd95e66b3 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/GridTest.unity b/Assets/Scenes/GridTest.unity new file mode 100644 index 0000000..93ca008 --- /dev/null +++ b/Assets/Scenes/GridTest.unity @@ -0,0 +1,296 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 1 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 1 +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &17071637 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 17071639} + - component: {fileID: 17071638} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &17071638 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 17071637} + m_Enabled: 1 + serializedVersion: 9 + m_Type: 1 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.802082 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 4 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &17071639 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 17071637} + m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!1 &825819305 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 825819308} + - component: {fileID: 825819307} + - component: {fileID: 825819306} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &825819306 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 825819305} + m_Enabled: 1 +--- !u!20 &825819307 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 825819305} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &825819308 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 825819305} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Assets/Scenes/GridTest.unity.meta b/Assets/Scenes/GridTest.unity.meta new file mode 100644 index 0000000..1edc07f --- /dev/null +++ b/Assets/Scenes/GridTest.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 7061b8f661c5fdc0dbe18b71fc0b7dad +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts.meta b/Assets/Scripts.meta new file mode 100644 index 0000000..9a78ad0 --- /dev/null +++ b/Assets/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f1963532d529281b982aca4f76e5e5f1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/GridWorld.cs b/Assets/Scripts/GridWorld.cs new file mode 100644 index 0000000..d173cb6 --- /dev/null +++ b/Assets/Scripts/GridWorld.cs @@ -0,0 +1,62 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class GridWorld : MonoBehaviour +{ + public float cellSize = 1.0f, neutralZone = 4.0f; + public int width = 4, length = 4; + + // Start is called before the first frame update + void Start() + { + + } + + // Update is called once per frame + void Update() + { + + } + + void OnDrawGizmos() { + Gizmos.color = Color.white; + Vector3 neutralZoneOffset = Vector3.forward * (neutralZone / 2); + Vector3 totalLength = Vector3.forward * (cellSize * length); + Vector3 totalWidth = Vector3.right * (cellSize * width); + Vector3 cellWidth = Vector3.right * cellSize; + Vector3 cellLength = Vector3.forward * cellSize; + + // Negative X, negative Z corner of the player's grid. + Vector3 playerGridCorner = -neutralZoneOffset - totalLength - totalWidth / 2; + // <= because we also want to draw a line on the right-hand side of the last grid cell. + for (int x = 0; x <= width; x++) { + Gizmos.DrawLine( + playerGridCorner + cellWidth * x, + playerGridCorner + cellWidth * x + totalLength + ); + } + for (int z = 0; z <= length; z++) { + Gizmos.DrawLine( + playerGridCorner + cellLength * z, + playerGridCorner + cellLength * z + totalWidth + ); + } + + // Negative X, negative Z corner of the enemy grid. + Vector3 enemyGridCorner = neutralZoneOffset - totalWidth / 2; + // <= because we also want to draw a line on the right-hand side of the last grid cell. + for (int x = 0; x <= width; x++) { + Gizmos.DrawLine( + enemyGridCorner + cellWidth * x, + enemyGridCorner + cellWidth * x + totalLength + ); + } + for (int z = 0; z <= length; z++) { + Gizmos.DrawLine( + enemyGridCorner + cellLength * z, + enemyGridCorner + cellLength * z + totalWidth + ); + } + } +} diff --git a/Assets/Scripts/GridWorld.cs.meta b/Assets/Scripts/GridWorld.cs.meta new file mode 100644 index 0000000..0bcb139 --- /dev/null +++ b/Assets/Scripts/GridWorld.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0c1492f8fc8e71355ae6643b3dba3cdf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 2d75cd62d4430fb6c26f7f692e2852cfb356f06e Mon Sep 17 00:00:00 2001 From: Code_Cube Date: Fri, 4 Oct 2019 00:38:26 -0700 Subject: [PATCH 04/14] Fleshed out capabilities of grid. --- Assets/Scripts/GridDweller.cs | 69 ++++++++++ Assets/Scripts/GridDweller.cs.meta | 11 ++ Assets/Scripts/GridWorld.cs | 212 +++++++++++++++++++++++++++-- 3 files changed, 278 insertions(+), 14 deletions(-) create mode 100644 Assets/Scripts/GridDweller.cs create mode 100644 Assets/Scripts/GridDweller.cs.meta diff --git a/Assets/Scripts/GridDweller.cs b/Assets/Scripts/GridDweller.cs new file mode 100644 index 0000000..6410fdc --- /dev/null +++ b/Assets/Scripts/GridDweller.cs @@ -0,0 +1,69 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class GridDweller : MonoBehaviour { + public CellContents type = CellContents.Player; + public CellPosition position = new CellPosition(); + public GridWorld dwellsOn; + + // Start is called before the first frame update + void Start() { + SyncRealPositionToCellPosition(); + dwellsOn.SetContentsInCell(position, type); + } + + // Update is called once per frame + void Update() { + + } + + /// Moves the real (screen) position of this object to whatever its position in the grid world + /// is. (Grid world position is set with MoveToCell()). Call this if you want changes made with + /// MoveToCell() to be reflected verbatim on screen. + public void SyncRealPositionToCellPosition() { + if (position != null) { + gameObject.transform.position = dwellsOn.GetRealPosition(position); + } + } + + /// Determines which cell the object is occupying based on its real (screen) position and then + /// moves this object's cell position to that cell. Call this if you want manual changes to the + /// object's position to be reflected in the game logic. + public void SyncCellPositionToRealPosition() { + position = dwellsOn.GridizeRealPosition(gameObject.transform.position); + } + + /// Tries to move to a different cell on the grid. Note that this does NOT change the REAL + /// position of the object. It will appear in the same position in the world. This method just + /// changes which cell it is marked as occupying. If the selected cell is not empty, an + /// exception will be thrown detailing exactly what lead to that error occuring. If null is + /// passed as newPosition, the object will be effectively 'removed' from the grid world. Moving + /// to a non-null cell will 'place' the object back in the world. + public void MoveToCell(CellPosition newPosition) { + if (position != null) dwellsOn.SetContentsInCell(position, CellContents.Empty); + position = newPosition; + if (position != null) dwellsOn.SetContentsInCell(position, type); + } + + /// Like MoveToCell(CellPosition), but moves to a different position on whatever side of the + /// world this object is already on. For example, if the object is on the Enemy side, it will + /// try to move to the cell on the enemy side with the specified coordinates. + public void MoveToCell(uint x, uint z) { + MoveToCell(new CellPosition(x, z, position.side)); + } + + /// Like MoveToCell(CellPosition), but returns false in place of throwing an exception. + public bool SafeMoveToCell(CellPosition newPosition) { + if (newPosition != null && !dwellsOn.IsCellEmpty(newPosition)) { + return false; + } + MoveToCell(newPosition); + return true; + } + + /// Like MoveToCell(uint, uint), but returns false in place of throwing an exception. + public bool SafeMoveToCell(uint x, uint z) { + return SafeMoveToCell(new CellPosition(x, z, position.side)); + } +} diff --git a/Assets/Scripts/GridDweller.cs.meta b/Assets/Scripts/GridDweller.cs.meta new file mode 100644 index 0000000..d237e63 --- /dev/null +++ b/Assets/Scripts/GridDweller.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 38fd45c0c01b83cd78e53d3e19e28c9b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/GridWorld.cs b/Assets/Scripts/GridWorld.cs index d173cb6..7fa2b7b 100644 --- a/Assets/Scripts/GridWorld.cs +++ b/Assets/Scripts/GridWorld.cs @@ -1,26 +1,177 @@ -using System.Collections; -using System.Collections.Generic; +using System; using UnityEngine; -public class GridWorld : MonoBehaviour -{ +public enum CellContents { + Empty, + Player, + Enemy +} + +public enum GridClass { + PlayerGrid, + EnemyGrid +} + +[Serializable] +public class CellPosition { + public uint x, z; + public GridClass side; + + public CellPosition() { + this.x = 0; + this.z = 0; + this.side = GridClass.PlayerGrid; + } + + public CellPosition(uint x, uint z, GridClass side) { + this.x = x; + this.z = z; + this.side = side; + } +} + +public class InvalidCellPositionException : Exception { + public InvalidCellPositionException(CellPosition position, GridWorld world) + : base(String.Format( + "Grid position ({0},{1}) is outside the bounds of ({2},{3})", + position.x, + position.z, + world.width, + world.length + )) + { } +} + +public class CellAlreadyOccupiedException: Exception { + public CellAlreadyOccupiedException( + CellPosition position, + CellContents type, + CellContents existing + ) : base(String.Format( + "Tried to place a {0} on ({1}, {2}) where there was already a {3}.", + type, + position.x, + position.z, + existing + )) + { } +} + +/// Holds data for the in-game grid, like which squares are occupied. It is not responsible for +/// drawing this information inside the game. Instead, other objects can use helper methods from +/// this class to determine which grid squares are occupied and present graphics accordingly. +public class GridWorld : MonoBehaviour { public float cellSize = 1.0f, neutralZone = 4.0f; public int width = 4, length = 4; + private CellContents[,] playerSideContents, enemySideContents; - // Start is called before the first frame update - void Start() - { - + /// We need to put this in Awake() because GridDwellers will try and place themselves on the + /// grid with Start(), so the arrays that hold that data needs to be initialized before any + /// Start() methods run. + void Awake() { + playerSideContents = new CellContents[width, length]; + enemySideContents = new CellContents[width, length]; + for (uint x = 0; x < width; x++) { + for (uint z = 0; z < length; z++) { + playerSideContents[x, z] = CellContents.Empty; + enemySideContents[x, z] = CellContents.Empty; + } + } } - // Update is called once per frame - void Update() - { - + /// Returns false if CellPosition is outside the bounds of this grid world. + public bool IsValid(CellPosition cellPosition) { + return cellPosition.x < width && cellPosition.z < length; + } + + public CellContents GetContentsInCell(CellPosition position) { + if (!IsValid(position)) { + throw new InvalidCellPositionException(position, this); + } + if (position.side == GridClass.PlayerGrid) { + return playerSideContents[position.x, position.z]; + } else { + return enemySideContents[position.x, position.z]; + } + } + + public bool IsCellEmpty(CellPosition position) { + return GetContentsInCell(position) == CellContents.Empty; + } + + /// This method should only be used by GridDweller. Use that component to represent something on + /// the grid. Never interact with this method directly. Throws an exception if trying to set + /// a non-emtpy cell to something non-empty, or if trying to set an empty cell as empty again. + public void SetContentsInCell(CellPosition position, CellContents contents) { + CellContents existing = GetContentsInCell(position); + if ( + existing == CellContents.Empty && contents == CellContents.Empty + || existing != CellContents.Empty && contents != CellContents.Empty + ) { + throw new CellAlreadyOccupiedException(position, contents, existing); + } + if (position.side == GridClass.PlayerGrid) { + playerSideContents[position.x, position.z] = contents; + } else { + enemySideContents[position.x, position.z] = contents; + } + } + + /// Returns a Vector3 indicating the real-world position of the center of the specified cell. + /// Throws an InvalidCellPositionException if the provided grid position is outside the bounds + /// of this grid world. + public Vector3 GetRealPosition(CellPosition cellPosition) { + if (!IsValid(cellPosition)) { + throw new InvalidCellPositionException(cellPosition, this); + } + Vector3 position = Vector3.zero; + if (cellPosition.side == GridClass.PlayerGrid) { + // Player grid is in the -Z direction. + position += Vector3.back * (neutralZone / 2 + cellSize * length); + } else { + // Enemy grid is in the +Z direction. + position += Vector3.forward * neutralZone / 2; + } + position += Vector3.left * (cellSize * width / 2); + // Position is now at the negative X, Z corner of whichever side cellPosition is on. + + // Add in an offset based on the actual x and z coordinates of cellPosition. At the same + // time, add an offset of (cellSize / 2) so that we are centered in the middle of the cell. + position += Vector3.right * (cellSize * cellPosition.x + cellSize / 2); + position += Vector3.forward * (cellSize * cellPosition.z + cellSize / 2); + + return position; + } + + /// Attempts to determine which cell the given world position lies in. If it is not inside the + /// bounds of either the player or enemy grid, null is returned instead. + public CellPosition GridizeRealPosition(Vector3 realPosition) { + bool isOnEnemyGrid = realPosition.z > 0; // Enemy grid is in the +z direction. + // Reorient the coordinate system so that 0, 0 is at the 0, 0 corner of the enemy grid + if (isOnEnemyGrid) { + realPosition -= Vector3.forward * (neutralZone / 2); + realPosition += Vector3.right * (cellSize * width / 2); + } else { // Player grid is in the -z direction; + realPosition -= Vector3.back * (neutralZone / 2); + realPosition -= Vector3.back * (cellSize * length); + realPosition += Vector3.right * (cellSize * width / 2); + } + // Scale the coordinate system so each cell is one square unit. + realPosition /= cellSize; + // Floor to find out which integer cell we are in. + int x = Mathf.FloorToInt(realPosition.x), z = Mathf.FloorToInt(realPosition.z); + // If we are out of bounds, return false. + if (x < 0 || z < 0 || x >= width || z >= width) { + return null; + } + // Otherwise, package up the coordinates we found. + return new CellPosition( + // V V We already checked that they are >= 0, so this cast is safe. + (uint) x, (uint) z, isOnEnemyGrid ? GridClass.EnemyGrid : GridClass.PlayerGrid + ); } void OnDrawGizmos() { - Gizmos.color = Color.white; Vector3 neutralZoneOffset = Vector3.forward * (neutralZone / 2); Vector3 totalLength = Vector3.forward * (cellSize * length); Vector3 totalWidth = Vector3.right * (cellSize * width); @@ -29,6 +180,11 @@ void OnDrawGizmos() { // Negative X, negative Z corner of the player's grid. Vector3 playerGridCorner = -neutralZoneOffset - totalLength - totalWidth / 2; + Gizmos.color = Color.blue; + Gizmos.DrawLine( + playerGridCorner, + playerGridCorner + (Vector3.left + Vector3.back) * (cellSize / 5) + ); // <= because we also want to draw a line on the right-hand side of the last grid cell. for (int x = 0; x <= width; x++) { Gizmos.DrawLine( @@ -42,9 +198,26 @@ void OnDrawGizmos() { playerGridCorner + cellLength * z + totalWidth ); } - + if (playerSideContents != null) { + for (int x = 0; x < width; x++) { + for (int z = 0; z < length; z++) { + CellContents c = playerSideContents[x, z]; + if (c == CellContents.Player) DrawDiamondGizmo( + playerGridCorner + cellWidth * x + cellLength * z, Color.blue + ); else if (c == CellContents.Enemy) DrawDiamondGizmo( + playerGridCorner + cellWidth * x + cellLength * z, Color.red + ); + } + } + } + // Negative X, negative Z corner of the enemy grid. Vector3 enemyGridCorner = neutralZoneOffset - totalWidth / 2; + Gizmos.color = Color.red; + Gizmos.DrawLine( + enemyGridCorner, + enemyGridCorner + (Vector3.left + Vector3.back) * (cellSize / 5) + ); // <= because we also want to draw a line on the right-hand side of the last grid cell. for (int x = 0; x <= width; x++) { Gizmos.DrawLine( @@ -59,4 +232,15 @@ void OnDrawGizmos() { ); } } + + void DrawDiamondGizmo(Vector3 position, Color color) { + Vector3 x10 = Vector3.right * cellSize, z10 = Vector3.forward * cellSize; + Vector3 x2 = x10 / 5, x5 = x10 / 2, z2 = z10 / 5, z5 = z10 / 2; + + Gizmos.color = color; + Gizmos.DrawLine(position + x2 + z5, position + x5 + z10 - z2); + Gizmos.DrawLine(position + x10 - x2 + z5, position + x5 + z10 - z2); + Gizmos.DrawLine(position + x10 - x2 + z5, position + x5 + z2); + Gizmos.DrawLine(position + x2 + z5, position + x5 + z2); + } } From 90808bf02564130c61e337bf3462b2c56bd48417 Mon Sep 17 00:00:00 2001 From: Code_Cube Date: Fri, 4 Oct 2019 01:26:41 -0700 Subject: [PATCH 05/14] Added three possible uses of the grid system. --- Assets/Scripts/AnimatedExample.cs | 26 +++++++++ Assets/Scripts/AnimatedExample.cs.meta | 11 ++++ Assets/Scripts/GridDweller.cs | 4 +- Assets/Scripts/HopperExample.cs | 77 ++++++++++++++++++++++++++ Assets/Scripts/HopperExample.cs.meta | 11 ++++ Assets/Scripts/SnappyExample.cs | 41 ++++++++++++++ Assets/Scripts/SnappyExample.cs.meta | 11 ++++ 7 files changed, 179 insertions(+), 2 deletions(-) create mode 100644 Assets/Scripts/AnimatedExample.cs create mode 100644 Assets/Scripts/AnimatedExample.cs.meta create mode 100644 Assets/Scripts/HopperExample.cs create mode 100644 Assets/Scripts/HopperExample.cs.meta create mode 100644 Assets/Scripts/SnappyExample.cs create mode 100644 Assets/Scripts/SnappyExample.cs.meta diff --git a/Assets/Scripts/AnimatedExample.cs b/Assets/Scripts/AnimatedExample.cs new file mode 100644 index 0000000..af8017f --- /dev/null +++ b/Assets/Scripts/AnimatedExample.cs @@ -0,0 +1,26 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +/// One option for doing movement in the game is having enemies capable of performing arbitrary +/// animations and then updating their cell position based on where they are currently positioned. +/// This is nice and simple but can cause problems with enemies overlapping each other on screen +/// and thus not having properly updated grid positions. +public class AnimatedExample : MonoBehaviour { + GridDweller dweller; + float timer = 0.0f; + void Start() { + dweller = GetComponent(); + } + + // Update is called once per frame + void Update() { + timer += Time.deltaTime; + // Move the position of our object. + gameObject.transform.position = + Vector3.forward * Mathf.Sin(timer) * 5.0f + + Vector3.left * Mathf.Cos(timer * 5); + // Update which cell we are currently in. + dweller.SyncCellPositionToRealPosition(); + } +} diff --git a/Assets/Scripts/AnimatedExample.cs.meta b/Assets/Scripts/AnimatedExample.cs.meta new file mode 100644 index 0000000..32a9731 --- /dev/null +++ b/Assets/Scripts/AnimatedExample.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5bd11d9d35311785f98a9a865047857c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/GridDweller.cs b/Assets/Scripts/GridDweller.cs index 6410fdc..01316a6 100644 --- a/Assets/Scripts/GridDweller.cs +++ b/Assets/Scripts/GridDweller.cs @@ -4,8 +4,8 @@ public class GridDweller : MonoBehaviour { public CellContents type = CellContents.Player; - public CellPosition position = new CellPosition(); public GridWorld dwellsOn; + private CellPosition position = null; // Start is called before the first frame update void Start() { @@ -31,7 +31,7 @@ public void SyncRealPositionToCellPosition() { /// moves this object's cell position to that cell. Call this if you want manual changes to the /// object's position to be reflected in the game logic. public void SyncCellPositionToRealPosition() { - position = dwellsOn.GridizeRealPosition(gameObject.transform.position); + SafeMoveToCell(dwellsOn.GridizeRealPosition(gameObject.transform.position)); } /// Tries to move to a different cell on the grid. Note that this does NOT change the REAL diff --git a/Assets/Scripts/HopperExample.cs b/Assets/Scripts/HopperExample.cs new file mode 100644 index 0000000..2d14659 --- /dev/null +++ b/Assets/Scripts/HopperExample.cs @@ -0,0 +1,77 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +enum Mode { + Wait, + Animate, +} + + +/// One option is to pick a grid square to move to and play an animation to get there. This is the +/// most complicated option but I think it would be worth it. +public class HopperExample : MonoBehaviour { + const float WAIT_TIME = 1.0f; + const float ANIMATE_TIME = 0.5f; + const float ANIMATION_HEIGHT = 3.0f; + GridDweller dweller; + CellPosition[] patrol = { + new CellPosition(0, 0, GridClass.EnemyGrid), + new CellPosition(2, 0, GridClass.EnemyGrid), + new CellPosition(2, 2, GridClass.EnemyGrid), + new CellPosition(0, 2, GridClass.EnemyGrid), + new CellPosition(3, 3, GridClass.EnemyGrid), + new CellPosition(1, 3, GridClass.EnemyGrid), + new CellPosition(1, 1, GridClass.EnemyGrid), + new CellPosition(3, 1, GridClass.EnemyGrid), + }; + Mode mode = Mode.Wait; + uint patrolStep = 0; + float timer = 0.0f; + Vector3 animationStart, animationEnd; + + void Start() { + dweller = GetComponent(); + dweller.MoveToCell(patrol[patrolStep]); + dweller.SyncRealPositionToCellPosition(); + patrolStep++; + } + + /// Roots at x=0 and x=1, vertex at (0.5, 1.0). + float ParabolicCurve(float progress) { + return 1.0f - Mathf.Pow(2 * progress - 1, 2.0f); + } + + void Update() { + timer += Time.deltaTime; + + if (mode == Mode.Wait && timer >= WAIT_TIME) { + // Wait time is over, fire up the animation. + timer -= WAIT_TIME; + mode = Mode.Animate; + // Start the anim at the current position... + animationStart = dweller.dwellsOn.GetRealPosition(patrol[patrolStep]); + patrolStep++; + if (patrolStep >= patrol.Length) { + patrolStep = 0; + } + // And end it at the next position. + animationEnd = dweller.dwellsOn.GetRealPosition(patrol[patrolStep]); + } else if (mode == Mode.Animate && timer >= ANIMATE_TIME) { + timer -= ANIMATE_TIME; + mode = Mode.Wait; + // Lock us in to be exactly at the target position. + gameObject.transform.position = animationEnd; + // Update our cell position. + dweller.SyncCellPositionToRealPosition(); + } + + if (mode == Mode.Animate) { + float progress = timer / ANIMATE_TIME; + // Compute a parabolic jump animation. + gameObject.transform.position = + Vector3.Lerp(animationStart, animationEnd, progress) + + Vector3.up * ANIMATION_HEIGHT * ParabolicCurve(progress); + } + } +} diff --git a/Assets/Scripts/HopperExample.cs.meta b/Assets/Scripts/HopperExample.cs.meta new file mode 100644 index 0000000..b583ae9 --- /dev/null +++ b/Assets/Scripts/HopperExample.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a4fb156b0e1f42516bf021b2a8e9b8b8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/SnappyExample.cs b/Assets/Scripts/SnappyExample.cs new file mode 100644 index 0000000..a9cc3b2 --- /dev/null +++ b/Assets/Scripts/SnappyExample.cs @@ -0,0 +1,41 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +/// One option for doing movement in the game is to rigidly lock the enemies to a grid. This is +/// simple but results in clunky animation. +public class SnappyExample : MonoBehaviour { + GridDweller dweller; + CellPosition[] patrol = { + new CellPosition(0, 0, GridClass.PlayerGrid), + new CellPosition(1, 0, GridClass.PlayerGrid), + new CellPosition(2, 0, GridClass.PlayerGrid), + new CellPosition(3, 0, GridClass.PlayerGrid), + new CellPosition(3, 1, GridClass.PlayerGrid), + new CellPosition(3, 2, GridClass.PlayerGrid), + new CellPosition(3, 3, GridClass.PlayerGrid), + new CellPosition(2, 3, GridClass.PlayerGrid), + new CellPosition(1, 3, GridClass.PlayerGrid), + new CellPosition(0, 3, GridClass.PlayerGrid), + new CellPosition(0, 2, GridClass.PlayerGrid), + new CellPosition(0, 1, GridClass.PlayerGrid), + }; + float timer = 0.0f; + public float stepDuration = 0.5f; + + void Start() { + dweller = GetComponent(); + } + + void Update() { + timer += Time.deltaTime; + if (timer > patrol.Length * stepDuration) { + timer -= patrol.Length * stepDuration; + } + + // Set our position on the grid. This does not change our "real" aka "screen" position. + dweller.MoveToCell(patrol[Mathf.FloorToInt(timer / stepDuration)]); + // Set our real position to mimic our grid position. + dweller.SyncRealPositionToCellPosition(); + } +} diff --git a/Assets/Scripts/SnappyExample.cs.meta b/Assets/Scripts/SnappyExample.cs.meta new file mode 100644 index 0000000..d0a74e1 --- /dev/null +++ b/Assets/Scripts/SnappyExample.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0f9e3403e99c43a288dd277fb46d5206 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From eef5c7027c9cbb65da461cf4e245e6d99ef4e7fe Mon Sep 17 00:00:00 2001 From: Code_Cube Date: Fri, 4 Oct 2019 01:48:04 -0700 Subject: [PATCH 06/14] Grid world can handle multiple things in a square now. --- Assets/Scripts/GridDweller.cs | 30 +++------ Assets/Scripts/GridWorld.cs | 111 +++++++++++++++++++--------------- 2 files changed, 70 insertions(+), 71 deletions(-) diff --git a/Assets/Scripts/GridDweller.cs b/Assets/Scripts/GridDweller.cs index 01316a6..8112875 100644 --- a/Assets/Scripts/GridDweller.cs +++ b/Assets/Scripts/GridDweller.cs @@ -3,14 +3,13 @@ using UnityEngine; public class GridDweller : MonoBehaviour { - public CellContents type = CellContents.Player; + public CellItem type = CellItem.Player; public GridWorld dwellsOn; private CellPosition position = null; // Start is called before the first frame update void Start() { SyncRealPositionToCellPosition(); - dwellsOn.SetContentsInCell(position, type); } // Update is called once per frame @@ -31,19 +30,18 @@ public void SyncRealPositionToCellPosition() { /// moves this object's cell position to that cell. Call this if you want manual changes to the /// object's position to be reflected in the game logic. public void SyncCellPositionToRealPosition() { - SafeMoveToCell(dwellsOn.GridizeRealPosition(gameObject.transform.position)); + MoveToCell(dwellsOn.GridizeRealPosition(gameObject.transform.position)); } /// Tries to move to a different cell on the grid. Note that this does NOT change the REAL /// position of the object. It will appear in the same position in the world. This method just - /// changes which cell it is marked as occupying. If the selected cell is not empty, an - /// exception will be thrown detailing exactly what lead to that error occuring. If null is - /// passed as newPosition, the object will be effectively 'removed' from the grid world. Moving - /// to a non-null cell will 'place' the object back in the world. + /// changes which cell it is marked as occupying. If null is passed as newPosition, the object + /// will be effectively 'removed' from the grid world. Moving to a non-null cell will 'place' + /// the object back in the world. public void MoveToCell(CellPosition newPosition) { - if (position != null) dwellsOn.SetContentsInCell(position, CellContents.Empty); + if (position != null) dwellsOn.RemoveItemFromCell(position, type); position = newPosition; - if (position != null) dwellsOn.SetContentsInCell(position, type); + if (position != null) dwellsOn.AddItemToCell(position, type); } /// Like MoveToCell(CellPosition), but moves to a different position on whatever side of the @@ -52,18 +50,4 @@ public void MoveToCell(CellPosition newPosition) { public void MoveToCell(uint x, uint z) { MoveToCell(new CellPosition(x, z, position.side)); } - - /// Like MoveToCell(CellPosition), but returns false in place of throwing an exception. - public bool SafeMoveToCell(CellPosition newPosition) { - if (newPosition != null && !dwellsOn.IsCellEmpty(newPosition)) { - return false; - } - MoveToCell(newPosition); - return true; - } - - /// Like MoveToCell(uint, uint), but returns false in place of throwing an exception. - public bool SafeMoveToCell(uint x, uint z) { - return SafeMoveToCell(new CellPosition(x, z, position.side)); - } } diff --git a/Assets/Scripts/GridWorld.cs b/Assets/Scripts/GridWorld.cs index 7fa2b7b..306ea00 100644 --- a/Assets/Scripts/GridWorld.cs +++ b/Assets/Scripts/GridWorld.cs @@ -1,7 +1,8 @@ using System; +using System.Collections.Generic; using UnityEngine; -public enum CellContents { +public enum CellItem { Empty, Player, Enemy @@ -42,39 +43,24 @@ public InvalidCellPositionException(CellPosition position, GridWorld world) { } } -public class CellAlreadyOccupiedException: Exception { - public CellAlreadyOccupiedException( - CellPosition position, - CellContents type, - CellContents existing - ) : base(String.Format( - "Tried to place a {0} on ({1}, {2}) where there was already a {3}.", - type, - position.x, - position.z, - existing - )) - { } -} - /// Holds data for the in-game grid, like which squares are occupied. It is not responsible for /// drawing this information inside the game. Instead, other objects can use helper methods from /// this class to determine which grid squares are occupied and present graphics accordingly. public class GridWorld : MonoBehaviour { public float cellSize = 1.0f, neutralZone = 4.0f; public int width = 4, length = 4; - private CellContents[,] playerSideContents, enemySideContents; + private List[,] playerSideContents, enemySideContents; /// We need to put this in Awake() because GridDwellers will try and place themselves on the /// grid with Start(), so the arrays that hold that data needs to be initialized before any /// Start() methods run. void Awake() { - playerSideContents = new CellContents[width, length]; - enemySideContents = new CellContents[width, length]; + playerSideContents = new List[width, length]; + enemySideContents = new List[width, length]; for (uint x = 0; x < width; x++) { for (uint z = 0; z < length; z++) { - playerSideContents[x, z] = CellContents.Empty; - enemySideContents[x, z] = CellContents.Empty; + playerSideContents[x, z] = new List(); + enemySideContents[x, z] = new List(); } } } @@ -84,36 +70,51 @@ public bool IsValid(CellPosition cellPosition) { return cellPosition.x < width && cellPosition.z < length; } - public CellContents GetContentsInCell(CellPosition position) { + public int ItemCountInCell(CellPosition position) { + if (!IsValid(position)) { + throw new InvalidCellPositionException(position, this); + } + if (position.side == GridClass.PlayerGrid) { + return playerSideContents[position.x, position.z].Count; + } else { + return enemySideContents[position.x, position.z].Count; + } + } + + public bool IsItemInCell(CellPosition position, CellItem item) { if (!IsValid(position)) { throw new InvalidCellPositionException(position, this); } if (position.side == GridClass.PlayerGrid) { - return playerSideContents[position.x, position.z]; + return playerSideContents[position.x, position.z].Contains(item); } else { - return enemySideContents[position.x, position.z]; + return enemySideContents[position.x, position.z].Contains(item); } } public bool IsCellEmpty(CellPosition position) { - return GetContentsInCell(position) == CellContents.Empty; + return ItemCountInCell(position) == 0; } /// This method should only be used by GridDweller. Use that component to represent something on /// the grid. Never interact with this method directly. Throws an exception if trying to set /// a non-emtpy cell to something non-empty, or if trying to set an empty cell as empty again. - public void SetContentsInCell(CellPosition position, CellContents contents) { - CellContents existing = GetContentsInCell(position); - if ( - existing == CellContents.Empty && contents == CellContents.Empty - || existing != CellContents.Empty && contents != CellContents.Empty - ) { - throw new CellAlreadyOccupiedException(position, contents, existing); + public void AddItemToCell(CellPosition position, CellItem item) { + if (position.side == GridClass.PlayerGrid) { + playerSideContents[position.x, position.z].Add(item); + } else { + enemySideContents[position.x, position.z].Add(item); } + } + + /// This method should only be used by GridDweller. Use that component to represent something on + /// the grid. Never interact with this method directly. Throws an exception if trying to set + /// a non-emtpy cell to something non-empty, or if trying to set an empty cell as empty again. + public void RemoveItemFromCell(CellPosition position, CellItem item) { if (position.side == GridClass.PlayerGrid) { - playerSideContents[position.x, position.z] = contents; + playerSideContents[position.x, position.z].Remove(item); } else { - enemySideContents[position.x, position.z] = contents; + enemySideContents[position.x, position.z].Remove(item); } } @@ -201,12 +202,13 @@ void OnDrawGizmos() { if (playerSideContents != null) { for (int x = 0; x < width; x++) { for (int z = 0; z < length; z++) { - CellContents c = playerSideContents[x, z]; - if (c == CellContents.Player) DrawDiamondGizmo( - playerGridCorner + cellWidth * x + cellLength * z, Color.blue - ); else if (c == CellContents.Enemy) DrawDiamondGizmo( - playerGridCorner + cellWidth * x + cellLength * z, Color.red - ); + Vector3 pos = playerGridCorner + cellWidth * x + cellLength * z; + pos += (Vector3.right + Vector3.forward) * (cellSize / 2); + foreach (CellItem item in playerSideContents[x, z]) { + DrawItemGizmo(pos, item); + // Stack multiple items on the same cell. + pos += Vector3.up * 0.5f; + } } } } @@ -231,16 +233,29 @@ void OnDrawGizmos() { enemyGridCorner + cellLength * z + totalWidth ); } + if (enemySideContents != null) { + for (int x = 0; x < width; x++) { + for (int z = 0; z < length; z++) { + Vector3 pos = enemyGridCorner + cellWidth * x + cellLength * z; + pos += (Vector3.right + Vector3.forward) * (cellSize / 2); + foreach (CellItem item in enemySideContents[x, z]) { + DrawItemGizmo(pos, item); + // Stack multiple items on the same cell. + pos += Vector3.up * 0.5f; + } + } + } + } } - void DrawDiamondGizmo(Vector3 position, Color color) { - Vector3 x10 = Vector3.right * cellSize, z10 = Vector3.forward * cellSize; - Vector3 x2 = x10 / 5, x5 = x10 / 2, z2 = z10 / 5, z5 = z10 / 2; + void DrawItemGizmo(Vector3 position, CellItem item) { + if (item == CellItem.Player) { + Gizmos.color = Color.blue; + } else if (item == CellItem.Enemy) { + Gizmos.color = Color.red; + } - Gizmos.color = color; - Gizmos.DrawLine(position + x2 + z5, position + x5 + z10 - z2); - Gizmos.DrawLine(position + x10 - x2 + z5, position + x5 + z10 - z2); - Gizmos.DrawLine(position + x10 - x2 + z5, position + x5 + z2); - Gizmos.DrawLine(position + x2 + z5, position + x5 + z2); + Gizmos.DrawLine(position, position + Vector3.up * 5); + Gizmos.DrawCube(position + Vector3.up * 3, new Vector3(0.2f, 0.2f, 0.2f)); } } From 28303eeef2ae96406b49f26e4a3a473b5833e4fc Mon Sep 17 00:00:00 2001 From: Code_Cube Date: Fri, 4 Oct 2019 11:11:26 -0700 Subject: [PATCH 07/14] Forgot to save the level :P --- Assets/Scenes/GridTest.unity | 446 ++++++++++++++++++++++++++++++++++- 1 file changed, 444 insertions(+), 2 deletions(-) diff --git a/Assets/Scenes/GridTest.unity b/Assets/Scenes/GridTest.unity index 93ca008..ba4b532 100644 --- a/Assets/Scenes/GridTest.unity +++ b/Assets/Scenes/GridTest.unity @@ -211,6 +211,126 @@ Transform: m_Father: {fileID: 0} m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!1 &769384963 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 769384968} + - component: {fileID: 769384967} + - component: {fileID: 769384966} + - component: {fileID: 769384965} + - component: {fileID: 769384964} + - component: {fileID: 769384969} + m_Layer: 0 + m_Name: HopperExample + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &769384964 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 769384963} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 38fd45c0c01b83cd78e53d3e19e28c9b, type: 3} + m_Name: + m_EditorClassIdentifier: + type: 2 + dwellsOn: {fileID: 2129435950} +--- !u!65 &769384965 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 769384963} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &769384966 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 769384963} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &769384967 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 769384963} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &769384968 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 769384963} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -0.91, y: 0, z: 1.34} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &769384969 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 769384963} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a4fb156b0e1f42516bf021b2a8e9b8b8, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1 &825819305 GameObject: m_ObjectHideFlags: 0 @@ -287,10 +407,332 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 825819305} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 1, z: -10} + m_LocalRotation: {x: 0.49999994, y: 0.5, z: -0.5000003, w: 0.4999998} + m_LocalPosition: {x: 0, y: 6.63, z: -0} m_LocalScale: {x: 1, y: 1, z: 1} m_Children: [] m_Father: {fileID: 0} m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 90, y: 180, z: 89.99999} +--- !u!1 &1640058004 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1640058010} + - component: {fileID: 1640058009} + - component: {fileID: 1640058008} + - component: {fileID: 1640058007} + - component: {fileID: 1640058006} + - component: {fileID: 1640058005} + m_Layer: 0 + m_Name: AnimatedExample + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1640058005 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1640058004} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5bd11d9d35311785f98a9a865047857c, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!114 &1640058006 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1640058004} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 38fd45c0c01b83cd78e53d3e19e28c9b, type: 3} + m_Name: + m_EditorClassIdentifier: + type: 2 + dwellsOn: {fileID: 2129435950} +--- !u!65 &1640058007 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1640058004} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1640058008 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1640058004} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &1640058009 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1640058004} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1640058010 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1640058004} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -0.94, y: 0, z: -0.75} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1940135309 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1940135315} + - component: {fileID: 1940135314} + - component: {fileID: 1940135313} + - component: {fileID: 1940135312} + - component: {fileID: 1940135311} + - component: {fileID: 1940135310} + m_Layer: 0 + m_Name: SnapperExample + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1940135310 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1940135309} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0f9e3403e99c43a288dd277fb46d5206, type: 3} + m_Name: + m_EditorClassIdentifier: + stepDuration: 0.5 +--- !u!114 &1940135311 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1940135309} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 38fd45c0c01b83cd78e53d3e19e28c9b, type: 3} + m_Name: + m_EditorClassIdentifier: + type: 2 + dwellsOn: {fileID: 2129435950} +--- !u!65 &1940135312 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1940135309} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1940135313 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1940135309} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &1940135314 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1940135309} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1940135315 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1940135309} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.8, y: 0, z: 0.02} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &2129435950 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 5166608720900095202, guid: cc76d76453b9adefe9c6bb2dd95e66b3, + type: 3} + m_PrefabInstance: {fileID: 1606325940500838668} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0c1492f8fc8e71355ae6643b3dba3cdf, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1001 &1606325940500838668 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 6466675777360773743, guid: cc76d76453b9adefe9c6bb2dd95e66b3, + type: 3} + propertyPath: m_Name + value: Grid World + objectReference: {fileID: 0} + - target: {fileID: 6159513309455308054, guid: cc76d76453b9adefe9c6bb2dd95e66b3, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6159513309455308054, guid: cc76d76453b9adefe9c6bb2dd95e66b3, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6159513309455308054, guid: cc76d76453b9adefe9c6bb2dd95e66b3, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6159513309455308054, guid: cc76d76453b9adefe9c6bb2dd95e66b3, + type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6159513309455308054, guid: cc76d76453b9adefe9c6bb2dd95e66b3, + type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6159513309455308054, guid: cc76d76453b9adefe9c6bb2dd95e66b3, + type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6159513309455308054, guid: cc76d76453b9adefe9c6bb2dd95e66b3, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 6159513309455308054, guid: cc76d76453b9adefe9c6bb2dd95e66b3, + type: 3} + propertyPath: m_RootOrder + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 6159513309455308054, guid: cc76d76453b9adefe9c6bb2dd95e66b3, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6159513309455308054, guid: cc76d76453b9adefe9c6bb2dd95e66b3, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6159513309455308054, guid: cc76d76453b9adefe9c6bb2dd95e66b3, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: cc76d76453b9adefe9c6bb2dd95e66b3, type: 3} From 6ca916e5825eac24cb8999bd9665d3d90bb6a3e8 Mon Sep 17 00:00:00 2001 From: Code_Cube Date: Fri, 4 Oct 2019 12:03:37 -0700 Subject: [PATCH 08/14] Added physical grid, made some tweaks. --- Assets/Materials.meta | 8 ++ Assets/Materials/PrototypeBlue.mat | 77 +++++++++++ Assets/Materials/PrototypeBlue.mat.meta | 8 ++ Assets/Materials/PrototypeGrey.mat | 77 +++++++++++ Assets/Materials/PrototypeGrey.mat.meta | 8 ++ Assets/Materials/PrototypeRed.mat | 77 +++++++++++ Assets/Materials/PrototypeRed.mat.meta | 8 ++ Assets/Prefabs/Cell.prefab | 125 +++++++++++++++++ Assets/Prefabs/Cell.prefab.meta | 7 + Assets/Prefabs/EnemyIndicator.prefab | 125 +++++++++++++++++ Assets/Prefabs/EnemyIndicator.prefab.meta | 7 + Assets/Prefabs/PlayerIndicator.prefab | 125 +++++++++++++++++ Assets/Prefabs/PlayerIndicator.prefab.meta | 7 + Assets/Scenes/GridTest.unity | 149 ++++++++++++++++++++- Assets/Scripts/GridWorld.cs | 12 ++ Assets/Scripts/HopperExample.cs | 2 + Assets/Scripts/PhysicalGrid.cs | 75 +++++++++++ Assets/Scripts/PhysicalGrid.cs.meta | 11 ++ 18 files changed, 905 insertions(+), 3 deletions(-) create mode 100644 Assets/Materials.meta create mode 100644 Assets/Materials/PrototypeBlue.mat create mode 100644 Assets/Materials/PrototypeBlue.mat.meta create mode 100644 Assets/Materials/PrototypeGrey.mat create mode 100644 Assets/Materials/PrototypeGrey.mat.meta create mode 100644 Assets/Materials/PrototypeRed.mat create mode 100644 Assets/Materials/PrototypeRed.mat.meta create mode 100644 Assets/Prefabs/Cell.prefab create mode 100644 Assets/Prefabs/Cell.prefab.meta create mode 100644 Assets/Prefabs/EnemyIndicator.prefab create mode 100644 Assets/Prefabs/EnemyIndicator.prefab.meta create mode 100644 Assets/Prefabs/PlayerIndicator.prefab create mode 100644 Assets/Prefabs/PlayerIndicator.prefab.meta create mode 100644 Assets/Scripts/PhysicalGrid.cs create mode 100644 Assets/Scripts/PhysicalGrid.cs.meta diff --git a/Assets/Materials.meta b/Assets/Materials.meta new file mode 100644 index 0000000..d9cfd6a --- /dev/null +++ b/Assets/Materials.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b204bdb66033945b2998a9fb3e57af8c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Materials/PrototypeBlue.mat b/Assets/Materials/PrototypeBlue.mat new file mode 100644 index 0000000..b3b6a4a --- /dev/null +++ b/Assets/Materials/PrototypeBlue.mat @@ -0,0 +1,77 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: PrototypeBlue + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.558 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0, g: 0.5716195, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/Materials/PrototypeBlue.mat.meta b/Assets/Materials/PrototypeBlue.mat.meta new file mode 100644 index 0000000..bd9407e --- /dev/null +++ b/Assets/Materials/PrototypeBlue.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ab9f88402c0769547a2c7a090f1af6d9 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Materials/PrototypeGrey.mat b/Assets/Materials/PrototypeGrey.mat new file mode 100644 index 0000000..4433a16 --- /dev/null +++ b/Assets/Materials/PrototypeGrey.mat @@ -0,0 +1,77 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: PrototypeGrey + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.192 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0.5660378, g: 0.5660378, b: 0.5660378, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/Materials/PrototypeGrey.mat.meta b/Assets/Materials/PrototypeGrey.mat.meta new file mode 100644 index 0000000..331c41f --- /dev/null +++ b/Assets/Materials/PrototypeGrey.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b18aa676c8e7832a09b7acae21ed5662 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Materials/PrototypeRed.mat b/Assets/Materials/PrototypeRed.mat new file mode 100644 index 0000000..362851d --- /dev/null +++ b/Assets/Materials/PrototypeRed.mat @@ -0,0 +1,77 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: PrototypeRed + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _EMISSION + m_LightmapFlags: 1 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.609 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 1, g: 0.103773594, b: 0.103773594, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/Materials/PrototypeRed.mat.meta b/Assets/Materials/PrototypeRed.mat.meta new file mode 100644 index 0000000..0f50b6a --- /dev/null +++ b/Assets/Materials/PrototypeRed.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4eb51db75e53bb881bf754f79988c934 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/Cell.prefab b/Assets/Prefabs/Cell.prefab new file mode 100644 index 0000000..7a33d0b --- /dev/null +++ b/Assets/Prefabs/Cell.prefab @@ -0,0 +1,125 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &4312626832982465632 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7593718857162761721} + m_Layer: 0 + m_Name: Cell + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &7593718857162761721 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4312626832982465632} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -1.3045772, y: -0.71958035, z: -0.3215394} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 850907284803132359} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &5353459015872337001 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 850907284803132359} + - component: {fileID: 6905165132563712277} + - component: {fileID: 3052921385566872828} + - component: {fileID: 5069835026282644199} + m_Layer: 0 + m_Name: Cube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &850907284803132359 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5353459015872337001} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.9, y: 0.19158857, z: 0.9} + m_Children: [] + m_Father: {fileID: 7593718857162761721} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &6905165132563712277 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5353459015872337001} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &3052921385566872828 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5353459015872337001} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: b18aa676c8e7832a09b7acae21ed5662, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!65 &5069835026282644199 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5353459015872337001} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} diff --git a/Assets/Prefabs/Cell.prefab.meta b/Assets/Prefabs/Cell.prefab.meta new file mode 100644 index 0000000..1bc91c5 --- /dev/null +++ b/Assets/Prefabs/Cell.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 17e170c19d044ffe0a220abb08ae9d7d +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/EnemyIndicator.prefab b/Assets/Prefabs/EnemyIndicator.prefab new file mode 100644 index 0000000..b0204a5 --- /dev/null +++ b/Assets/Prefabs/EnemyIndicator.prefab @@ -0,0 +1,125 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &3732195104394283809 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8236840291962373263} + - component: {fileID: 2761892026788009565} + - component: {fileID: 6043270924706872244} + - component: {fileID: 4601422251162099119} + m_Layer: 0 + m_Name: Cube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8236840291962373263 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3732195104394283809} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0.125, z: 0} + m_LocalScale: {x: 0.9, y: 0.2, z: 0.9} + m_Children: [] + m_Father: {fileID: 1216651539984054961} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &2761892026788009565 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3732195104394283809} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &6043270924706872244 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3732195104394283809} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 4eb51db75e53bb881bf754f79988c934, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!65 &4601422251162099119 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3732195104394283809} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!1 &4781031086883701544 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1216651539984054961} + m_Layer: 0 + m_Name: EnemyIndicator + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1216651539984054961 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4781031086883701544} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 2.8537874, y: 0, z: -4.4023027} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 8236840291962373263} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Assets/Prefabs/EnemyIndicator.prefab.meta b/Assets/Prefabs/EnemyIndicator.prefab.meta new file mode 100644 index 0000000..dd30bc6 --- /dev/null +++ b/Assets/Prefabs/EnemyIndicator.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 993895520ab0bb667b46c52eada7ba72 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/PlayerIndicator.prefab b/Assets/Prefabs/PlayerIndicator.prefab new file mode 100644 index 0000000..74304ba --- /dev/null +++ b/Assets/Prefabs/PlayerIndicator.prefab @@ -0,0 +1,125 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &1653133395508173151 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1101810178173332474} + m_Layer: 0 + m_Name: PlayerIndicator + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1101810178173332474 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1653133395508173151} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 2.8537874, y: 0, z: -5.167} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 8951352142750061214} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &7629652522327332745 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8951352142750061214} + - component: {fileID: 2220002712130868091} + - component: {fileID: 5820070644628450190} + - component: {fileID: 3039296476964889407} + m_Layer: 0 + m_Name: Cube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8951352142750061214 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7629652522327332745} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0.354, z: 0} + m_LocalScale: {x: 0.135009, y: 0.7396468, z: 0.140013} + m_Children: [] + m_Father: {fileID: 1101810178173332474} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &2220002712130868091 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7629652522327332745} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &5820070644628450190 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7629652522327332745} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: ab9f88402c0769547a2c7a090f1af6d9, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!65 &3039296476964889407 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7629652522327332745} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} diff --git a/Assets/Prefabs/PlayerIndicator.prefab.meta b/Assets/Prefabs/PlayerIndicator.prefab.meta new file mode 100644 index 0000000..565290d --- /dev/null +++ b/Assets/Prefabs/PlayerIndicator.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: dab0478d3b2020af4b585450d724e245 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/GridTest.unity b/Assets/Scenes/GridTest.unity index ba4b532..7ab4cfc 100644 --- a/Assets/Scenes/GridTest.unity +++ b/Assets/Scenes/GridTest.unity @@ -211,6 +211,57 @@ Transform: m_Father: {fileID: 0} m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!1 &21003251 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 21003253} + - component: {fileID: 21003252} + m_Layer: 0 + m_Name: PhysicalGrid + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &21003252 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 21003251} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e564f9337cfd99775b8afcf9a56f82ea, type: 3} + m_Name: + m_EditorClassIdentifier: + gridWorld: {fileID: 2129435950} + cellPrefab: {fileID: 4312626832982465632, guid: 17e170c19d044ffe0a220abb08ae9d7d, + type: 3} + playerIndicator: {fileID: 1653133395508173151, guid: dab0478d3b2020af4b585450d724e245, + type: 3} + enemyIndicator: {fileID: 4781031086883701544, guid: 993895520ab0bb667b46c52eada7ba72, + type: 3} +--- !u!4 &21003253 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 21003251} + 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_Children: + - {fileID: 1729586188} + m_Father: {fileID: 0} + m_RootOrder: 6 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &769384963 GameObject: m_ObjectHideFlags: 0 @@ -314,7 +365,7 @@ Transform: m_GameObject: {fileID: 769384963} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: -0.91, y: 0, z: 1.34} - m_LocalScale: {x: 1, y: 1, z: 1} + m_LocalScale: {x: 0.79838, y: 0.79838, z: 0.79838} m_Children: [] m_Father: {fileID: 0} m_RootOrder: 3 @@ -529,11 +580,103 @@ Transform: m_GameObject: {fileID: 1640058004} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: -0.94, y: 0, z: -0.75} - m_LocalScale: {x: 1, y: 1, z: 1} + m_LocalScale: {x: 0.75521, y: 0.75521, z: 0.75521} m_Children: [] m_Father: {fileID: 0} m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1729586187 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1729586188} + - component: {fileID: 1729586191} + - component: {fileID: 1729586190} + - component: {fileID: 1729586189} + m_Layer: 0 + m_Name: Cube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1729586188 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1729586187} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: -0.25, z: 0} + m_LocalScale: {x: 7, y: 0.5, z: 16} + m_Children: [] + m_Father: {fileID: 21003253} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!65 &1729586189 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1729586187} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1729586190 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1729586187} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &1729586191 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1729586187} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} --- !u!1 &1940135309 GameObject: m_ObjectHideFlags: 0 @@ -650,7 +793,7 @@ Transform: m_GameObject: {fileID: 1940135309} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.8, y: 0, z: 0.02} - m_LocalScale: {x: 1, y: 1, z: 1} + m_LocalScale: {x: 0.74, y: 0.74, z: 0.74} m_Children: [] m_Father: {fileID: 0} m_RootOrder: 5 diff --git a/Assets/Scripts/GridWorld.cs b/Assets/Scripts/GridWorld.cs index 306ea00..4393190 100644 --- a/Assets/Scripts/GridWorld.cs +++ b/Assets/Scripts/GridWorld.cs @@ -118,6 +118,18 @@ public void RemoveItemFromCell(CellPosition position, CellItem item) { } } + /// Returns a list containing one CellPosition for every cell in the grid world. + public List ListAllCells() { + List result = new List(); + for (uint x = 0; x < width; x++) { + for (uint z = 0; z < length; z++) { + result.Add(new CellPosition(x, z, GridClass.PlayerGrid)); + result.Add(new CellPosition(x, z, GridClass.EnemyGrid)); + } + } + return result; + } + /// Returns a Vector3 indicating the real-world position of the center of the specified cell. /// Throws an InvalidCellPositionException if the provided grid position is outside the bounds /// of this grid world. diff --git a/Assets/Scripts/HopperExample.cs b/Assets/Scripts/HopperExample.cs index 2d14659..0599b16 100644 --- a/Assets/Scripts/HopperExample.cs +++ b/Assets/Scripts/HopperExample.cs @@ -57,6 +57,8 @@ void Update() { } // And end it at the next position. animationEnd = dweller.dwellsOn.GetRealPosition(patrol[patrolStep]); + // Remove ourselves from the grid (we will add ourselves back after the animation.) + dweller.MoveToCell(null); } else if (mode == Mode.Animate && timer >= ANIMATE_TIME) { timer -= ANIMATE_TIME; mode = Mode.Wait; diff --git a/Assets/Scripts/PhysicalGrid.cs b/Assets/Scripts/PhysicalGrid.cs new file mode 100644 index 0000000..720cc08 --- /dev/null +++ b/Assets/Scripts/PhysicalGrid.cs @@ -0,0 +1,75 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +class PhysicalCell { + public Vector3 position; + public GameObject playerIndicator = null; + public GameObject enemyIndicator = null; +} + +public class PhysicalGrid : MonoBehaviour { + public GridWorld gridWorld; + [Tooltip( + "This prefab will be instantiated for every single cell in the grid. The prefab should be " + + "1 unit big, and will be scaled to the actual size of the grid." + )] + public GameObject cellPrefab; + [Tooltip( + "This prefab will be instantiated for every cell containing a player. The prefab should be " + + "1 unit big, and will be scaled to the actual size of the grid." + )] + public GameObject playerIndicator; + [Tooltip( + "This prefab will be instantiated for every cell containing an enemy. The prefab should be " + + "1 unit big, and will be scaled to the actual size of the grid." + )] + public GameObject enemyIndicator; + + List allCells; + List physicalCells = new List(); + + // Handles scaling the prefab to match the grid world's cell size. + GameObject Instantiate(GameObject original, Vector3 position) { + GameObject instance = Instantiate(original, position, Quaternion.identity, gameObject.transform); + instance.transform.localScale = Vector3.one * gridWorld.cellSize; + return instance; + } + + void Start() { + allCells = gridWorld.ListAllCells(); + foreach (CellPosition cell in allCells) { + PhysicalCell physicalCell = new PhysicalCell(); + physicalCell.position = gridWorld.GetRealPosition(cell); + Instantiate(cellPrefab, physicalCell.position); + physicalCells.Add(physicalCell); + } + } + + void Update() { + for (int i = 0; i < allCells.Count; i++) { + CellPosition cellPosition = allCells[i]; + PhysicalCell physicalCell = physicalCells[i]; + + if (gridWorld.IsItemInCell(cellPosition, CellItem.Player)) { + if (physicalCell.playerIndicator == null) physicalCell.playerIndicator = + Instantiate(playerIndicator, physicalCell.position); + } else { + if (physicalCell.playerIndicator != null) { + Destroy(physicalCell.playerIndicator); + physicalCell.playerIndicator = null; + } + } + + if (gridWorld.IsItemInCell(cellPosition, CellItem.Enemy)) { + if (physicalCell.enemyIndicator == null) physicalCell.enemyIndicator = + Instantiate(enemyIndicator, physicalCell.position); + } else { + if (physicalCell.enemyIndicator != null) { + Destroy(physicalCell.enemyIndicator); + physicalCell.enemyIndicator = null; + } + } + } + } +} diff --git a/Assets/Scripts/PhysicalGrid.cs.meta b/Assets/Scripts/PhysicalGrid.cs.meta new file mode 100644 index 0000000..b8e3dfa --- /dev/null +++ b/Assets/Scripts/PhysicalGrid.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e564f9337cfd99775b8afcf9a56f82ea +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 51a410d27d416f8bf337a5e58f60ce4d1feb8a15 Mon Sep 17 00:00:00 2001 From: Code_Cube Date: Fri, 4 Oct 2019 12:13:52 -0700 Subject: [PATCH 09/14] Added tweaks and made grid world a singleton. --- Assets/Prefabs/Physical Grid.prefab | 144 +++++++++++ Assets/Prefabs/Physical Grid.prefab.meta | 7 + Assets/Scenes/GridTest.meta | 8 + Assets/Scenes/GridTest.unity | 236 ++++++------------ Assets/Scenes/GridTest/LightingData.asset | Bin 0 -> 18096 bytes .../Scenes/GridTest/LightingData.asset.meta | 8 + Assets/Scenes/GridTest/ReflectionProbe-0.exr | Bin 0 -> 163873 bytes .../GridTest/ReflectionProbe-0.exr.meta | 91 +++++++ Assets/Scripts/GridDweller.cs | 3 +- Assets/Scripts/GridWorld.cs | 9 + Assets/Scripts/HopperExample.cs | 4 +- Assets/Scripts/PhysicalGrid.cs | 3 +- 12 files changed, 347 insertions(+), 166 deletions(-) create mode 100644 Assets/Prefabs/Physical Grid.prefab create mode 100644 Assets/Prefabs/Physical Grid.prefab.meta create mode 100644 Assets/Scenes/GridTest.meta create mode 100644 Assets/Scenes/GridTest/LightingData.asset create mode 100644 Assets/Scenes/GridTest/LightingData.asset.meta create mode 100644 Assets/Scenes/GridTest/ReflectionProbe-0.exr create mode 100644 Assets/Scenes/GridTest/ReflectionProbe-0.exr.meta diff --git a/Assets/Prefabs/Physical Grid.prefab b/Assets/Prefabs/Physical Grid.prefab new file mode 100644 index 0000000..369badd --- /dev/null +++ b/Assets/Prefabs/Physical Grid.prefab @@ -0,0 +1,144 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &4448783347283947931 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4448783347283947932} + - component: {fileID: 4448783347283947935} + - component: {fileID: 4448783347283947934} + - component: {fileID: 4448783347283947933} + m_Layer: 0 + m_Name: Cube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4448783347283947932 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4448783347283947931} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: -0.25, z: 0} + m_LocalScale: {x: 7, y: 0.5, z: 16} + m_Children: [] + m_Father: {fileID: 4448783347927182949} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &4448783347283947935 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4448783347283947931} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &4448783347283947934 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4448783347283947931} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!65 &4448783347283947933 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4448783347283947931} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!1 &4448783347927182947 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4448783347927182949} + - component: {fileID: 4448783347927182948} + m_Layer: 0 + m_Name: Physical Grid + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4448783347927182949 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4448783347927182947} + 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_Children: + - {fileID: 4448783347283947932} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &4448783347927182948 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4448783347927182947} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e564f9337cfd99775b8afcf9a56f82ea, type: 3} + m_Name: + m_EditorClassIdentifier: + cellPrefab: {fileID: 4312626832982465632, guid: 17e170c19d044ffe0a220abb08ae9d7d, + type: 3} + playerIndicator: {fileID: 1653133395508173151, guid: dab0478d3b2020af4b585450d724e245, + type: 3} + enemyIndicator: {fileID: 4781031086883701544, guid: 993895520ab0bb667b46c52eada7ba72, + type: 3} diff --git a/Assets/Prefabs/Physical Grid.prefab.meta b/Assets/Prefabs/Physical Grid.prefab.meta new file mode 100644 index 0000000..2221eaa --- /dev/null +++ b/Assets/Prefabs/Physical Grid.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2e87a1b846fe65befb6b8f3b8a0aa6bf +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/GridTest.meta b/Assets/Scenes/GridTest.meta new file mode 100644 index 0000000..02065d1 --- /dev/null +++ b/Assets/Scenes/GridTest.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b39b8abf460459aa48ebf065114aaf4a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/GridTest.unity b/Assets/Scenes/GridTest.unity index 7ab4cfc..2153800 100644 --- a/Assets/Scenes/GridTest.unity +++ b/Assets/Scenes/GridTest.unity @@ -23,7 +23,7 @@ RenderSettings: m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} - m_AmbientIntensity: 1 + m_AmbientIntensity: 0.95 m_AmbientMode: 0 m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} @@ -38,7 +38,7 @@ RenderSettings: m_ReflectionIntensity: 1 m_CustomReflection: {fileID: 0} m_Sun: {fileID: 0} - m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_IndirectSpecularColor: {r: 0.18028334, g: 0.22571343, b: 0.30692208, a: 1} m_UseRadianceAmbientProbe: 0 --- !u!157 &3 LightmapSettings: @@ -96,7 +96,8 @@ LightmapSettings: m_PVRFilteringAtrousPositionSigmaAO: 1 m_ExportTrainingData: 0 m_TrainingDataDestination: TrainingData - m_LightingDataAsset: {fileID: 0} + m_LightingDataAsset: {fileID: 112000000, guid: 884a00cdf8f10f7d9b35ed0e79133b3a, + type: 2} m_UseShadowmask: 1 --- !u!196 &4 NavMeshSettings: @@ -205,63 +206,12 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 17071637} m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} - m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalPosition: {x: 1.29, y: 6.92, z: -2.22} m_LocalScale: {x: 1, y: 1, z: 1} m_Children: [] m_Father: {fileID: 0} m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} ---- !u!1 &21003251 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 21003253} - - component: {fileID: 21003252} - m_Layer: 0 - m_Name: PhysicalGrid - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &21003252 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 21003251} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: e564f9337cfd99775b8afcf9a56f82ea, type: 3} - m_Name: - m_EditorClassIdentifier: - gridWorld: {fileID: 2129435950} - cellPrefab: {fileID: 4312626832982465632, guid: 17e170c19d044ffe0a220abb08ae9d7d, - type: 3} - playerIndicator: {fileID: 1653133395508173151, guid: dab0478d3b2020af4b585450d724e245, - type: 3} - enemyIndicator: {fileID: 4781031086883701544, guid: 993895520ab0bb667b46c52eada7ba72, - type: 3} ---- !u!4 &21003253 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 21003251} - 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_Children: - - {fileID: 1729586188} - m_Father: {fileID: 0} - m_RootOrder: 6 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &769384963 GameObject: m_ObjectHideFlags: 0 @@ -296,7 +246,6 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: type: 2 - dwellsOn: {fileID: 2129435950} --- !u!65 &769384965 BoxCollider: m_ObjectHideFlags: 0 @@ -511,7 +460,6 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: type: 2 - dwellsOn: {fileID: 2129435950} --- !u!65 &1640058007 BoxCollider: m_ObjectHideFlags: 0 @@ -585,98 +533,6 @@ Transform: m_Father: {fileID: 0} m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1729586187 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1729586188} - - component: {fileID: 1729586191} - - component: {fileID: 1729586190} - - component: {fileID: 1729586189} - m_Layer: 0 - m_Name: Cube - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &1729586188 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1729586187} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: -0.25, z: 0} - m_LocalScale: {x: 7, y: 0.5, z: 16} - m_Children: [] - m_Father: {fileID: 21003253} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!65 &1729586189 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1729586187} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 1, y: 1, z: 1} - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &1729586190 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1729586187} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &1729586191 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1729586187} - m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} --- !u!1 &1940135309 GameObject: m_ObjectHideFlags: 0 @@ -724,7 +580,6 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: type: 2 - dwellsOn: {fileID: 2129435950} --- !u!65 &1940135312 BoxCollider: m_ObjectHideFlags: 0 @@ -798,18 +653,6 @@ Transform: m_Father: {fileID: 0} m_RootOrder: 5 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &2129435950 stripped -MonoBehaviour: - m_CorrespondingSourceObject: {fileID: 5166608720900095202, guid: cc76d76453b9adefe9c6bb2dd95e66b3, - type: 3} - m_PrefabInstance: {fileID: 1606325940500838668} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 0c1492f8fc8e71355ae6643b3dba3cdf, type: 3} - m_Name: - m_EditorClassIdentifier: --- !u!1001 &1606325940500838668 PrefabInstance: m_ObjectHideFlags: 0 @@ -879,3 +722,72 @@ PrefabInstance: objectReference: {fileID: 0} m_RemovedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: cc76d76453b9adefe9c6bb2dd95e66b3, type: 3} +--- !u!1001 &4448783347906188688 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 4448783347927182947, guid: 2e87a1b846fe65befb6b8f3b8a0aa6bf, + type: 3} + propertyPath: m_Name + value: Physical Grid + objectReference: {fileID: 0} + - target: {fileID: 4448783347927182949, guid: 2e87a1b846fe65befb6b8f3b8a0aa6bf, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4448783347927182949, guid: 2e87a1b846fe65befb6b8f3b8a0aa6bf, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4448783347927182949, guid: 2e87a1b846fe65befb6b8f3b8a0aa6bf, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4448783347927182949, guid: 2e87a1b846fe65befb6b8f3b8a0aa6bf, + type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4448783347927182949, guid: 2e87a1b846fe65befb6b8f3b8a0aa6bf, + type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4448783347927182949, guid: 2e87a1b846fe65befb6b8f3b8a0aa6bf, + type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4448783347927182949, guid: 2e87a1b846fe65befb6b8f3b8a0aa6bf, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4448783347927182949, guid: 2e87a1b846fe65befb6b8f3b8a0aa6bf, + type: 3} + propertyPath: m_RootOrder + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 4448783347927182949, guid: 2e87a1b846fe65befb6b8f3b8a0aa6bf, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4448783347927182949, guid: 2e87a1b846fe65befb6b8f3b8a0aa6bf, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4448783347927182949, guid: 2e87a1b846fe65befb6b8f3b8a0aa6bf, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 2e87a1b846fe65befb6b8f3b8a0aa6bf, type: 3} diff --git a/Assets/Scenes/GridTest/LightingData.asset b/Assets/Scenes/GridTest/LightingData.asset new file mode 100644 index 0000000000000000000000000000000000000000..c886b373a8207f0bbda54c16982057622786f8ca GIT binary patch literal 18096 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⋘!#Ig}Z3FfRehjC8O5bkX;?Wp_6s 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

8yb#CtCE5DB-o!UHIWB~(qH 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 z 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 NG1}39ABQjh{{c!x{xtvq literal 0 HcmV?d00001 diff --git a/Assets/Scenes/GridTest/ReflectionProbe-0.exr.meta b/Assets/Scenes/GridTest/ReflectionProbe-0.exr.meta new file mode 100644 index 0000000..a88778b --- /dev/null +++ b/Assets/Scenes/GridTest/ReflectionProbe-0.exr.meta @@ -0,0 +1,91 @@ +fileFormatVersion: 2 +guid: 641880590aa893d9fb579c7b38f0b7a2 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 10 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 1 + seamlessCubemap: 1 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 0 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 2 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 100 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/GridDweller.cs b/Assets/Scripts/GridDweller.cs index 8112875..97bf7de 100644 --- a/Assets/Scripts/GridDweller.cs +++ b/Assets/Scripts/GridDweller.cs @@ -4,11 +4,12 @@ public class GridDweller : MonoBehaviour { public CellItem type = CellItem.Player; - public GridWorld dwellsOn; + GridWorld dwellsOn; private CellPosition position = null; // Start is called before the first frame update void Start() { + dwellsOn = GridWorld.getInstance(); SyncRealPositionToCellPosition(); } diff --git a/Assets/Scripts/GridWorld.cs b/Assets/Scripts/GridWorld.cs index 4393190..8b0d8e4 100644 --- a/Assets/Scripts/GridWorld.cs +++ b/Assets/Scripts/GridWorld.cs @@ -50,11 +50,20 @@ public class GridWorld : MonoBehaviour { public float cellSize = 1.0f, neutralZone = 4.0f; public int width = 4, length = 4; private List[,] playerSideContents, enemySideContents; + private static GridWorld instance; + + public static GridWorld getInstance() { + if (instance == null) { + throw new NullReferenceException("No grid world exists in this level."); + } + return instance; + } /// We need to put this in Awake() because GridDwellers will try and place themselves on the /// grid with Start(), so the arrays that hold that data needs to be initialized before any /// Start() methods run. void Awake() { + instance = this; playerSideContents = new List[width, length]; enemySideContents = new List[width, length]; for (uint x = 0; x < width; x++) { diff --git a/Assets/Scripts/HopperExample.cs b/Assets/Scripts/HopperExample.cs index 0599b16..f6663ed 100644 --- a/Assets/Scripts/HopperExample.cs +++ b/Assets/Scripts/HopperExample.cs @@ -50,13 +50,13 @@ void Update() { timer -= WAIT_TIME; mode = Mode.Animate; // Start the anim at the current position... - animationStart = dweller.dwellsOn.GetRealPosition(patrol[patrolStep]); + animationStart = GridWorld.getInstance().GetRealPosition(patrol[patrolStep]); patrolStep++; if (patrolStep >= patrol.Length) { patrolStep = 0; } // And end it at the next position. - animationEnd = dweller.dwellsOn.GetRealPosition(patrol[patrolStep]); + animationEnd = GridWorld.getInstance().GetRealPosition(patrol[patrolStep]); // Remove ourselves from the grid (we will add ourselves back after the animation.) dweller.MoveToCell(null); } else if (mode == Mode.Animate && timer >= ANIMATE_TIME) { diff --git a/Assets/Scripts/PhysicalGrid.cs b/Assets/Scripts/PhysicalGrid.cs index 720cc08..07d0c20 100644 --- a/Assets/Scripts/PhysicalGrid.cs +++ b/Assets/Scripts/PhysicalGrid.cs @@ -9,7 +9,6 @@ class PhysicalCell { } public class PhysicalGrid : MonoBehaviour { - public GridWorld gridWorld; [Tooltip( "This prefab will be instantiated for every single cell in the grid. The prefab should be " + "1 unit big, and will be scaled to the actual size of the grid." @@ -28,6 +27,7 @@ public class PhysicalGrid : MonoBehaviour { List allCells; List physicalCells = new List(); + GridWorld gridWorld; // Handles scaling the prefab to match the grid world's cell size. GameObject Instantiate(GameObject original, Vector3 position) { @@ -37,6 +37,7 @@ GameObject Instantiate(GameObject original, Vector3 position) { } void Start() { + gridWorld = GridWorld.getInstance(); allCells = gridWorld.ListAllCells(); foreach (CellPosition cell in allCells) { PhysicalCell physicalCell = new PhysicalCell(); From 15bbb5b213e745e25326aa0a6c67fb3ae9449b33 Mon Sep 17 00:00:00 2001 From: Code_Cube Date: Fri, 4 Oct 2019 12:23:37 -0700 Subject: [PATCH 10/14] Bugfix / cleanup --- Assets/Scenes/GridTest.unity | 6 +++--- Assets/Scripts/GridDweller.cs | 1 - Assets/Scripts/GridWorld.cs | 1 - Assets/Scripts/HopperExample.cs | 3 --- 4 files changed, 3 insertions(+), 8 deletions(-) diff --git a/Assets/Scenes/GridTest.unity b/Assets/Scenes/GridTest.unity index 2153800..31da3c6 100644 --- a/Assets/Scenes/GridTest.unity +++ b/Assets/Scenes/GridTest.unity @@ -245,7 +245,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 38fd45c0c01b83cd78e53d3e19e28c9b, type: 3} m_Name: m_EditorClassIdentifier: - type: 2 + type: 1 --- !u!65 &769384965 BoxCollider: m_ObjectHideFlags: 0 @@ -459,7 +459,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 38fd45c0c01b83cd78e53d3e19e28c9b, type: 3} m_Name: m_EditorClassIdentifier: - type: 2 + type: 1 --- !u!65 &1640058007 BoxCollider: m_ObjectHideFlags: 0 @@ -579,7 +579,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 38fd45c0c01b83cd78e53d3e19e28c9b, type: 3} m_Name: m_EditorClassIdentifier: - type: 2 + type: 1 --- !u!65 &1940135312 BoxCollider: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/GridDweller.cs b/Assets/Scripts/GridDweller.cs index 97bf7de..6f06be4 100644 --- a/Assets/Scripts/GridDweller.cs +++ b/Assets/Scripts/GridDweller.cs @@ -10,7 +10,6 @@ public class GridDweller : MonoBehaviour { // Start is called before the first frame update void Start() { dwellsOn = GridWorld.getInstance(); - SyncRealPositionToCellPosition(); } // Update is called once per frame diff --git a/Assets/Scripts/GridWorld.cs b/Assets/Scripts/GridWorld.cs index 8b0d8e4..41ef904 100644 --- a/Assets/Scripts/GridWorld.cs +++ b/Assets/Scripts/GridWorld.cs @@ -3,7 +3,6 @@ using UnityEngine; public enum CellItem { - Empty, Player, Enemy } diff --git a/Assets/Scripts/HopperExample.cs b/Assets/Scripts/HopperExample.cs index f6663ed..2331e11 100644 --- a/Assets/Scripts/HopperExample.cs +++ b/Assets/Scripts/HopperExample.cs @@ -32,9 +32,6 @@ public class HopperExample : MonoBehaviour { void Start() { dweller = GetComponent(); - dweller.MoveToCell(patrol[patrolStep]); - dweller.SyncRealPositionToCellPosition(); - patrolStep++; } /// Roots at x=0 and x=1, vertex at (0.5, 1.0). From a594043776716c333475bedeb68dbd8579f3b853 Mon Sep 17 00:00:00 2001 From: Code_Cube Date: Fri, 4 Oct 2019 14:36:04 -0700 Subject: [PATCH 11/14] Grid world keeps track of actual dwellers in each cell now. --- Assets/Scripts/GridDweller.cs | 7 ++--- Assets/Scripts/GridWorld.cs | 48 ++++++++++++++++++---------------- Assets/Scripts/PhysicalGrid.cs | 4 +-- 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/Assets/Scripts/GridDweller.cs b/Assets/Scripts/GridDweller.cs index 6f06be4..64f096f 100644 --- a/Assets/Scripts/GridDweller.cs +++ b/Assets/Scripts/GridDweller.cs @@ -3,7 +3,7 @@ using UnityEngine; public class GridDweller : MonoBehaviour { - public CellItem type = CellItem.Player; + public DwellerType type = DwellerType.Player; GridWorld dwellsOn; private CellPosition position = null; @@ -39,9 +39,10 @@ public void SyncCellPositionToRealPosition() { /// will be effectively 'removed' from the grid world. Moving to a non-null cell will 'place' /// the object back in the world. public void MoveToCell(CellPosition newPosition) { - if (position != null) dwellsOn.RemoveItemFromCell(position, type); + if (newPosition == position) return; + if (position != null) dwellsOn.RemoveDwellerFromCell(position, this); position = newPosition; - if (position != null) dwellsOn.AddItemToCell(position, type); + if (position != null) dwellsOn.AddDwellerToCell(position, this); } /// Like MoveToCell(CellPosition), but moves to a different position on whatever side of the diff --git a/Assets/Scripts/GridWorld.cs b/Assets/Scripts/GridWorld.cs index 41ef904..3cbfa05 100644 --- a/Assets/Scripts/GridWorld.cs +++ b/Assets/Scripts/GridWorld.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using UnityEngine; -public enum CellItem { +public enum DwellerType { Player, Enemy } @@ -48,7 +48,7 @@ public InvalidCellPositionException(CellPosition position, GridWorld world) public class GridWorld : MonoBehaviour { public float cellSize = 1.0f, neutralZone = 4.0f; public int width = 4, length = 4; - private List[,] playerSideContents, enemySideContents; + private List[,] playerSideContents, enemySideContents; private static GridWorld instance; public static GridWorld getInstance() { @@ -63,12 +63,12 @@ public static GridWorld getInstance() { /// Start() methods run. void Awake() { instance = this; - playerSideContents = new List[width, length]; - enemySideContents = new List[width, length]; + playerSideContents = new List[width, length]; + enemySideContents = new List[width, length]; for (uint x = 0; x < width; x++) { for (uint z = 0; z < length; z++) { - playerSideContents[x, z] = new List(); - enemySideContents[x, z] = new List(); + playerSideContents[x, z] = new List(); + enemySideContents[x, z] = new List(); } } } @@ -89,14 +89,18 @@ public int ItemCountInCell(CellPosition position) { } } - public bool IsItemInCell(CellPosition position, CellItem item) { + public bool IsTypeInCell(CellPosition position, DwellerType type) { if (!IsValid(position)) { throw new InvalidCellPositionException(position, this); } if (position.side == GridClass.PlayerGrid) { - return playerSideContents[position.x, position.z].Contains(item); + return playerSideContents[position.x, position.z].Exists( + delegate(GridDweller dweller) { return dweller.type == type; } + ); } else { - return enemySideContents[position.x, position.z].Contains(item); + return enemySideContents[position.x, position.z].Exists( + delegate(GridDweller dweller) { return dweller.type == type; } + ); } } @@ -107,22 +111,22 @@ public bool IsCellEmpty(CellPosition position) { /// This method should only be used by GridDweller. Use that component to represent something on /// the grid. Never interact with this method directly. Throws an exception if trying to set /// a non-emtpy cell to something non-empty, or if trying to set an empty cell as empty again. - public void AddItemToCell(CellPosition position, CellItem item) { + public void AddDwellerToCell(CellPosition position, GridDweller dweller) { if (position.side == GridClass.PlayerGrid) { - playerSideContents[position.x, position.z].Add(item); + playerSideContents[position.x, position.z].Add(dweller); } else { - enemySideContents[position.x, position.z].Add(item); + enemySideContents[position.x, position.z].Add(dweller); } } /// This method should only be used by GridDweller. Use that component to represent something on /// the grid. Never interact with this method directly. Throws an exception if trying to set /// a non-emtpy cell to something non-empty, or if trying to set an empty cell as empty again. - public void RemoveItemFromCell(CellPosition position, CellItem item) { + public void RemoveDwellerFromCell(CellPosition position, GridDweller dweller) { if (position.side == GridClass.PlayerGrid) { - playerSideContents[position.x, position.z].Remove(item); + playerSideContents[position.x, position.z].Remove(dweller); } else { - enemySideContents[position.x, position.z].Remove(item); + enemySideContents[position.x, position.z].Remove(dweller); } } @@ -224,8 +228,8 @@ void OnDrawGizmos() { for (int z = 0; z < length; z++) { Vector3 pos = playerGridCorner + cellWidth * x + cellLength * z; pos += (Vector3.right + Vector3.forward) * (cellSize / 2); - foreach (CellItem item in playerSideContents[x, z]) { - DrawItemGizmo(pos, item); + foreach (GridDweller dweller in playerSideContents[x, z]) { + DrawDwellerTypeGizmo(pos, dweller.type); // Stack multiple items on the same cell. pos += Vector3.up * 0.5f; } @@ -258,8 +262,8 @@ void OnDrawGizmos() { for (int z = 0; z < length; z++) { Vector3 pos = enemyGridCorner + cellWidth * x + cellLength * z; pos += (Vector3.right + Vector3.forward) * (cellSize / 2); - foreach (CellItem item in enemySideContents[x, z]) { - DrawItemGizmo(pos, item); + foreach (GridDweller dweller in enemySideContents[x, z]) { + DrawDwellerTypeGizmo(pos, dweller.type); // Stack multiple items on the same cell. pos += Vector3.up * 0.5f; } @@ -268,10 +272,10 @@ void OnDrawGizmos() { } } - void DrawItemGizmo(Vector3 position, CellItem item) { - if (item == CellItem.Player) { + void DrawDwellerTypeGizmo(Vector3 position, DwellerType type) { + if (type == DwellerType.Player) { Gizmos.color = Color.blue; - } else if (item == CellItem.Enemy) { + } else if (type == DwellerType.Enemy) { Gizmos.color = Color.red; } diff --git a/Assets/Scripts/PhysicalGrid.cs b/Assets/Scripts/PhysicalGrid.cs index 07d0c20..3cc15e7 100644 --- a/Assets/Scripts/PhysicalGrid.cs +++ b/Assets/Scripts/PhysicalGrid.cs @@ -52,7 +52,7 @@ void Update() { CellPosition cellPosition = allCells[i]; PhysicalCell physicalCell = physicalCells[i]; - if (gridWorld.IsItemInCell(cellPosition, CellItem.Player)) { + if (gridWorld.IsTypeInCell(cellPosition, DwellerType.Player)) { if (physicalCell.playerIndicator == null) physicalCell.playerIndicator = Instantiate(playerIndicator, physicalCell.position); } else { @@ -62,7 +62,7 @@ void Update() { } } - if (gridWorld.IsItemInCell(cellPosition, CellItem.Enemy)) { + if (gridWorld.IsTypeInCell(cellPosition, DwellerType.Enemy)) { if (physicalCell.enemyIndicator == null) physicalCell.enemyIndicator = Instantiate(enemyIndicator, physicalCell.position); } else { From 112ff0b1b15fe6658aa9517ecc0235740bd78b61 Mon Sep 17 00:00:00 2001 From: Code_Cube Date: Fri, 4 Oct 2019 15:47:49 -0700 Subject: [PATCH 12/14] Added helper method for animating grid dwellers. --- Assets/Scripts/GridDweller.cs | 28 +++++++++++++++++++++++++++- Assets/Scripts/HopperExample.cs | 22 +++++++++------------- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/Assets/Scripts/GridDweller.cs b/Assets/Scripts/GridDweller.cs index 64f096f..7198c42 100644 --- a/Assets/Scripts/GridDweller.cs +++ b/Assets/Scripts/GridDweller.cs @@ -6,6 +6,9 @@ public class GridDweller : MonoBehaviour { public DwellerType type = DwellerType.Player; GridWorld dwellsOn; private CellPosition position = null; + private float animTimer = 0.0f, animDuration = 0.0f, animDelay = 0.0f; + private bool animating = false; + Vector3 animStart, animEnd; // Start is called before the first frame update void Start() { @@ -14,7 +17,30 @@ void Start() { // Update is called once per frame void Update() { - + animTimer += Time.deltaTime; + if (animating && animTimer > animDelay) { + // We only need to animate the X and Z axes, so make the code agnostic to any changes + // in the Y value. + if (animTimer < (animDelay + animDuration)) { + float progress = (animTimer - animDelay) / animDuration; + float oldY = gameObject.transform.position.y; + gameObject.transform.position = Vector3.Lerp(animStart, animEnd, progress); + SyncCellPositionToRealPosition(); + } else { + animEnd.y = gameObject.transform.position.y; + gameObject.transform.position = animEnd; + animating = false; + } + } + } + + public void AnimateToCell(CellPosition position, float delay, float duration) { + animTimer = 0.0f; + animDelay = delay; + animDuration = duration; + animStart = gameObject.transform.position; + animEnd = dwellsOn.GetRealPosition(position); + animating = true; } /// Moves the real (screen) position of this object to whatever its position in the grid world diff --git a/Assets/Scripts/HopperExample.cs b/Assets/Scripts/HopperExample.cs index 2331e11..451f8f7 100644 --- a/Assets/Scripts/HopperExample.cs +++ b/Assets/Scripts/HopperExample.cs @@ -28,7 +28,6 @@ public class HopperExample : MonoBehaviour { Mode mode = Mode.Wait; uint patrolStep = 0; float timer = 0.0f; - Vector3 animationStart, animationEnd; void Start() { dweller = GetComponent(); @@ -47,30 +46,27 @@ void Update() { timer -= WAIT_TIME; mode = Mode.Animate; // Start the anim at the current position... - animationStart = GridWorld.getInstance().GetRealPosition(patrol[patrolStep]); patrolStep++; if (patrolStep >= patrol.Length) { patrolStep = 0; } - // And end it at the next position. - animationEnd = GridWorld.getInstance().GetRealPosition(patrol[patrolStep]); - // Remove ourselves from the grid (we will add ourselves back after the animation.) - dweller.MoveToCell(null); + dweller.AnimateToCell(patrol[patrolStep], 0, ANIMATE_TIME); } else if (mode == Mode.Animate && timer >= ANIMATE_TIME) { timer -= ANIMATE_TIME; mode = Mode.Wait; - // Lock us in to be exactly at the target position. - gameObject.transform.position = animationEnd; - // Update our cell position. - dweller.SyncCellPositionToRealPosition(); + + // Make sure we are on the ground once the animation ends. + Vector3 newPosition = gameObject.transform.position; + newPosition.y = 0; + gameObject.transform.position = newPosition; } if (mode == Mode.Animate) { float progress = timer / ANIMATE_TIME; // Compute a parabolic jump animation. - gameObject.transform.position = - Vector3.Lerp(animationStart, animationEnd, progress) - + Vector3.up * ANIMATION_HEIGHT * ParabolicCurve(progress); + Vector3 newPosition = gameObject.transform.position; + newPosition.y = ANIMATION_HEIGHT * ParabolicCurve(progress); + gameObject.transform.position = newPosition; } } } From 8c46a125174b6e045a8baece2c73ae4cef818071 Mon Sep 17 00:00:00 2001 From: Code_Cube Date: Fri, 4 Oct 2019 16:15:53 -0700 Subject: [PATCH 13/14] Added helper to find empty spaces. --- Assets/Scenes/GridTest.unity | 10 ++++++++++ Assets/Scripts/GridDweller.cs | 6 ++++++ Assets/Scripts/GridWorld.cs | 24 ++++++++++++++++++++++++ Assets/Scripts/ListShuffle.cs | 18 ++++++++++++++++++ Assets/Scripts/ListShuffle.cs.meta | 11 +++++++++++ 5 files changed, 69 insertions(+) create mode 100644 Assets/Scripts/ListShuffle.cs create mode 100644 Assets/Scripts/ListShuffle.cs.meta diff --git a/Assets/Scenes/GridTest.unity b/Assets/Scenes/GridTest.unity index 31da3c6..9aa3422 100644 --- a/Assets/Scenes/GridTest.unity +++ b/Assets/Scenes/GridTest.unity @@ -720,6 +720,16 @@ PrefabInstance: propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} + - target: {fileID: 5166608720900095202, guid: cc76d76453b9adefe9c6bb2dd95e66b3, + type: 3} + propertyPath: cellSize + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5166608720900095202, guid: cc76d76453b9adefe9c6bb2dd95e66b3, + type: 3} + propertyPath: neutralZone + value: 2 + objectReference: {fileID: 0} m_RemovedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: cc76d76453b9adefe9c6bb2dd95e66b3, type: 3} --- !u!1001 &4448783347906188688 diff --git a/Assets/Scripts/GridDweller.cs b/Assets/Scripts/GridDweller.cs index 7198c42..e311340 100644 --- a/Assets/Scripts/GridDweller.cs +++ b/Assets/Scripts/GridDweller.cs @@ -15,6 +15,12 @@ void Start() { dwellsOn = GridWorld.getInstance(); } + void StartAt(CellPosition position) { + Start(); + MoveToCell(position); + SyncRealPositionToCellPosition(); + } + // Update is called once per frame void Update() { animTimer += Time.deltaTime; diff --git a/Assets/Scripts/GridWorld.cs b/Assets/Scripts/GridWorld.cs index 3cbfa05..a7fd3d2 100644 --- a/Assets/Scripts/GridWorld.cs +++ b/Assets/Scripts/GridWorld.cs @@ -108,6 +108,19 @@ public bool IsCellEmpty(CellPosition position) { return ItemCountInCell(position) == 0; } + /// If one can be found, returns the position of a cell on the specified side which does not + /// contain the specified type of dweller. If none can be found, null is returned instead. + public CellPosition FindRandomCellWithout(DwellerType type, GridClass side) { + List allCells = ListAllCellsOnSide(side); + allCells.Shuffle(); + foreach (CellPosition position in allCells) { + if (!IsTypeInCell(position, type)) { + return position; + } + } + return null; + } + /// This method should only be used by GridDweller. Use that component to represent something on /// the grid. Never interact with this method directly. Throws an exception if trying to set /// a non-emtpy cell to something non-empty, or if trying to set an empty cell as empty again. @@ -142,6 +155,17 @@ public List ListAllCells() { return result; } + /// Returns a list containing one CellPosition for every cell on the specified side. + public List ListAllCellsOnSide(GridClass side) { + List result = new List(); + for (uint x = 0; x < width; x++) { + for (uint z = 0; z < length; z++) { + result.Add(new CellPosition(x, z, side)); + } + } + return result; + } + /// Returns a Vector3 indicating the real-world position of the center of the specified cell. /// Throws an InvalidCellPositionException if the provided grid position is outside the bounds /// of this grid world. diff --git a/Assets/Scripts/ListShuffle.cs b/Assets/Scripts/ListShuffle.cs new file mode 100644 index 0000000..f553505 --- /dev/null +++ b/Assets/Scripts/ListShuffle.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +public static class ListShuffle { + private static Random rng = new Random(); + + public static void Shuffle(this IList list) { + int n = list.Count; + while (n > 1) { + n--; + int k = rng.Next(n + 1); + T value = list[k]; + list[k] = list[n]; + list[n] = value; + } + } +} diff --git a/Assets/Scripts/ListShuffle.cs.meta b/Assets/Scripts/ListShuffle.cs.meta new file mode 100644 index 0000000..93a21c3 --- /dev/null +++ b/Assets/Scripts/ListShuffle.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 333376e58f8311aa7ad93d4844090741 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 8807727cb8486061a79221fde8db2dcc5ced0ca8 Mon Sep 17 00:00:00 2001 From: Autofire Date: Sun, 6 Oct 2019 14:55:36 -0700 Subject: [PATCH 14/14] Changed comment format, and added private label to some things. --- Assets/Scripts/GridDweller.cs | 34 ++++++++++++++++++++-------------- Assets/Scripts/GridWorld.cs | 26 +++++++++++++++++++++----- Assets/Scripts/PhysicalGrid.cs | 13 +++++++++---- 3 files changed, 50 insertions(+), 23 deletions(-) diff --git a/Assets/Scripts/GridDweller.cs b/Assets/Scripts/GridDweller.cs index 64f096f..2dca476 100644 --- a/Assets/Scripts/GridDweller.cs +++ b/Assets/Scripts/GridDweller.cs @@ -4,50 +4,56 @@ public class GridDweller : MonoBehaviour { public DwellerType type = DwellerType.Player; - GridWorld dwellsOn; + + private GridWorld dwellsOn; private CellPosition position = null; - // Start is called before the first frame update - void Start() { + private void Start() { dwellsOn = GridWorld.getInstance(); } - // Update is called once per frame - void Update() { - - } - + ///

/// Moves the real (screen) position of this object to whatever its position in the grid world /// is. (Grid world position is set with MoveToCell()). Call this if you want changes made with /// MoveToCell() to be reflected verbatim on screen. + /// public void SyncRealPositionToCellPosition() { if (position != null) { gameObject.transform.position = dwellsOn.GetRealPosition(position); } } + /// /// Determines which cell the object is occupying based on its real (screen) position and then /// moves this object's cell position to that cell. Call this if you want manual changes to the /// object's position to be reflected in the game logic. + /// public void SyncCellPositionToRealPosition() { MoveToCell(dwellsOn.GridizeRealPosition(gameObject.transform.position)); } - /// Tries to move to a different cell on the grid. Note that this does NOT change the REAL - /// position of the object. It will appear in the same position in the world. This method just - /// changes which cell it is marked as occupying. If null is passed as newPosition, the object - /// will be effectively 'removed' from the grid world. Moving to a non-null cell will 'place' - /// the object back in the world. - public void MoveToCell(CellPosition newPosition) { + /// + /// Tries to move to a different cell on the grid. Note that this does NOT change the REAL + /// position of the object. It will appear in the same position in the world. This method just + /// changes which cell it is marked as occupying. If null is passed as newPosition, the object + /// will be effectively 'removed' from the grid world. Moving to a non-null cell will 'place' + /// the object back in the world. + /// + /// + public void MoveToCell(CellPosition newPosition) { if (newPosition == position) return; if (position != null) dwellsOn.RemoveDwellerFromCell(position, this); position = newPosition; if (position != null) dwellsOn.AddDwellerToCell(position, this); } + /// /// Like MoveToCell(CellPosition), but moves to a different position on whatever side of the /// world this object is already on. For example, if the object is on the Enemy side, it will /// try to move to the cell on the enemy side with the specified coordinates. + /// + /// + /// public void MoveToCell(uint x, uint z) { MoveToCell(new CellPosition(x, z, position.side)); } diff --git a/Assets/Scripts/GridWorld.cs b/Assets/Scripts/GridWorld.cs index 3cbfa05..004a5a3 100644 --- a/Assets/Scripts/GridWorld.cs +++ b/Assets/Scripts/GridWorld.cs @@ -58,10 +58,12 @@ public static GridWorld getInstance() { return instance; } - /// We need to put this in Awake() because GridDwellers will try and place themselves on the - /// grid with Start(), so the arrays that hold that data needs to be initialized before any - /// Start() methods run. void Awake() { + + /// We need to put this in Awake() because GridDwellers will try and place themselves on the + /// grid with Start(), so the arrays that hold that data needs to be initialized before any + /// Start() methods run. + instance = this; playerSideContents = new List[width, length]; enemySideContents = new List[width, length]; @@ -73,8 +75,12 @@ void Awake() { } } - /// Returns false if CellPosition is outside the bounds of this grid world. - public bool IsValid(CellPosition cellPosition) { + /// + /// Returns false if CellPosition is outside the bounds of this grid world. + /// + /// + /// + public bool IsValid(CellPosition cellPosition) { return cellPosition.x < width && cellPosition.z < length; } @@ -108,9 +114,11 @@ public bool IsCellEmpty(CellPosition position) { return ItemCountInCell(position) == 0; } + /// /// This method should only be used by GridDweller. Use that component to represent something on /// the grid. Never interact with this method directly. Throws an exception if trying to set /// a non-emtpy cell to something non-empty, or if trying to set an empty cell as empty again. + /// public void AddDwellerToCell(CellPosition position, GridDweller dweller) { if (position.side == GridClass.PlayerGrid) { playerSideContents[position.x, position.z].Add(dweller); @@ -119,9 +127,11 @@ public void AddDwellerToCell(CellPosition position, GridDweller dweller) { } } + /// /// This method should only be used by GridDweller. Use that component to represent something on /// the grid. Never interact with this method directly. Throws an exception if trying to set /// a non-emtpy cell to something non-empty, or if trying to set an empty cell as empty again. + /// public void RemoveDwellerFromCell(CellPosition position, GridDweller dweller) { if (position.side == GridClass.PlayerGrid) { playerSideContents[position.x, position.z].Remove(dweller); @@ -130,7 +140,9 @@ public void RemoveDwellerFromCell(CellPosition position, GridDweller dweller) { } } + /// /// Returns a list containing one CellPosition for every cell in the grid world. + /// public List ListAllCells() { List result = new List(); for (uint x = 0; x < width; x++) { @@ -142,9 +154,11 @@ public List ListAllCells() { return result; } + /// /// Returns a Vector3 indicating the real-world position of the center of the specified cell. /// Throws an InvalidCellPositionException if the provided grid position is outside the bounds /// of this grid world. + /// public Vector3 GetRealPosition(CellPosition cellPosition) { if (!IsValid(cellPosition)) { throw new InvalidCellPositionException(cellPosition, this); @@ -168,8 +182,10 @@ public Vector3 GetRealPosition(CellPosition cellPosition) { return position; } + /// /// Attempts to determine which cell the given world position lies in. If it is not inside the /// bounds of either the player or enemy grid, null is returned instead. + /// public CellPosition GridizeRealPosition(Vector3 realPosition) { bool isOnEnemyGrid = realPosition.z > 0; // Enemy grid is in the +z direction. // Reorient the coordinate system so that 0, 0 is at the 0, 0 corner of the enemy grid diff --git a/Assets/Scripts/PhysicalGrid.cs b/Assets/Scripts/PhysicalGrid.cs index 3cc15e7..69e248b 100644 --- a/Assets/Scripts/PhysicalGrid.cs +++ b/Assets/Scripts/PhysicalGrid.cs @@ -25,11 +25,16 @@ public class PhysicalGrid : MonoBehaviour { )] public GameObject enemyIndicator; - List allCells; - List physicalCells = new List(); - GridWorld gridWorld; + private List allCells; + private List physicalCells = new List(); + private GridWorld gridWorld; - // Handles scaling the prefab to match the grid world's cell size. + /// + /// Handles scaling the prefab to match the grid world's cell size. + /// + /// + /// + /// GameObject Instantiate(GameObject original, Vector3 position) { GameObject instance = Instantiate(original, position, Quaternion.identity, gameObject.transform); instance.transform.localScale = Vector3.one * gridWorld.cellSize;