Created
January 10, 2017 12:00
-
-
Save nin-jat/af1f0ebc08b7b7509827fc8b5f8c1aab to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using UnityEngine; | |
| using System.Collections.Generic; | |
| using System; | |
| public class HandheldItem : MonoBehaviour | |
| { | |
| internal SteamVR_TrackedController controller; | |
| internal float pickupRadius; | |
| public bool Highlighted = false; | |
| public void PickUp(SteamVR_TrackedController controller) | |
| { | |
| this.controller = controller; | |
| // The item was picked up. | |
| } | |
| public void Drop() | |
| { | |
| // The item is dropped. | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using UnityEngine; | |
| using System.Collections.Generic; | |
| using System; | |
| public class HandheldManager : MonoBehaviour { | |
| #region singleton instance | |
| // Other scripts cannot access this. | |
| private static HandheldManager instance; | |
| // Other scripts can only read from this variable. | |
| public static HandheldManager Instance | |
| { | |
| get | |
| { | |
| // If the instance variable has not been set then find an object of this type. | |
| // If it's still not set then just wedge about it. Sometimes however you might | |
| // want to instantiate this script and this is where you would do it. | |
| if (instance == null) | |
| { | |
| instance = FindObjectOfType<HandheldManager>(); | |
| if (instance == null) | |
| Debug.LogError("There is no HandheldManager Scripts in this scene"); | |
| } | |
| // Return instance. | |
| return instance; | |
| } | |
| } | |
| #endregion | |
| public SteamVR_TrackedController leftController; | |
| public SteamVR_TrackedController rightController; | |
| public List<HandheldItem> items = new List<HandheldItem>(); | |
| public Hand leftHand; | |
| public Hand rightHand; | |
| // This class, this class is the most important class of all the classes (in this file). | |
| // It does everything! | |
| public class Hand | |
| { | |
| #region Variables | |
| // The item the controller is currently holding. If the hand is holding nothing it will be NULL. | |
| public HandheldItem heldItem; | |
| // The controller that is linked to this hand. | |
| public SteamVR_TrackedController controller; | |
| // The item that is highlighted. | |
| public HandheldItem highlightedItem; | |
| // The name of the hand. E.g. 'middle hand' | |
| public string name; | |
| #endregion | |
| // The constructor for this class. | |
| public Hand(SteamVR_TrackedController controller, string name) | |
| { | |
| // Set the controller and the name to the ones provided and register a Gripped event. | |
| // See 'ControllerGripped' for more info on the last bit. | |
| this.controller = controller; | |
| this.name = name; | |
| controller.Gripped += ControllerGripped; | |
| } | |
| // This will find an object suitable for picking up. | |
| public void ScanTick(ref List<HandheldItem> items) | |
| { | |
| // If the hand is holding an item then just return out. | |
| if (heldItem != null) | |
| return; | |
| // Make a variable to store the nearest item. | |
| HandheldItem nearest = null; | |
| // === Find the nearest item to the controller only if the item is === | |
| // A. Not already picked up. | |
| // B. It is the closest item. | |
| // C. It is not 400 km away (closer than the item.radus) | |
| { | |
| Vector3 pos = controller.transform.position; | |
| int count = items.Count; | |
| //Set the distance to the largest number possible (for a float) and create a variable | |
| // to keep track of what the nearest items is. | |
| float smallestDistance = Mathf.Infinity; | |
| int nearestItem = -1; | |
| // Loop over <meme> ALL THE THINGS! </meme> (items). | |
| for (int i = 0; i < count; i++) | |
| { | |
| // If the item is not already picked up [A] (the item keeps track of what controller is | |
| // holding it) then get the itemDistance between this controller and the items[i]. Next, | |
| // find out if the itemDistance is smaller than the smallestDistance [B] and.... if the | |
| // itemDistance is within the item's pickup radius [C]. | |
| // [A] | |
| if (items[i].controller == null) | |
| { | |
| float itemDistance = Vector3.Distance(pos, items[i].transform.position); | |
| // [B] & [C] | |
| if (itemDistance < smallestDistance && itemDistance < items[i].pickupRadius) | |
| { | |
| smallestDistance = itemDistance; | |
| nearestItem = i; | |
| } | |
| } | |
| } | |
| // If an item was found, set the nearest item variable for the next part. | |
| if (nearestItem >= 0) | |
| nearest = items[nearestItem]; | |
| } | |
| // === Update the highlighted statuses only if an item was found from the above code. === | |
| // The highlight only has to change if the highlighted item has changed. | |
| if (nearest != highlightedItem) | |
| { | |
| // Sometimes these two variables can be null. So a null-check is required. | |
| // Because the highlighted item is now different we can turn off the highlighted item | |
| // before we change it. | |
| if (highlightedItem != null) | |
| highlightedItem.Highlighted = false; | |
| // Turn on the nearest item highlight before we change it. | |
| if (nearest != null) | |
| nearest.Highlighted = true; | |
| // Make the nearest item the highlighted item. | |
| highlightedItem = nearest; | |
| } | |
| } | |
| // ControllerGripped. This is called every time the Grip button on the controller is pressed. | |
| // This is just a better (Shhhh. everyone has their own options ((that are 100% correct)) way | |
| // to do stuff when a button is pressed. Notice, no Update(). | |
| private void ControllerGripped(object sender, ClickedEventArgs e) | |
| { | |
| // So the controller button was just pressed. If there is a highlighted item and if there | |
| // is no held item then pick up the highlighted item. | |
| if (highlightedItem != null && heldItem == null) | |
| { | |
| // How does one pick up an item? First, Pick it up, then make it 'in this hand,' next | |
| // remove the highlight and finally make the highlighted item null. | |
| highlightedItem.PickUp(controller); | |
| heldItem = highlightedItem; | |
| highlightedItem.Highlighted = false; | |
| highlightedItem = null; | |
| } | |
| // If there is an item then just drop it, yep let that 3 million Jet engine hit the ground. | |
| else if (heldItem != null) | |
| { | |
| // Drop it then make it 'not in this hand.' | |
| heldItem.Drop(); | |
| heldItem = null; | |
| } | |
| } | |
| } | |
| void Awake() | |
| { | |
| // Once the script has loaded set-up the left and right hands using the controllers above. | |
| leftHand = new Hand(leftController, "Left Hand"); | |
| rightHand = new Hand(rightController, "Right Hand"); | |
| } | |
| void FixedUpdate() | |
| { | |
| // Run the scan tick on each hand. | |
| leftHand.ScanTick(ref items); | |
| rightHand.ScanTick(ref items); | |
| // Notice the ref. I don't know if this is needed for a List<T> but this just makes the function | |
| // receive a reference of the item instead of the item it's self (saves memory). | |
| } | |
| #region Item Registration | |
| // Registration and Un-Registration of items. Instead of doing a FindObjectsOfType on start, I have | |
| // made all items add (and remove) themselves to the list of items. Because you might want items to get created | |
| // and destroyed at runtime. | |
| public void RegisterItem(HandheldItem item) | |
| { | |
| if (!items.Contains(item)) | |
| items.Add(item); | |
| } | |
| public void UnRegisterItme(HandheldItem item) | |
| { | |
| if (items.Contains(item)) | |
| items.Remove(item); | |
| } | |
| #endregion | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment