[英]How to enable gyroscope camera at current device orientation
我想啟用陀螺儀控制的相機 onButtonClick 事件,但我希望它從相機當前的 position 開始。 目前,當陀螺儀啟用時,它會將相機移至新的 position(可能是設備當前的陀螺儀旋轉),而不是將其留在原處並從該點開始旋轉。
希望我說得有道理,但基本上我不希望用戶注意到他們在游戲中看到的任何變化(即由陀螺儀控制的相機,但用戶不會注意到這種變化)。 這是我正在使用的代碼:
void Update ()
{
Quaternion attitudeFix = new Quaternion (-gyro.attitude.x, -gyro.attitude.z, -gyro.attitude.y, gyro.attitude.w);
Quaternion offsetRotation = initialGyroRotation * attitudeFix;
rotation = initialRotation * offsetRotation;
transform.rotation = rotation;
}
public void EnableGyro()
{
initialGyroRotation = Input.gyro.attitude;
initialRotation = transform.rotation;
Debug.Log("initialRotation: " + initialRotation.ToString());
Debug.Log("transform.rotation: " + transform.rotation.ToString());
Debug.Log("initialGyroRotation: " + initialGyroRotation.ToString());
}
**
編輯:這是一個屏幕,顯示了當用戶將設備放在臉前(肖像)並向北行駛時,我希望視圖看起來如何。 無論應用程序啟動時設備的方向如何,當手機以縱向方向向北行駛時(再次當用戶通過手機查看時),它應該是這樣的。
編輯 2:測試變得令人困惑,所以我將代碼放回您的解決方案所建議的方式。 仍然有一個小問題,但看起來這個腳本非常接近。 主要問題是當我運行每個測試時屏幕看起來不像上面的圖片,使用設備以奇怪的角度啟動應用程序。 啟動應用程序時設備的角度並不重要,指向北方和縱向時它需要看起來像上面的屏幕。
我需要做更多的測試,並且會用一個新的/干凈的項目來做。
您需要在“ Awake
或“ Start
功能中獲取攝像機的偏移位置。 在Update
功能中,將該偏移值應用於陀螺儀傳感器的值。
看來您已經知道應該使用偏移量,但是您這樣做的方式不正確。 令人困惑的部分是獲取偏移量,該偏移量需要從陀螺儀傳感器值中減去當前攝像機的旋轉角度。
要減去Quaternion
乘Inverse
Quaternion
,而不只是Quaternion
:
Quaternion = Quaternion *
Quaternion.Inverse
要添加Quaternion
乘以Quaternion
:
Quaternion = Quaternion * Quaternion.
這是您的代碼應如下所示:
Quaternion offset;
void Awake()
{
Input.gyro.enabled = true;
}
void Start()
{
//Subtract Quaternion
offset = transform.rotation * Quaternion.Inverse(GyroToUnity(Input.gyro.attitude));
}
void Update()
{
GyroModifyCamera();
}
void GyroModifyCamera()
{
//Apply offset
transform.rotation = offset * GyroToUnity(Input.gyro.attitude);
}
private static Quaternion GyroToUnity(Quaternion q)
{
return new Quaternion(q.x, q.y, -q.z, -q.w);
}
我遇到了麻煩,它在構建中不起作用這是我發現的,這個腳本已經工作了。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class GyroMovement : MonoBehaviour
{
// Start is called before the first frame update
//Movement
[SerializeField] float speed = 3.3f;
private float rotspeed = 90f;
private Vector3 moveDirection = Vector3.zero;
[SerializeField] private CharacterController controller;
//Rotation
private float _initialYAngle = 0f;
private float _appliedGyroYAngle = 0f;
private float _calibrationYAngle = 0f;
private Transform _rawGyroRotation;
private float _tempSmoothing;
//settings
private float _smoothing = 0.1f;
private void Update(){
//Movement
//Vector3 move = new Vector3 (Input.acceleration.x * speed * Time.deltaTime, 0f, -Input.acceleration.z * speed * Time.deltaTime);
//Vector3 rotMovement = transform.TransformDirection(move);
//controller.Move(rotMovement);
//Rotation
ApplyGyroRotation();
ApplyCalibration();
transform.rotation = Quaternion.Slerp(transform.rotation, _rawGyroRotation.rotation, _smoothing);
}
private IEnumerator Start(){
Input.gyro.enabled = true;
Application.targetFrameRate = 60;
_initialYAngle = transform.eulerAngles.y;
_rawGyroRotation = new GameObject("GyroRaw").transform;
_rawGyroRotation.position = transform.position;
_rawGyroRotation.rotation = transform.rotation;
yield return new WaitForSeconds(1f);
StartCoroutine (CalibrateYAngle());
}
private IEnumerator CalibrateYAngle(){
_tempSmoothing = _smoothing;
_smoothing = 1f;
_calibrationYAngle = _appliedGyroYAngle - _initialYAngle;
yield return null;
_smoothing = _tempSmoothing;
}
private void ApplyGyroRotation(){
_rawGyroRotation.rotation = Input.gyro.attitude;
_rawGyroRotation.Rotate(0f, 0f, 180f, Space.Self);
_rawGyroRotation.Rotate(90f, 180f, 0f, Space.World);
_appliedGyroYAngle = _rawGyroRotation.eulerAngles.y;
}
private void ApplyCalibration(){
_rawGyroRotation.Rotate(0f, -_calibrationYAngle, 0f, Space.World);
}
public void SetEnabled (bool value){
enabled = true;
StartCoroutine(CalibrateYAngle());
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.