From 93cabd04357123ad5afb444a5012617c75a591ee Mon Sep 17 00:00:00 2001 From: Jens Pitkanen Date: Sat, 2 May 2020 19:00:33 +0300 Subject: [PATCH] Implement backpack --- Assets/Prefabs/VR/Casette VR.prefab | 2 +- Assets/Scenes/VRScene.unity | 214 ++++++++++++++++++ Assets/Scripts/Backpack.cs | 94 ++++++++ Assets/Scripts/Backpack.cs.meta | 11 + Assets/Scripts/BackpackAccessor.cs | 51 +++++ Assets/Scripts/BackpackAccessor.cs.meta | 11 + .../Resources/SteamVR_Settings.asset | 4 +- Packages/manifest.json | 2 +- 8 files changed, 385 insertions(+), 4 deletions(-) create mode 100644 Assets/Scripts/Backpack.cs create mode 100644 Assets/Scripts/Backpack.cs.meta create mode 100644 Assets/Scripts/BackpackAccessor.cs create mode 100644 Assets/Scripts/BackpackAccessor.cs.meta diff --git a/Assets/Prefabs/VR/Casette VR.prefab b/Assets/Prefabs/VR/Casette VR.prefab index aadc487..c3c00b3 100644 --- a/Assets/Prefabs/VR/Casette VR.prefab +++ b/Assets/Prefabs/VR/Casette VR.prefab @@ -149,7 +149,7 @@ MonoBehaviour: snapAttachEaseInTime: 0.15 snapAttachEaseInCompleted: 0 skeletonPoser: {fileID: 0} - handFollowTransform: 1 + handFollowTransform: 0 highlightOnHover: 1 hideHighlight: [] hoverPriority: 0 diff --git a/Assets/Scenes/VRScene.unity b/Assets/Scenes/VRScene.unity index ced9dee..6eb9e14 100644 --- a/Assets/Scenes/VRScene.unity +++ b/Assets/Scenes/VRScene.unity @@ -2135,6 +2135,10 @@ PrefabInstance: m_Modification: m_TransformParent: {fileID: 1660514110} m_Modifications: + - target: {fileID: 100470, guid: dc06161b6d97feb419f45f03b62e14b9, type: 3} + propertyPath: m_Layer + value: 14 + objectReference: {fileID: 0} - target: {fileID: 107946, guid: dc06161b6d97feb419f45f03b62e14b9, type: 3} propertyPath: m_Name value: Player VR @@ -2143,6 +2147,34 @@ PrefabInstance: propertyPath: m_TagString value: Player objectReference: {fileID: 0} + - target: {fileID: 129006, guid: dc06161b6d97feb419f45f03b62e14b9, type: 3} + propertyPath: m_Layer + value: 14 + objectReference: {fileID: 0} + - target: {fileID: 144230, guid: dc06161b6d97feb419f45f03b62e14b9, type: 3} + propertyPath: m_Layer + value: 14 + objectReference: {fileID: 0} + - target: {fileID: 160596, guid: dc06161b6d97feb419f45f03b62e14b9, type: 3} + propertyPath: m_Layer + value: 14 + objectReference: {fileID: 0} + - target: {fileID: 165334, guid: dc06161b6d97feb419f45f03b62e14b9, type: 3} + propertyPath: m_Layer + value: 14 + objectReference: {fileID: 0} + - target: {fileID: 167242, guid: dc06161b6d97feb419f45f03b62e14b9, type: 3} + propertyPath: m_Layer + value: 14 + objectReference: {fileID: 0} + - target: {fileID: 171246, guid: dc06161b6d97feb419f45f03b62e14b9, type: 3} + propertyPath: m_Layer + value: 14 + objectReference: {fileID: 0} + - target: {fileID: 177230, guid: dc06161b6d97feb419f45f03b62e14b9, type: 3} + propertyPath: m_Layer + value: 14 + objectReference: {fileID: 0} - target: {fileID: 447954, guid: dc06161b6d97feb419f45f03b62e14b9, type: 3} propertyPath: m_LocalPosition.x value: 1.244 @@ -2213,8 +2245,112 @@ PrefabInstance: value: objectReference: {fileID: 1000011547835092, guid: 08a99a73a9931d346a28a8d04f3c2296, type: 3} + - target: {fileID: 1000013428287994, guid: dc06161b6d97feb419f45f03b62e14b9, type: 3} + propertyPath: m_Layer + value: 14 + objectReference: {fileID: 0} + - target: {fileID: 1000014277073068, guid: dc06161b6d97feb419f45f03b62e14b9, type: 3} + propertyPath: m_Layer + value: 14 + objectReference: {fileID: 0} + - target: {fileID: 114000010591715100, guid: dc06161b6d97feb419f45f03b62e14b9, + type: 3} + propertyPath: clearanceCheckMask.m_Bits + value: 9216 + objectReference: {fileID: 0} + - target: {fileID: 114000011734077242, guid: dc06161b6d97feb419f45f03b62e14b9, + type: 3} + propertyPath: clearanceCheckMask.m_Bits + value: 9216 + objectReference: {fileID: 0} m_RemovedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: dc06161b6d97feb419f45f03b62e14b9, type: 3} +--- !u!1 &189615143 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 160596, guid: dc06161b6d97feb419f45f03b62e14b9, + type: 3} + m_PrefabInstance: {fileID: 189615142} + m_PrefabAsset: {fileID: 0} +--- !u!1 &189615144 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 144230, guid: dc06161b6d97feb419f45f03b62e14b9, + type: 3} + m_PrefabInstance: {fileID: 189615142} + m_PrefabAsset: {fileID: 0} +--- !u!114 &189615145 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 189615143} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fa0236872506f7648881c1a3d7bbf267, type: 3} + m_Name: + m_EditorClassIdentifier: + Backpack: {fileID: 831661730} + GrabActions: + - actionPath: /actions/default/in/GrabPinch + needsReinit: 0 + - actionPath: /actions/default/in/GrabGrip + needsReinit: 0 + GrabOnBoolean: 1 + StoreActions: + - actionPath: /actions/default/in/GrabPinch + needsReinit: 0 + - actionPath: /actions/default/in/GrabGrip + needsReinit: 0 + StoreOnBoolean: 0 +--- !u!114 &189615146 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 189615144} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fa0236872506f7648881c1a3d7bbf267, type: 3} + m_Name: + m_EditorClassIdentifier: + Backpack: {fileID: 831661730} + GrabActions: + - actionPath: /actions/default/in/GrabPinch + needsReinit: 0 + - actionPath: /actions/default/in/GrabGrip + needsReinit: 0 + GrabOnBoolean: 1 + StoreActions: + - actionPath: /actions/default/in/GrabPinch + needsReinit: 0 + - actionPath: /actions/default/in/GrabGrip + needsReinit: 0 + StoreOnBoolean: 0 +--- !u!114 &189615150 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 11401046, guid: dc06161b6d97feb419f45f03b62e14b9, + type: 3} + m_PrefabInstance: {fileID: 189615142} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 189615143} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 29e3e4511966ba94d8ba0b98c6c62f82, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!114 &189615151 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 11450312, guid: dc06161b6d97feb419f45f03b62e14b9, + type: 3} + m_PrefabInstance: {fileID: 189615142} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 189615144} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 29e3e4511966ba94d8ba0b98c6c62f82, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!4 &191837989 stripped Transform: m_CorrespondingSourceObject: {fileID: 7234109734831889898, guid: 65b9ab5277d05de459f2091021e0ee01, @@ -9184,6 +9320,68 @@ PrefabInstance: objectReference: {fileID: 0} m_RemovedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 65b9ab5277d05de459f2091021e0ee01, type: 3} +--- !u!1 &831661729 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 831661734} + - component: {fileID: 831661731} + - component: {fileID: 831661730} + m_Layer: 0 + m_Name: Backpack + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &831661730 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 831661729} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: bde631285606bdf44b670fedb0defd0d, type: 3} + m_Name: + m_EditorClassIdentifier: + GrabFlags: 85 + Hands: + - {fileID: 189615151} + - {fileID: 189615150} + Contents: [] +--- !u!65 &831661731 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 831661729} + m_Material: {fileID: 0} + m_IsTrigger: 1 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 0.7, z: 0.5} + m_Center: {x: 0, y: 0, z: -0.25} +--- !u!4 &831661734 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 831661729} + 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: 2110606700} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!4 &831877394 stripped Transform: m_CorrespondingSourceObject: {fileID: 7234109734831889898, guid: 65b9ab5277d05de459f2091021e0ee01, @@ -17857,6 +18055,16 @@ PrefabInstance: propertyPath: GameState value: objectReference: {fileID: 834592896} + - target: {fileID: 986826787110512831, guid: 8ee6eecf5317b4841817712d24763e37, + type: 3} + propertyPath: GoodFuelAmount + value: 45 + objectReference: {fileID: 0} + - target: {fileID: 986826787110512831, guid: 8ee6eecf5317b4841817712d24763e37, + type: 3} + propertyPath: Fuel + value: 90 + objectReference: {fileID: 0} - target: {fileID: 1408567892783054407, guid: 8ee6eecf5317b4841817712d24763e37, type: 3} propertyPath: m_StaticEditorFlags @@ -24749,6 +24957,12 @@ PrefabInstance: objectReference: {fileID: 0} m_RemovedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 65b9ab5277d05de459f2091021e0ee01, type: 3} +--- !u!4 &2110606700 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 453574, guid: dc06161b6d97feb419f45f03b62e14b9, + type: 3} + m_PrefabInstance: {fileID: 189615142} + m_PrefabAsset: {fileID: 0} --- !u!1 &2115104243 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/Backpack.cs b/Assets/Scripts/Backpack.cs new file mode 100644 index 0000000..b57194b --- /dev/null +++ b/Assets/Scripts/Backpack.cs @@ -0,0 +1,94 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using Valve.VR.InteractionSystem; + + +[RequireComponent(typeof(Collider))] +public class Backpack : MonoBehaviour { + private class HapticPulse { + public Hand Hand; + public ushort Duration; + + public HapticPulse(Hand hand, ushort duration = 2000) { + Hand = hand; + Duration = duration; + } + } + + public Hand.AttachmentFlags GrabFlags; + public Hand[] Hands; + public List Contents = new List(); + + private Collider Collider; + private List PulseQueue = new List(4); + private float NextHapticTime = 0; + private bool[] HandReminded = new bool[] { false, false }; + + private void Awake() { + Collider = GetComponent(); + if (Hands.Length > HandReminded.Length) { + Debug.LogError($"Backpack has >{HandReminded.Length} hands assigned, please update HandReminded accordingly."); + } + } + + private void Update() { + for (int I = 0; I < Hands.Length; I++) { + bool HandInBag = IsHandInBag(Hands[I]); + if (!HandReminded[I] && HandInBag) { + HandReminded[I] = true; + if (PulseQueue.Count == 0) { + PulseQueue.Add(new HapticPulse(Hands[I], 1000)); + } + } else if (HandReminded[I] && !HandInBag) { + HandReminded[I] = false; + if (PulseQueue.Count == 0) { + PulseQueue.Add(new HapticPulse(Hands[I], 500)); + } + } + } + + if (Time.time >= NextHapticTime && PulseQueue.Count > 0) { + HapticPulse NextPulse = PulseQueue[0]; + // Note: using the microsecond-based haptic pulses to avoid Vive wands getting stuck vibrating. + // Don't know why it happens, and didn't find much info by googling. + NextPulse.Hand.TriggerHapticPulse(NextPulse.Duration); + NextHapticTime = Time.time + Time.deltaTime; + PulseQueue.RemoveAt(0); + } + } + + private bool IsHandInBag(Hand hand) { + Vector3 DeltaFromBag = hand.transform.position - Collider.ClosestPoint(hand.transform.position); + return DeltaFromBag.magnitude < hand.hoverSphereRadius; + } + + public void Grab(Hand hand) { + if (IsHandInBag(hand) && Contents.Count > 0) { + int Index = Contents.Count - 1; + Throwable Item = Contents[Index]; + Item.gameObject.SetActive(true); + hand.AttachObject(Item.gameObject, hand.IsGrabbingWithType(GrabTypes.Pinch) ? GrabTypes.Pinch : GrabTypes.Grip, GrabFlags); + Contents.RemoveAt(Index); + + PulseQueue.Clear(); + PulseQueue.Add(new HapticPulse(hand, 2_000)); + PulseQueue.Add(new HapticPulse(hand, 4_000)); + PulseQueue.Add(new HapticPulse(hand, 8_000)); + } + } + + public void Store(Hand hand) { + if (hand.currentAttachedObject != null) { + Throwable Item = hand.currentAttachedObject.GetComponent(); + if (IsHandInBag(hand) && Item != null) { + Contents.Add(Item); + hand.DetachObject(Item.gameObject); + Item.gameObject.SetActive(false); + + PulseQueue.Clear(); + PulseQueue.Add(new HapticPulse(hand, 15_000)); + } + } + } +} diff --git a/Assets/Scripts/Backpack.cs.meta b/Assets/Scripts/Backpack.cs.meta new file mode 100644 index 0000000..58bd326 --- /dev/null +++ b/Assets/Scripts/Backpack.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bde631285606bdf44b670fedb0defd0d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/BackpackAccessor.cs b/Assets/Scripts/BackpackAccessor.cs new file mode 100644 index 0000000..253a328 --- /dev/null +++ b/Assets/Scripts/BackpackAccessor.cs @@ -0,0 +1,51 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using Valve.VR; +using Valve.VR.InteractionSystem; + +public class BackpackAccessor : MonoBehaviour { + public Backpack Backpack; + + [Header("Actions")] + public SteamVR_Action_Boolean[] GrabActions; + [Tooltip("Should GrabAction become true or false when grabbing?")] + public bool GrabOnBoolean = false; + + public SteamVR_Action_Boolean[] StoreActions; + [Tooltip("Should StoreAction become true or false when dropping an item in the backpack?")] + public bool StoreOnBoolean = false; + + private Hand Hand; + + private void OnEnable() { + Hand = GetComponent(); + foreach (SteamVR_Action_Boolean GrabAction in GrabActions) { + GrabAction.AddOnChangeListener(OnGrabActionChange, Hand.handType); + } + foreach (SteamVR_Action_Boolean StoreAction in StoreActions) { + StoreAction.AddOnChangeListener(OnStoreActionChange, Hand.handType); + } + } + + private void OnDisable() { + foreach (SteamVR_Action_Boolean GrabAction in GrabActions) { + GrabAction.RemoveOnChangeListener(OnGrabActionChange, Hand.handType); + } + foreach (SteamVR_Action_Boolean StoreAction in StoreActions) { + StoreAction.RemoveOnChangeListener(OnStoreActionChange, Hand.handType); + } + } + + private void OnGrabActionChange(SteamVR_Action_Boolean actionIn, SteamVR_Input_Sources inputSources, bool newValue) { + if (newValue == GrabOnBoolean) { + Backpack.Grab(Hand); + } + } + + private void OnStoreActionChange(SteamVR_Action_Boolean actionIn, SteamVR_Input_Sources inputSources, bool newValue) { + if (newValue == StoreOnBoolean) { + Backpack.Store(Hand); + } + } +} diff --git a/Assets/Scripts/BackpackAccessor.cs.meta b/Assets/Scripts/BackpackAccessor.cs.meta new file mode 100644 index 0000000..963ba77 --- /dev/null +++ b/Assets/Scripts/BackpackAccessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fa0236872506f7648881c1a3d7bbf267 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SteamVR_Resources/Resources/SteamVR_Settings.asset b/Assets/SteamVR_Resources/Resources/SteamVR_Settings.asset index d6e46d9..90a2949 100644 --- a/Assets/SteamVR_Resources/Resources/SteamVR_Settings.asset +++ b/Assets/SteamVR_Resources/Resources/SteamVR_Settings.asset @@ -24,8 +24,8 @@ MonoBehaviour: autoEnableVR: 1 legacyMixedRealityCamera: 1 mixedRealityCameraPose: - actionPath: /actions//in/ExternalCamera - needsReinit: 1 + actionPath: /actions/mixedreality/in/ExternalCamera + needsReinit: 0 mixedRealityCameraInputSource: 11 mixedRealityActionSetAutoEnable: 1 previewHandLeft: {fileID: 0} diff --git a/Packages/manifest.json b/Packages/manifest.json index fb4250d..4ee45b2 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -1,6 +1,6 @@ { "dependencies": { - "com.unity.ide.vscode": "1.1.4", + "com.unity.ide.vscode": "1.1.3", "com.unity.postprocessing": "2.3.0", "com.unity.textmeshpro": "2.0.1", "com.unity.timeline": "1.2.13",