Unity Hand tracking issue on the quest with UI raycasting - unity3d

I'm working on a Unity project, trying to test the UI interaction on the Quest II with hand tracking and ray casting.
I've set up a very basic scene with all the default assets (OVRCameraRig, UIHelper) and added just a button to test the UI interaction.
This is what my scene looks like:
The issue I have is, when I run the scene, the Ray is rotated 90 degrees, and it's attached to the wrist for some reason. I made a video here to show what I mean :
https://www.youtube.com/watch?v=5f12yfpugB8
It's still interacting with the UI though.
Then after watching some online tutorials, I commented out these lines in the HandInputSelector.cs, which was attached to the UIHelper:
void SetActiveController(OVRInput.Controller c)
{
/*
Transform t;
if(c == OVRInput.Controller.LTouch)
{
t = m_CameraRig.leftHandAnchor;
}
else
{
t = m_CameraRig.rightHandAnchor;
}
m_InputModule.rayTransform = t;
*/
}
and instead added a 2nd script to the UI helper, with these lines only:
public OVRHand hand;
public OVRInputModule inputModule;
private void Start()
{
inputModule.rayTransform = hand.PointerPose;
}
Now the ray is at least attached to the correct position, but it still doesn't rotate properly with the hand movement. I made another video of it here :
Now the ray is at least attached to the correct position, but it still doesn't rotate properly with the hand movement. I made another video of it here :
https://youtu.be/q3d0eG2LwY0
My Unity version is 2021.3.1f1
Can someone please tell me what I'm doing wrong?

Related

Get the object or renderer displayed (rendered on top)

Is it possible to know I a mesh renderer is not visible due to the fact its being occluded by another gameObject? Up to what I researched, Rederer.isVisible responds to "isRendered" and scene params needs to be baked. So I wonder if there could be a simple way to know if an scene element is rendered on top of other in a simple manner. Larger explanation below.
Consider a simplified use case, with a camera (with occlusion culling activated), an occluder and an occludee such as this:
With the shadows options disabled (for both occluder and occludee. I would think disabling this is only needed for the ocludee but disabled for both just in case):
And a simple script to check visibility options:
using UnityEngine;
public class RenderCheck : MonoBehaviour
{
MeshRenderer mr;
private void Start()
{
mr = GetComponent<MeshRenderer>();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space)) {
bool isVisible = mr.isVisible;
Debug.Log($"cube visible: {isVisible}");
}
}
void OnBecameVisible() {
Debug.LogError($"{this.GetHashCode()} VISIBLE!!");
}
void OnWillRenderObject() {
Debug.LogError($"{this.GetHashCode()} VISIBLE!!");
}
}
The result I expected is that the ocludee .isVisible would return false, and that OnWillRenderObject() would be executed constantly after OnBecameVisible() is executed on the event of the occludee been moved out the occluders back, so into the sight of the camera. However I get .isVisible = true and the log thrown by the OnWillRenderObject().
I am aware of the fact that the Scene view cameras will also cause this value to be true. The explained outcome considers no scene camera and only the gamePlay camera (with occlusion culling activated).
I got this approach to work baking the scene occlusion options following the documentation steps. But my question here more if its rendered or not regarding the oclussion settings, is to know if a gameobject or a mesh is rendered "on top" of other (in the case of culling not being applied). Unity needs to handle that as it is how the render takes place in the scene.
There seem to be a bunch of useful options here for what I am after, however, for .isVisible to work I need to set and bake the occusion scene options (afaik). So .isVisible responds more to "isRendered"
fact. According to the documentation shouldn't Renderer.isVisible be giving the result I expected in a direct/simple manner and not be influenced by the fact of being rendered or not by dynamic occlusion?
Edit: As far as I checked, seems that only a raycast can address blocking by geometry. All these other things mean "visible" in the sense that the camera's rendering pipeline has to consider the object in some way.
With a raycast I can get the "physical" block, determined by a collision. Isn't there any way to determine the "graphical" block? As I said, that is figured out somewhere soas to be renedered accordingly in the display screen, so is that info available somehow?

How would I detect if my player is touching a game object?

Okay so basically im working on this test project that relies heavily on movement and momentum to complete levels, with a bit of parkour. I need a collider for two reasons, 1. The player touches an object at the end and gets put back into the menu. 2. If the player falls out of the map they die.
I tried a bit messing around with Colliders and at the Docs and while usually id figure it out ive been stumped for 20 minutes looking at Unity's docs and a few questions from here.
public GameObject objectCollider;
public GameObject anotherCollider;
void OnCollisionEnter(Collision collision)
{
if (CollisionDetection.IsTouching(objectCollider.gameObject, anotherCollider.gameObject))
{
Destroy(plr);
}
}
This is what I got so far. I get an error from here and if I switch it to if collider object == the other it errors out.
Basically what I want (If you perfer to just post the answer code but comments on it would still be helpful so i learn!) is for one gameobject (player (but in code its objectCollider)) to be detected if it touches the other (a cube (in code its anotherCollider)) and to execute code (for example Destroy(playerObject))
Thank you for any help you bring here, links, code anything!
Hopefully this is what you're looking for:
public void OnCollisionEnter(Collision collision)
{
if (collision.collider.name == "endObject")
{
//put back into the menu
}
}
Once your player enters a collision, it checks the name of whatever object it collided with. Then you can execute what code you want in the if statement.
You can use collision.collider for many other things, such as collision.collider.tag, but this should give you a start.

Check if a gameobject is visble on the current camera

I've been searching stack overflow and the internet for a bit trying to search for a solution to this issue, everytime i try to use OnBecameVisible() or OnBecameInvisible() or TestPlanesAABB to check if the object is not visible through the wall, the camera can still see the object through a solid wall.
Video of the problem here:
https://youtu.be/3HiEugm6On8
As you can see, if i'm looking at him he stops moving, if i turn around and he "unloads" or "becomes invisible" he moves closer, but if i go around a corner still looking in his direction he stops moving as if i can see him and there is no wall there, this is what i'm looking to solve
it's an enemy that roams around, and i want him to only move if i cannot see him, which i thought would be fairly simple, but alas it seems not to be as simple as i thought
my current code is basic:
public bool IsSeen = false;
public void OnBecameVisible()
{
Debug.Log("I can now see you");
IsSeen = true;
}
public void OnBecameInvisible()
{
Debug.Log("I can't see you");
IsSeen = false;
}
this is attatched to the object that i wish to detect / not detect through walls, which i do believe checks if the object is viewable by the camera that i choose.
does anyone have any ideas as to how i can fix / achieve this?
As already mentioned the general "problem" with Renderer.OnBecameVisible is
Note that object is considered visible when it needs to be rendered in the Scene. It might not be actually visible by any camera, but still need to be rendered for shadows for example. Also, when running in the editor, the Scene view cameras will also cause this function to be called.
So its not really usable for you.
is there a simple way to raycast the whole screen?
Unfortunately not really :/
You can a bit avoid this using GeometryUtility.CalculateFrustumPlanes in order to get the four planes of the camera frustrum. Then you can check whether the object is actually inside the frustrum using GeometryUtility.TestPlanesAABB
var cam = Camera.main;
var planes = GeometryUtility.CalculateFrustumPlanes(cam);
var objCollider = GetComponent<Collider>();
if (GeometryUtility.TestPlanesAABB(planes, objCollider.bounds))
{
Debug.Log("I am inside the camera frustrum!");
}
else
{
Debug.Log("I am out of sight...");
}
However, this still does not cover any other object being in front of the target object and therefore actually covering it.
You would need to define exactly what visible means (e.g. any portion of the mesh? Is the center of the object enough to test? etc).
For e.g. testing only the center of the object you could use a Physics.Linecast like e.g.
if (GeometryUtility.TestPlanesAABB(planes, objCollider.bounds))
{
Debug.Log("I am inside the camera frustrum!");
if(Physics.LineCast(cam.transform.position, objCollider.GetComponentInChildren<Renderer>().bounds.center, out var hit)
{
if(hit.gameObject != objCollider.gameObject)
{
Debug.Log("..but something else is in the way..");
}
else
{
Debug.Log("Now you see me, muhaha!");
}
}
}
If you want it to be more precise and track of any part of the mesh is visible then it actually gets tricky. You would need to raycast multiple key points of the bounding box (e.g. each corner, centers of the edges etc) depending on your needs.

Unity: OnCollisionEnter fires only on NEW entry, but not on NEW entry on different object with same name

I am building a platformer with appearing boxes. The box gets rendered as soon as the player hits it hitbox. This works just fine like so:
public class AppearingBoxes : MonoBehaviour
{
public GameObject Block, RageFace;
bool showBlock = false;
void Start()
{
showBlock = false;
}
void OnCollisionEnter(Collision2D col)
{
if (col.gameObject.name == "Birdy")
{
showBlock = true;
}
}
void FixedUpdate()
{
Block.GetComponent<Renderer>().enabled = showBlock;
RageFace.GetComponent<Renderer>().enabled = showBlock;
}
}
This script is attached to all of those boxes. Each box is an individual box but all with the same script and properties and name:
But here comes the issue. Only the first HIT triggers a box. As you can imagine, the player jumps on top of those invisble boxes and then triggers the one he hits. The player now moves forward over the other boxes that are still invisble and enters there hitboxes. However they dont appear. I believe this is due to the fact that the player is still in the "same" hitbox even though it is a different prefab object. If I jump ontop of the invisible platform and then fall back down to it (i left and then reentered the trigger) the box on which I land immeadiately appears as it should.
So what can I do to get the box to appear as soon as the player touched it even though he is has not left the hitbox of the box before?
Thank you! :)
Try to change the boxes colliders to isTrigger and use instead OnTriggerEnter2D
Or maybe it's because you use OnCollisionEnter instead of OnCollisionEnter2D ?
There is a problem in your code. I don't know if you missed that or it is a typo but you can not use OnCollisionEnter with a Collision2D parameter. Your game would run but it must be giving you this error message:
Script error: OnCollisionEnter
This message parameter has to be of type: Collision
The message will be ignored.
Use OnCollisionEnter2D instead
void OnCollisionEnter2D(Collision2D col)
{
if (col.gameObject.name == "Birdy")
{
showBlock = true;
}
}
Everyone, I did find a "workaround" It sill doesnt really explain the issue but alreast works...
What I did was to increase the size of the BoxCollider for every box just a little bit more. Like 3 pixels bigger than the actual box the player stands on. This solved the issue but makes me wonder: If the player didnt "really" collide with the collider in the first place he wouldve fallen through. But he didnt. Now the colliders a slightly bigger and everything gets triggered just perfect. Maybe a bug in the engine?
Thanks for all your help
He didn't fall because the collider isn't Trigger that's all.

Unity. Cant play animation in animator

i'm making a game in 2d and whenever i create an animation sprite, an animator controller is created automatically, i dont know why, i once tried it but i thought it wouldnt be necesary for animations i just want to make in 2d.. so after trying many times to play an animation without the animator (because unity says i have to set the animation legacy, which i dont know where), i gave it a try to play animations in the animator.. i searched through the script reference and wrote the code just like this:
#pragma strict
var velocity : float = 8;
function Update ()
{
var movement = Input.GetAxis("Horizontal") * velocity;
transform.Translate(Vector2.right * movement * Time.deltaTime);
if(Input.anyKey)
Animator.Play("move");
}
the error that unity says is : Assets/PlayerControl.js(12,26): BCE0020: An instance of type 'UnityEngine.Animator' is required to access non static member 'Play'.
so i tried to do this:
function Start ()
{
//var anim = GetComponent("Animator");
}
function Update ()
{
var movement = Input.GetAxis("Horizontal") * velocity;
transform.Translate(Vector2.right * movement * Time.deltaTime);
if(Input.anyKey)
anim.Play("move");
}
and another error occurs: Assets/PlayerControl.js(17,17): BCE0005: Unknown identifier: 'anim'.
i just want to play one simple animation that will just change the sprites. i know how to play animations without the animator.. so please tell me what to do with it.. how to stop unity auto creating animator controller or set the animation legacy, or how to fix this problem with the animator script.
Update:
i removed the code code just to make other stuff while i search solution for this but now it seems that animator is running this animation no matter what.. i made another state on it as idle, but then it goes to the animation i created.. i really dont understand this.
You can check Unity3D Animation mechanism with example http://docs.unity3d.com/Manual/Animator.html
Unity doesn't give us static method for animation play. See above.
http://docs.unity3d.com/ScriptReference/Animator.html
Try to play of animation
GetComponent("Animator").Play("move", -1, 0.0f);
Check the script reference of official site.
http://docs.unity3d.com/ScriptReference/Animator.Play.html