From 5b27866ef1d3defd6718f98cb8377d0e03a8d39b Mon Sep 17 00:00:00 2001 From: Sveske Juice Date: Sat, 20 Apr 2024 11:58:46 +0200 Subject: [PATCH] Fix arc sampling (chat gpt is stupid) + draggable sliders for turret aiming --- Assets/Prefabs/Towers/BaseTower.prefab | 258 +++++++++++++++++++- Assets/Prefabs/Towers/Turret.prefab | 5 + Assets/Scenes/TowerTest.unity | 16 +- Assets/Scripts/Utilities/EditableArc.cs | 78 +++--- Assets/Scripts/Utilities/SliderKnob.cs | 27 ++ Assets/Scripts/Utilities/SliderKnob.cs.meta | 11 + 6 files changed, 348 insertions(+), 47 deletions(-) create mode 100644 Assets/Scripts/Utilities/SliderKnob.cs create mode 100644 Assets/Scripts/Utilities/SliderKnob.cs.meta diff --git a/Assets/Prefabs/Towers/BaseTower.prefab b/Assets/Prefabs/Towers/BaseTower.prefab index fd365d5..839639c 100644 --- a/Assets/Prefabs/Towers/BaseTower.prefab +++ b/Assets/Prefabs/Towers/BaseTower.prefab @@ -221,7 +221,8 @@ Transform: m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 - m_Children: [] + m_Children: + - {fileID: 1005161694208365894} m_Father: {fileID: 7523567070824087546} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!120 &8501533562697966838 @@ -266,9 +267,7 @@ LineRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 - m_Positions: - - {x: 0, y: 0, z: 0} - - {x: 0, y: 0, z: 1} + m_Positions: [] m_Parameters: serializedVersion: 3 widthMultiplier: 1 @@ -340,9 +339,131 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 907145a413a8aab36826e850743ffdcc, type: 3} m_Name: m_EditorClassIdentifier: + orientation: 0 samples: 15 visualRadius: 1 + knob: {fileID: 5325871420816673616} + knobSensitiviy: 1 rotationMinMax: {x: -30, y: 30} +--- !u!1 &5036551877689028418 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1005161694208365894} + - component: {fileID: 1972570430634883426} + - component: {fileID: 5278001764115219070} + - component: {fileID: 4719671969439815360} + - component: {fileID: 5325871420816673616} + m_Layer: 0 + m_Name: SliderKnob + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1005161694208365894 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5036551877689028418} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0.843} + m_LocalScale: {x: 0.1, y: 0.1, z: 0.1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 1223875499574008094} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &1972570430634883426 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5036551877689028418} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 1fb12e769af8dfc4b9c47b291e1da192, 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &5278001764115219070 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5036551877689028418} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!64 &4719671969439815360 +MeshCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5036551877689028418} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 5 + m_Convex: 0 + m_CookingOptions: 30 + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!114 &5325871420816673616 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5036551877689028418} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9998882d4b72010a9b0ca2d8bd35835e, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1 &7730797280345979287 GameObject: m_ObjectHideFlags: 0 @@ -373,7 +494,8 @@ Transform: m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 - m_Children: [] + m_Children: + - {fileID: 6098578092099223971} m_Father: {fileID: 7523567070824087546} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!120 &639897978325975064 @@ -418,9 +540,7 @@ LineRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 - m_Positions: - - {x: 0, y: 0, z: 0} - - {x: 0, y: 0, z: 1} + m_Positions: [] m_Parameters: serializedVersion: 3 widthMultiplier: 1 @@ -492,6 +612,128 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 907145a413a8aab36826e850743ffdcc, type: 3} m_Name: m_EditorClassIdentifier: + orientation: 0 samples: 15 visualRadius: 1 + knob: {fileID: 6589470144374164838} + knobSensitiviy: 1 rotationMinMax: {x: -30, y: 30} +--- !u!1 &8464444921411020014 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6098578092099223971} + - component: {fileID: 5101626729001350425} + - component: {fileID: 4513446337555113257} + - component: {fileID: 8074503904714955461} + - component: {fileID: 6589470144374164838} + m_Layer: 0 + m_Name: SliderKnob + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &6098578092099223971 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8464444921411020014} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0.843} + m_LocalScale: {x: 0.1, y: 0.1, z: 0.1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 8537103711824016857} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &5101626729001350425 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8464444921411020014} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 1fb12e769af8dfc4b9c47b291e1da192, 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &4513446337555113257 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8464444921411020014} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!64 &8074503904714955461 +MeshCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8464444921411020014} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 5 + m_Convex: 0 + m_CookingOptions: 30 + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!114 &6589470144374164838 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8464444921411020014} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9998882d4b72010a9b0ca2d8bd35835e, type: 3} + m_Name: + m_EditorClassIdentifier: diff --git a/Assets/Prefabs/Towers/Turret.prefab b/Assets/Prefabs/Towers/Turret.prefab index 3e4c832..8952275 100644 --- a/Assets/Prefabs/Towers/Turret.prefab +++ b/Assets/Prefabs/Towers/Turret.prefab @@ -23,6 +23,11 @@ PrefabInstance: propertyPath: orientation value: 1 objectReference: {fileID: 0} + - target: {fileID: 1842811169542586225, guid: c309e2ab8a7e17f049cee02d2d5e1af3, + type: 3} + propertyPath: rotationMinMax.x + value: -38.7 + objectReference: {fileID: 0} - target: {fileID: 4241178655744724118, guid: c309e2ab8a7e17f049cee02d2d5e1af3, type: 3} propertyPath: m_Name diff --git a/Assets/Scenes/TowerTest.unity b/Assets/Scenes/TowerTest.unity index d2e5cd5..6730563 100644 --- a/Assets/Scenes/TowerTest.unity +++ b/Assets/Scenes/TowerTest.unity @@ -210,7 +210,7 @@ Transform: m_GameObject: {fileID: 330585543} serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 1, z: -10} + m_LocalPosition: {x: 0, y: 1, z: -2.6} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] @@ -453,7 +453,7 @@ PrefabInstance: - target: {fileID: 6499929602381336473, guid: 9415cb10a1bd579269301ca4f61a1554, type: 3} propertyPath: m_LocalPosition.x - value: 0 + value: -0.12817177 objectReference: {fileID: 0} - target: {fileID: 6499929602381336473, guid: 9415cb10a1bd579269301ca4f61a1554, type: 3} @@ -463,27 +463,27 @@ PrefabInstance: - target: {fileID: 6499929602381336473, guid: 9415cb10a1bd579269301ca4f61a1554, type: 3} propertyPath: m_LocalPosition.z - value: 0 + value: 0.34760666 objectReference: {fileID: 0} - target: {fileID: 6499929602381336473, guid: 9415cb10a1bd579269301ca4f61a1554, type: 3} propertyPath: m_LocalRotation.w - value: 1 + value: 0.5129842 objectReference: {fileID: 0} - target: {fileID: 6499929602381336473, guid: 9415cb10a1bd579269301ca4f61a1554, type: 3} propertyPath: m_LocalRotation.x - value: 0 + value: -0 objectReference: {fileID: 0} - target: {fileID: 6499929602381336473, guid: 9415cb10a1bd579269301ca4f61a1554, type: 3} propertyPath: m_LocalRotation.y - value: 0 + value: 0.858398 objectReference: {fileID: 0} - target: {fileID: 6499929602381336473, guid: 9415cb10a1bd579269301ca4f61a1554, type: 3} propertyPath: m_LocalRotation.z - value: 0 + value: -0 objectReference: {fileID: 0} - target: {fileID: 6499929602381336473, guid: 9415cb10a1bd579269301ca4f61a1554, type: 3} @@ -493,7 +493,7 @@ PrefabInstance: - target: {fileID: 6499929602381336473, guid: 9415cb10a1bd579269301ca4f61a1554, type: 3} propertyPath: m_LocalEulerAnglesHint.y - value: 0 + value: 118.274 objectReference: {fileID: 0} - target: {fileID: 6499929602381336473, guid: 9415cb10a1bd579269301ca4f61a1554, type: 3} diff --git a/Assets/Scripts/Utilities/EditableArc.cs b/Assets/Scripts/Utilities/EditableArc.cs index 5abcbc2..38d2e6a 100644 --- a/Assets/Scripts/Utilities/EditableArc.cs +++ b/Assets/Scripts/Utilities/EditableArc.cs @@ -1,4 +1,6 @@ +using System; using UnityEngine; +using UnityEngine.Assertions; public enum ArcOrientation { @@ -12,6 +14,9 @@ public class EditableArc : MonoBehaviour [SerializeField] private ArcOrientation orientation = ArcOrientation.HORIZONTAL; [SerializeField, Range(5, 50)] private int samples = 15; [SerializeField] private float visualRadius = 1f; + [SerializeField] private SliderKnob knob; + [SerializeField] private float knobSensitiviy = 1f; + [SerializeField] private string moveKnobAxisName = "Mouse X"; [SerializeField] private Vector2 rotationMinMax = new Vector2(-30f, 30f); private LineRenderer lineRenderer; @@ -19,13 +24,52 @@ public class EditableArc : MonoBehaviour public Observer Value { get; private set; } = new(0); public Vector2 RotationMinMax => rotationMinMax; + public Vector3 normal => orientation == ArcOrientation.HORIZONTAL ? transform.up : transform.right; + public Vector3 tangent => orientation == ArcOrientation.HORIZONTAL ? transform.right : transform.up; + private void Awake() { lineRenderer = GetComponent(); Value.AddListener(UpdateArc); + Value.AddListener(UpdateKnobPosition); Value.Value = (rotationMinMax.x + rotationMinMax.y) / 2f; + + Assert.IsNotNull(knob, $"No knob on {this}"); + knob.OnDrag += PointerDraggedOnKnob; + + // Initial + UpdateKnobPosition(Value); + } + + // Moves the knob to the right position based on the angle on the arc + private void UpdateKnobPosition(float angle) + { + Vector3 dir = Quaternion.AngleAxis(angle, normal) * tangent; + Vector3 knobPos = transform.position + dir; + + knob.transform.position = knobPos; + } + + private void OnDestroy() + { + Value.RemoveListener(UpdateArc); + Value.RemoveListener(UpdateKnobPosition); + knob.OnDrag -= PointerDraggedOnKnob; + } + + private void PointerDraggedOnKnob(SliderKnob knob) + { + // Amount mouse have moved since last frame - ie. mouse velocity + float mouseMovement = Input.GetAxis(moveKnobAxisName); + + // TODO: figure out this based on camera orientation + float sign = -1f; + + float delta = mouseMovement * knobSensitiviy * sign; + float newAngle = Mathf.Clamp(Value.Value + delta, rotationMinMax.x, rotationMinMax.y); + Value.Value = newAngle; } private void Update() @@ -35,24 +79,6 @@ public class EditableArc : MonoBehaviour private void UpdateArc(float rotation) { - Vector3 normal; - Vector3 tangent; - - if (orientation == ArcOrientation.HORIZONTAL) - { - normal = transform.up; - tangent = transform.right; - } - else if (orientation == ArcOrientation.VERTICAL) - { - normal = transform.right; - tangent = transform.up; - } - else - { - throw new System.Exception("WTFFFFF HAVE YOU DONE YOU MF!!?"); - } - float angle = rotationMinMax.y - rotationMinMax.x; float v = (Mathf.PI - Value * Mathf.Deg2Rad) / 2f; Vector3 start = Quaternion.AngleAxis(rotationMinMax.x, normal) * tangent; @@ -75,18 +101,8 @@ public class EditableArc : MonoBehaviour public Vector3 SamplePointOnArc(Vector3 startPoint, Vector3 endPoint, float radius, float t) { - // Calculate the angle between start and end points - float angle = Vector3.Angle(startPoint, endPoint) * t; - - // Calculate the perpendicular vector from start to end - Vector3 axis = Vector3.Cross(startPoint, endPoint).normalized; - - // Calculate the position of the point on the arc - Vector3 pointOnArc = Quaternion.AngleAxis(angle, axis) * startPoint; - - // Scale the point by the radius - pointOnArc *= radius; - - return pointOnArc; + float angle = Mathf.LerpAngle(rotationMinMax.x, rotationMinMax.y, t); + Vector3 dir = Quaternion.AngleAxis(angle, normal) * tangent; + return transform.position + dir.normalized * radius; } } diff --git a/Assets/Scripts/Utilities/SliderKnob.cs b/Assets/Scripts/Utilities/SliderKnob.cs new file mode 100644 index 0000000..1fa5519 --- /dev/null +++ b/Assets/Scripts/Utilities/SliderKnob.cs @@ -0,0 +1,27 @@ +using System; +using UnityEngine; + +[RequireComponent(typeof(MeshCollider))] +public class SliderKnob : MonoBehaviour +{ + public event Action OnDrag; + + private Vector3 screenPoint; + private Vector3 offset; + + void OnMouseDown() + { + screenPoint = Camera.main.WorldToScreenPoint(gameObject.transform.position); + + offset = gameObject.transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z)); + } + + void OnMouseDrag() + { + OnDrag?.Invoke(this); + /* Vector3 curScreenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z); + + Vector3 curPosition = Camera.main.ScreenToWorldPoint(curScreenPoint) + offset; + transform.position = curPosition; */ + } +} diff --git a/Assets/Scripts/Utilities/SliderKnob.cs.meta b/Assets/Scripts/Utilities/SliderKnob.cs.meta new file mode 100644 index 0000000..fe864d2 --- /dev/null +++ b/Assets/Scripts/Utilities/SliderKnob.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9998882d4b72010a9b0ca2d8bd35835e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: