How do you get the rotation (or transform) of WMR motion controllers - unity3d

Is there a way to access the rotation of a controller using WMRToolkit? I know about solvers, but they seem to focus on using position. For reference, the idea is simply to set the rotation of another gameobject to be the same as the rotation of the controller, which seems like it should be a simple task.Thanks in advance!

This document shows how to use Unity API to get the position and rotation of a motion controller:Getting a hand or motion controller's pose
Besides, there is a new XR input mapping system in Unity 2019.1, if you are using unity of 2019.1 or later, you can try the following code:
bool TryGetCenterEyeFeature(out Quaternion rotation)
{
InputDevice device = InputDevices.GetDeviceAtXRNode(XRNode.RightHand);
if (device.isValid)
{
if (device.TryGetFeatureValue(CommonUsages.deviceRotation, out rotation))
return true;
}
rotation = Quaternion.identity;
return false;
}

Related

Unity XR - Rotate a grabbed object with XRGrabInteractable around its pivot

I'm pretty new to VR development with Unity, what I need to do is to grab a clockwork object and rotate it around its pivot by moving the right hand controller, like if I had to do that in real life
Here's the scenario:
Here's the code I'm using in Update:
public class Box1: MonoBehaviour {
public Transform rightHandTransf;
Vector3 handPosition;
void Update(){
Vector3 rhPos = rightHandTransf.position;
Quaternion rhRot = rightHandTransf.rotation;
// clockworkM Rotation
rhPos.z = clockworkM.transform.position.z - Camera.main.transform.position.z;
handPosition = Camera.main.WorldToScreenPoint(rhPos);
clockworkM.transform.rotation = Quaternion.LookRotation(Vector3.back, handPosition - clockworkM.transform.position);
}
}
What I get is that wherever I move the hand, the clockwork rotates just a little bit, and if I rotate the headset, the clockwork rotates based on my X axis rotation with my headset
Weird behavior, I have no idea what I'm doing wrong :(

Unity / Mirror - Is there a way to keep my camera independent from the player object's prefab after start?

I'm currently trying to create a multiplayer game using mirror!
So far I've been successful in creating a lobby and set up a simple character model with a player locomotion script I've taken and learnt inside out from Sebastian Graves on YouTube (you may know him as the dark souls III tutorial guy)
This player locomotion script uses unity's package 'Input System' and is also dependent on using the camera's .forward and .right directions to determine where the player moves and rotates instead of using forces on the rigidbody. This means you actually need the camera free in the scene and unparented from the player.
Here is my HandleRotation() function for rotating my character (not the camera's rotation function):
private void HandleRotation()
{
// target direction is the way we want our player to rotate and move // setting it to 0
Vector3 targetDirection = Vector3.zero;
targetDirection = cameraManager.cameraTransform.forward * inputHandler.verticalInput;
targetDirection += cameraManager.cameraTransform.right * inputHandler.horizontalInput;
targetDirection.Normalize();
targetDirection.y = 0;
if (targetDirection == Vector3.zero)
{
// keep our rotation facing the way we stopped
targetDirection = transform.forward;
}
// Quaternion's are used to calculate rotations
// Look towards our target direction
Quaternion targetRotation = Quaternion.LookRotation(targetDirection);
// Slerp = rotation between current rotation and target rotation by the speed you want to rotate * constant time regardless of framerates
Quaternion playerRotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);
transform.rotation = playerRotation;
}
It's also worth mentioning I'm not using cinemachine however I'm open to learning cinemachine as it may be beneficial in the future.
However, from what I've learnt and managed to find about mirror is that you have to parent the Main Camera under your player object's prefab so that when multiple people load in, multiple camera's are created. This has to happen on a Start() function or similar like OnStartLocalPlayer().
public override void OnStartLocalPlayer()
{
if (mainCam != null)
{
// configure and make camera a child of player
mainCam.orthographic = false;
mainCam.transform.SetParent(cameraPivotTransform);
mainCam.transform.localPosition = new Vector3(0f, 0f, -3f);
mainCam.transform.localEulerAngles = new Vector3(0f, 0f, 0f);
cameraTransform = GetComponentInChildren<Camera>().transform;
defaultPosition = cameraTransform.localPosition.z;
}
}
But of course, that means that the camera is no longer independent to the player and so what ends up happening is the camera rotates when the player rotates.
E.g. if I'm in game and looking to the right of my player model and then press 'w' to walk in the direction the camera is facing, my camera will spin with the player keeping the same rotation while my player spins in order to try and walk in the direction the camera is facing.
What my question here would be: Is there a way to create a system using mirror that doesn't require the camera to be parented to the player object prefab on start, and INSTEAD works by keeping it independent in the scene?
(I understand that using forces on a rigidbody is another method of creating a player locomotion script however I would like to avoid that if possible)
If anybody can help that would be greatly appreciated, Thank You! =]
With the constraint of your camera being attached to the player you will have to adapt the camera logic. What you can do is instantiate a proxy transform for the camera and copy that transforms properties to your camera, globally, every frame. The parent constraint component might do this for you. Then do all your transformations on that proxy.
Camera script with instantiation:
Transform proxy;
void Start(){
proxy = (new GameObject()).transform;
}
void Update(){
//transformations on proxy
transform.position = proxy.position;
transform.rotation = proxy.rotation;
}

Get Unity compass true north heading

I'm currently trying to implement a location-based AR app for Android using Unity C# and ARCore. I have managed to implement an algorithm which gets latitude/longitude and translates it to unity meters. However, this is not enough to place objects at a GPS location since the orientation of the world will be off if you do not align the unity scene with the real world orientation.
Anyway, the problem with the compass is that I cannot find a way to align an object with the true north.
I have tried aligning an object with true north by using
transform.rotation = Quaternion.Euler(0, -Input.compass.trueHeading, 0);
However this causes the object to constantly change rotation based on where my phone's heading so in a way true north is always changing.
What I am currently trying is:
var xrot = Mathf.Atan2(Input.acceleration.z, Input.acceleration.y);
var yzmag = Mathf.Sqrt(Mathf.Pow(Input.acceleration.y, 2) + Mathf.Pow(Input.acceleration.z, 2));
var zrot = Mathf.Atan2(Input.acceleration.x, yzmag);
xangle = xrot * (180 / Mathf.PI) + 90;
zangle = -zrot * (180 / Mathf.PI);
TheAllParent.transform.eulerAngles = new Vector3(xangle, 0, zangle - Input.compass.trueHeading);
This seems to be working better since the object will point towards a single direction with minimum shaking/jittering of the object due to erratic compass reading but points in one direction nonetheless. However, the problem with this is that it points to a different direction every time the app starts, so true north is never in one place according to the code. However the compass readings are fine as I have checked the readings against other GPS apps which implement a compass.
I have also tried transform.rotation = Quaternion.Euler(0, -Input.compass.magneticHeading, 0); but this gives the same always-changing result as the first one. Any help would be appreciated.
its how i solve this issue in my project
i wish it help you.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class newway : MonoBehaviour
{
GameObject cam;
void Start()
{
cam = Camera.main.gameObject;
Input.location.Start();
Input.compass.enabled = true;
}
void Update()
{
Quaternion cameraRotation = Quaternion.Euler(0, cam.transform.rotation.eulerAngles.y, 0);
Quaternion compass = Quaternion.Euler(0, -Input.compass.magneticHeading, 0);
Quaternion north = Quaternion.Euler(0, cameraRotation.eulerAngles.y + compass.eulerAngles.y, 0);
transform.rotation = north;
}
}
Possibly, your GameObject is rotating on its own axes, but you need your GameObject to pivot around the camera, or the center.
If that's the case, try creating another empty GameObject, and set its position to (0, 0, 0), or wherever you wish the center to be. Then add original GameObject as a child to this new one.
Apply your transform.rotation script to this new GameObject.

How to control oculus rotation and potition in unity 5.3.x

I want to control the rotation and position of the Oculus DK2 in Unity 5.3 over. It doesn't seems to be trivial, I've already tried all I could find on unity forum, but nothing seems to works. The CameraRig script doesn't look to do anything when i change it. I want to disable all rotation and position because I have a mocap system that more reliable for those things.
Need some help!
To be able to control the pose your camera must be represented by using a OVRCameraRig that is included with the OVRPlugin for Unity 5.
Once you have that you can use the UpdatedAnchors event from the camera to transform the mocap data on to the camera position, just overwrite the value of OVRCameraRig.trackerAnchor for the head and OVRCameraRig.leftHandAnchor and OVRCameraRig.rightEyeAnchorfor hand positions if your suit supports those.
public class MocapController : MonoBehavior
{
public OVRCameraRig camera; //Drag camera rig object on to the script in the editor.
void Awake()
{
camera.UpdatedAnchors += UpdateAnchors
}
void UpdatedAnchors(OVRCameraRig rigToUpdate)
{
Transform headTransform = GetHeadTransform(); //Write yourself
Transform lHandTransform = GetLHandTransform(); //Write yourself
Transform rHandTransform = GetRHandTransform(); //Write yourself
rigToUpdate.trackerAnchor = headTransform;
rigToUpdate.leftHandAnchor= lHandTransform;
rigToUpdate.rightHandAnchor= rHandTransform;
}
}

Unity Navmeshagent won't face the target object when reaches stopping distance

I'm trying to get the NPC to look at the main character when I'm talking to him. I need to make sure it looks natural and that he is facing me. I know I can do Transform.LookAt() but that is too instant and unnatural.
How do I rotate the navmeshagent to face my character when its stopped moving?
Try this out to control the body orientation - the slerp is adjustable to your desired rotation speed (https://docs.unity3d.com/ScriptReference/Quaternion.Slerp.html):
private void FaceTarget(Vector3 destination)
{
Vector3 lookPos = destination - transform.position;
lookPos.y = 0;
Quaternion rotation = Quaternion.LookRotation(lookPos);
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, [fill in desired rotation speed]);
}
if(agent.remainingDistance < agent.stoppingDistance)
{
agent.updateRotation = false;
//insert your rotation code here
}
else {
agent.updateRotation = true;
}
This will rotate your agent when it's distance below the stoppingDistance variable. However it will look inhuman, so if you're going for a humanoid ai I'd recommend looking at the unity Mecanim demo (particularly the locomotion scene) as it has code and animations that will properly animate the agent.
Maybe try this Head Look Controller. It's very smooth and blends with animations!
Put the char in a game object and copy the navmesh from the char to the parent, uncheck enable in char. move any scripts up too.
Just spent 5 hours to find this.