Ok my problem is the oculus touchpads use the same grip controls to determine teleportation/aiming and picking up objects. I don't want to change the controls because they're intuitive, but I cant have the teleportation randomly coming up as it does now when they are picking up an object.
There is no disable function in the Oculus standard Locomotion Teleport class, and Ive tried disabling it like this:
private void Update()
{
locomotionTeleport = GameObject.FindObjectOfType<LocomotionTeleport>();
// print(GameObject.FindObjectsOfType<OVRGrabber>()[0].isGrabbing || GameObject.FindObjectsOfType<OVRGrabber>()[1].isGrabbing);
locomotionTeleport.enabled = !(GameObject.FindObjectsOfType<OVRGrabber>()[0].isGrabbing || GameObject.FindObjectsOfType<OVRGrabber>()[1].isGrabbing);
}
Where I track if object is being grabbed in the OVRGrabbers:
void OnTriggerEnter(Collider otherCollider)
{
// Get the grab trigger
OVRGrabbable grabbable = otherCollider.GetComponent<OVRGrabbable>() ?? otherCollider.GetComponentInParent<OVRGrabbable>();
if (grabbable == null) return;
if(grabbable != null)
{
isGrabbing = true;
}
But this does nothing. Nothing I try setting bool flags in the teleportation class does anything. How can I prevent teleportation if an object is being picked up, and reenable afterwards?
Related
Anyone know how i can stop this from flicking basically I'm doing a raycast and if it hits the crafting table it it shows up a text saying press e to craft but it is flickering cause its in the void update function but if anyone knows a work around that would be nice thanks!
if(hit.collider.tag == "CraftingTable")
{
if(textIsOn)
{
noshowcraftingtext();
}
else
{
showcraftingtext();
}
}
void showcraftingtext()
{
textIsOn = true;
pressEToShowCraftingTableUI.SetActive(true);
}
void noshowcraftingtext()
{
textIsOn = false;
pressEToShowCraftingTableUI.SetActive(false);
}
The main problem of your code is that you are trying to change the state after state was changed.
That's why updated isn't the case in a big project, because all such things will lead to unpredictable or logically conflicted behavior, to avoid this you should use Data driven approach instead.
But to fix exactly your issue, you need to have a function, which isn't based on the state of the object, but returns what should happen right now.
There isn't much about what's going on inside your game, but I can guess that you are firing a raycast with mouse and then checking is it craftable or not.
public void Raycaster : MonoBehavior {
public void YourClickMethod()
{
if(hit.collider.tag == "CraftingTable")
{
hit.collider.GetComponent<UserInputReceiver>().SetClicked(this);
}
}
}
And on the object which is receiving your raycast you should add this:
public class UserInputReceiver : MonoBehavior {
private bool _isEnabled = false;
//set this inside inspector
public GameObject ObjectToEnable;
private Raycaster _currentSender = null
public void SetClicked(Raycaster sender){
_isEnabled = !_isEnabled;
_currentSender = sender;
}
public void Update(){
if(_currentSender != null && _isEnabled) {
_isEnabled = Vector3.Distance(transform.position, _currentSender.transform.position) < 1f; //set the threshold based on your unit system
}
//or another object, you can put it inside public field and enable him
//gameObject.SetActive(_isEnabled);
objectToEnable.SetActive(_isEnabled); //here you can pass a reference through inspector for your canvas
}
}
This is how you can outstand this issue with a short way.
This code will set the flag based on the received input and the distance. If you need to keep enabled text forever, than remove distance check than it will enable only with a second click, without distance dependency.
I'm very new to unity and I'm making a simple tag game with car like players. However, I'm having problems with my trigger collider. When I tag the other car it kind of flickers the is tagged true/false. Here is my code.
public Color TaggedColor;
public Color NoTaggedColor;
public bool Tagged;
// Start is called before the first frame update
void Start()
{
Tagged = true;
GetComponent<Image>().color = TaggedColor;
}
// Update is called once per frame
void Update()
{
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "P2")
{
if (Tagged == false)
{
Tagged = true;
GetComponent<Image>().color = TaggedColor;
}
else
{
if (Tagged == true)
{
Tagged = false;
GetComponent<Image>().color = NoTaggedColor;
}
}
Debug.Log("TAG!");
}
}
void GotTagged()
{
if (Tagged == false)
{
Tagged = true;
//GetComponent<Image>().color = TaggedColor;
}
}
void TaggedOtherPlayer()
{
if (Tagged == true)
{
Tagged = false;
GetComponent<Image>().color = NoTaggedColor;
}
}
I have a Second code for P2 that the only change is the start and the tag is P1. I'm not sure if this problem is something in my code or if it's the collider it's self. If anyone has any idea why this is happening I would love to hear it!
Update: I bevile the issue is coming from the Colliders because I have an empty as a child of both players that is the trigger collider. However when I tag one the other trigger goes off as well. Should I have only one trigger? And if so how would I go about doing it?
Thanks
once you tag a player SetActive(false) the empty triggers for about 1 second or so. If you had a button that whenever its pressed it changes s value from true to false the false to true if you press and hold that button it will "flicker" back and forth between true and false. Thats what's happening with your players the trigger is constantly being pulled while you're touching so make it inactive for long enough for you to not be touching anymore. I hope that makes sense.
I've used Unity for quite some time, but never tried the editor. Today I decided to try to make an EditorWindow to help me with shortcuts with my development.
What I want is to click on a button on my Window to turn on and off a specific light in my scene.
Added the code and an image of the Window below.
I am clueless on how to proceed. Any help would be appreciated a lot!
public class DevTools : EditorWindow
{
public Object workLight;
[MenuItem("Window/DevTools")]
public static void ShowWindow()
{
GetWindow<DevTools>("Development Tools");
}
private void OnGUI()
{
GUILayout.Label("This is the development tools.", EditorStyles.boldLabel);
workLight = EditorGUILayout.ObjectField(workLight, typeof(object), true);
if (GUILayout.Button("Working Light"))
{
if(workLight == null)
{
ShowNotification(new GUIContent("No light selected"));
}
else
{
}
}
}
}
This is my current Window
Well, you need a reference to the object to proceed with turning it on and off. You can either add a field to the editor and manually choose the object from the scene or dynamically find it through GameObject.Find.
I don't really know Unity (never used it) but it looks pretty straightforward.
The EditorFieldForObject method seems to take a second type param that denotes which types you can select using the field in the GUI - I'm not sure if you can make this a GameObject or not, but there are basically two approaches that should work:
Leave your code as is and cast the object (in OnGUI method):
var gameObject = workLight as GameObject;
if(gameObject == null)
{
ShowNotification(new GUIContent("No light selected"));
}
else
{
var light = gameObject.GetComponent<Light>();
if(light == null)
{
ShowNotification(new GUIContent("Selected object is not a light"));
return;
}
// Not sure if this is the correct way to disable a light but you can figure it out
light.enabled = false;
// or light.enabled = !light.enabled to toggle state
}
The other way is to make the editor GUI box look for GameObject instances in the first place:
public GameObject workLight;
....
workLight = EditorGUILayout.ObjectField(workLight, typeof(GameObject), true);
But I'm not sure if this is possible or not (as I've said, I don't know Unity)
Edit: apparently you need to use GameObject.SetActive(boolean) to toggle the
state of an object
Since you want to toggle, you can use the GameObject.activeSelf field which gives you the active true/false flag on the current object
So this should work:
light.SetActive(!light.activeSelf);
Thanks a lot Charleh!
With a little bit of rewriting, this seem to work. Not sure if it is optimized perfectly, but it works without a hitch (atm) :p.
public class DevTools : EditorWindow
{
Object workLight = default;
[MenuItem("Window/DevTools")]
public static void ShowWindow()
{
GetWindow<DevTools>("Development Tools");
}
private void OnGUI()
{
GUILayout.Label("This is the development tools.", EditorStyles.boldLabel);
if (GUILayout.Button("Working Light"))
{
if (workLight == null)
{
ShowNotification(new GUIContent("No light selected"));
}
else
{
var light = GameObject.Find("Work Light");
if (light == null)
{
ShowNotification(new GUIContent("Selected object is not a light"));
return;
}
else
{
light.gameObject.GetComponent<Light>().enabled = !light.gameObject.GetComponent<Light>().enabled;
}
}
}
}
}
I am attempting to make a physics sandbox-type game for the Vive, but the velocity of an object is completely reset and just begins falling when you let go of an object you were previously holding, making throwing impossible.
The system I am using currently will disable gravity on an object, and disable colliders of on an object when you pick it up. It will also child the object to your controller, making it like holding the object. When you let go of the button to release the object, it will enable gravity, enable colliders, and then set its parent object to null. This works to pick up and release an object, but it does not work at all for throwing objects. I have played around with timing and order of the components of the code, and nothing works.
Is there any way to find the velocity of an object and the directional velocity, without the object using gravity? Velocity doesn't work if gravity is disabled.
Here is my code:
using UnityEngine;
using System.Collections;
public class WandController : MonoBehaviour
{
//Basic Controller tracking stuff
private Valve.VR.EVRButtonId gripButton = Valve.VR.EVRButtonId.k_EButton_Grip;
public bool gripButtonDown = false;
public bool gripButtonUp = false;
public bool gripButtonPressed = false;
private Valve.VR.EVRButtonId triggerButton = Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger;
public bool triggerButtonDown = false;
public bool triggerButtonUp = false;
public bool triggerButtonPressed = false;
private SteamVR_Controller.Device controller { get { return SteamVR_Controller.Input((int)trackedObj.index); } }
private SteamVR_TrackedObject trackedObj;
//Game Variables
public GameObject wouldSelect; //What is in the select zone, has tiny script for the zone that sets the newest triggerenter to this variable
public GameObject isHolding; //When you hold something, it goes from wouldselect to isholding
public bool holding = false;
public GameObject holdingZone; //The holding zone, also where objects go if they are picked up
// Use this for initialization
void Start()
{
trackedObj = GetComponent<SteamVR_TrackedObject>();
}
// Update is called once per frame
void Update()
{
//Basic Controller configuration & button management stuff
if (controller == null)
{
Debug.Log("Controller not initialized");
return;
}
gripButtonDown = controller.GetPressDown(gripButton);
gripButtonUp = controller.GetPressUp(gripButton);
gripButtonPressed = controller.GetPress(gripButton);
triggerButtonDown = controller.GetPressDown(triggerButton);
triggerButtonUp = controller.GetPressUp(triggerButton);
triggerButtonPressed = controller.GetPress(triggerButton);
if (gripButtonDown)
{
Debug.Log("Grip Button was just pressed");
}
if (gripButtonUp)
{
Debug.Log("Grip Button was just unpressed");
}
if (triggerButtonDown)
{
Debug.Log("Trigger Button was just pressed");
}
if (triggerButtonUp)
{
Debug.Log("Trigger Button was just unpressed");
}
//Calling void that allows you to grab
CanGrab();
}
void CanGrab ()
{
if(wouldSelect != null && wouldSelect.tag == "Object" && triggerButtonDown == true && holding == false)
{
wouldSelect.GetComponent<Collider>().enabled = false;
wouldSelect.GetComponent<Rigidbody>().useGravity = false;
isHolding = wouldSelect;
wouldSelect.transform.SetParent(this.transform);
wouldSelect.transform.position = holdingZone.transform.position;
holding = true;
}
if(holding == true && triggerButtonUp == true)
{
wouldSelect.GetComponent<Collider>().enabled = true;
isHolding.GetComponent<Rigidbody>().useGravity = true;
isHolding.transform.SetParent(null);
holding = false;
wouldSelect = null;
isHolding = null;
}
}
}
I had a similar issue and solved it by:
tracking the position of the object at every frame, and storing it as lastPosition
when the object is let go, using (transform.position - lastPosition) to give me a rough estimate of the velocity of that object
From there, you can add an impulse force if you have a rigidbody, etc, I found a thread with some details on the various ways Unity does it -- http://answers.unity3d.com/questions/696068/difference-between-forcemodeforceaccelerationimpul.html
I did a number of throwing mechanics in VR using the same parameters you had (Setting the object as a child of your controller, disabling gravity, disabling colliders).
The way I did it was to record the position of the object on the previous and current frame, and take the difference between them as the velocity. However, there are three main factors to consider:
There might be some jitter in the tracking of the controller, and sometimes the object does not fly in the direction of throw.
There might be a lag time between the user pressing/letting go of the throwing button and the button press/release getting recorded, and so the object is thrown only towards the falling arc of the throw. (This happens a lot in my playtests)
There is a peak force during a throw during which an object gains the most velocity for its flight, and sometimes people let go of the object a split second after. This is rather inconsequential, but you should definitely consider if you want very realistic throwing (Take a look at The Lab demo and you will know what I mean)
My implementation:
Record the last x frames (for me the sweet spot is between 10-15 frames) for the object's position.
Take the difference in the first and last frame in the window and use that to calculate the velocity.
transform.velocity = position[n] - position[0];
If I want a slightly more accurate implementation, I'll calculate the force of the throw by taking the differences in velocities for adjacent frames. If there is a time window between the peak force and the release of the object, do not take the velocities in the later half of the window.
For example, if I decide to record the last 10 frames of a throw, and there are 4 frames between the peak force and the release, I will take frame current-12 to current-2, instead of frame current-10 to current for the velocity.
I have a OnMouseOver script that will activate a guipanel (using it as a popup tooltip) on specific objects. When clicked, those objects will disappear instantly (destroyed since single use uniques) - but the guipanel stays active since there's no OnMouseExit. I can't really afford to put a BoxCollider on the background as it will mess with a lot of my other BoxCollider triggers - is there any way around this, or a better way to do what I'm doing?
Thanks!
Script:
void OnMouseOver()
{
if (gameObject.tag == "Target")
{
InfoReturned = gameObject.GetComponentInParent<InfoFill>().InfoPanel();
PopUpInfoBoxes[0].text = InfoReturned[0];
PopUpInfoBoxes[1].text = InfoReturned[1];
PopUpInfoBoxes[2].text = InfoReturned[2];
PopUpInfoBoxes[3].text = InfoReturned[3];
PopUpPanel.SetActive(true);
}
void OnMouseExit()
{
PopUpPanel.SetActive(false);
}