Simulate gyroscope in Unity using compass and accelerometer - c#

I have been trying to simulate the gyroscope behavior in unity by using accelerometer and compass. So far I have achieved some functionality but it still has a lag; a delay of response. It does not change the view as fast as the tilt of the mobile phone. Any help is appreciated and thank you in advance.
Note: Z axis rotation is still not added.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GyroSimulator : MonoBehaviour {
float zValue;
float zValueMinMax = 5.0f;
Vector3 accelometerSmoothValue;
//Smooth Accelerometer
public float AccelerometerUpdateInterval = 1.0f / 100.0f;
public float LowPassKernelWidthInSeconds = 0.001f;
public Vector3 lowPassValue = Vector3.zero;
void Start () {
Screen.orientation = ScreenOrientation.LandscapeLeft;
Input.compass.enabled = true;
}
//Update is called once per frame
void Update () {
//Set Z Min Max
if (zValue < -zValueMinMax)
zValue = -zValueMinMax;
if (zValue > zValueMinMax)
zValue = zValueMinMax;
accelometerSmoothValue = LowPass();
zValue += accelometerSmoothValue.z;
transform.rotation = Quaternion.Slerp(
transform.rotation,
Quaternion.Euler(
-zValue*5.0f,
Input.compass.magneticHeading,
0
),
Time.deltaTime*5.0f
);
}
Vector3 LowPass()
{
Vector3 tilt = Input.acceleration;
float LowPassFilterFactor = AccelerometerUpdateInterval / LowPassKernelWidthInSeconds;
lowPassValue = Vector3.Lerp(lowPassValue, tilt, LowPassFilterFactor);
return lowPassValue;
}
}

Related

Increment Car Rotation based onsteering Wheel in Unity using C#

I am trying to build a car simulator in steam VR, I want the car and wheel to rotate by 30 degrees when I rotate the steering by 360, The problem I am facing is when I rotate the steering the 2nd time the car resets back to its original rotation angle that is at 0 to 30 degree again. How can I increment the angles. Below is the code that I tried to increment the angles but it not workingas the posFinal and posInitial are only varying from -0.4 to 0.4.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Valve.VR.InteractionSystem;
[RequireComponent(typeof(Interactable))]
public class RotateWheel : MonoBehaviour {
public Transform Steer;
public Transform Wheel2;
public Transform car;
float scalingFactor = 0.5f;
public float posInitial; public float posFinal; float temp;
void Start()
{
posInitial = 0f;
posFinal = Steer.transform.rotation.y;
car.transform.eulerAngles = new Vector3(0, 0, 0);
Wheel2.transform.eulerAngles=new Vector3(0,0,0);
}
private void FixedUpdate()
{
Wheel2.transform.eulerAngles = new Vector3(-0, ((car.transform.eulerAngles.y+(posFinal-posInitial) )*30f/360), 0);
car.transform.rotation = Quaternion.Slerp(Wheel2.transform.rotation, Quaternion.identity, (Time.deltaTime *5) / scalingFactor);
temp = posInitial;
posInitial = posFinal;
posFinal = Steer.transform.rotation.y;
}

GameObject rotation based Vector2 direction

I apologize in advance for my english.
I have a 2D GameObject and i want to rotate it forward based on Vector2 direction.
my arrow right now:
https://streamable.com/7kmtig
i would like this:
This code rotates arrow:
float angle = Mathf.Atan2(p.direction.y, p.direction.x) * Mathf.Rad2Deg;
punta.transform.rotation = Quaternion.AngleAxis(angle, -Vector3.forward);
punta is arrow GameObject
I created 2 scripts:
PlayerController:
using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public Camera cam;
Vector2 coordinate2D;
public bool direziona = false;
public Rigidbody2D rb;
public Vector2 direction;
public Vector2 mousePotion;
public float distanza;
// Start is called before the first frame update
void Start()
{
direction = Vector2.zero;
mousePotion = Vector2.zero;
distanza = 0;
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
if (hit.collider != null)
{
direziona = true;
}
}
if (direziona)
{
mousePotion = Camera.main.ScreenToWorldPoint(Input.mousePosition);
direction = new Vector2(transform.position.x - mousePotion.x, transform.position.y - mousePotion.y).normalized;
distanza = Mathf.Clamp(Vector2.Distance(mousePotion, transform.position) * 5, 0, 12);
direction = direction * distanza;
if (Input.GetMouseButtonUp(0))
{
rb.AddForce(direction, ForceMode2D.Impulse);
direziona = false;
}
}
}
}
DragLineController:
using System.Collections;
using System.Collections.Generic;
using System.Linq.Expressions;
using TMPro;
using UnityEngine;
public class DragLineController : MonoBehaviour
{
// Start is called before the first frame update
public GameObject player;
public GameObject punta; //sprite arrow
bool ClickPlayer;
LineRenderer _lineRender;
Vector2 startPoint;
Vector2 endPoint;
PlayerController p;
void Start()
{
p = player.GetComponent<PlayerController>();
_lineRender = GetComponent<LineRenderer>();
_lineRender.SetPosition(0, Vector3.zero);
_lineRender.SetPosition(1, Vector3.zero);
}
// Update is called once per frame
void Update()
{
ClickPlayer = player.GetComponent<PlayerController>().direziona;
if (ClickPlayer)
{
startPoint = player.transform.position;
_lineRender.SetPosition(0, startPoint);
float dist =Mathf.Clamp(p.distanza,0,0.3f);
Debug.Log(dist);
endPoint = startPoint + (p.direction * dist);
_lineRender.SetPosition(1, endPoint);
Vector3 FracciaEndPoint = new Vector3(endPoint.x, endPoint.y, -1);
//punta.transform.rotation = Quaternion.LookRotation(p.direction);
punta.transform.position = FracciaEndPoint;
float angle = Mathf.Atan2(p.direction.y, p.direction.x) * Mathf.Rad2Deg;
punta.transform.rotation = Quaternion.AngleAxis(angle, -Vector3.forward);
}
else
{
_lineRender.SetPosition(0, Vector3.zero);
_lineRender.SetPosition(1, Vector3.zero);
}
}
}
Thanks in advance for your availability.
Instead of calculating the rotation for
punta.transform.rotation = Quaternion.AngleAxis(angle, -Vector3.forward);
you could instead simply assign the according axis (I assume the point looks in its Y direction)
punta.transform.up = p.direction;
or .right if instead it points in its local X direction.

Moving Maincamera slowly to another position

I want to move main camera slowly from one point to another point when a button is pressed. This button calls the method which has the code to move the camera.
I have tried using the Lerp method but the camera position is changing so fast that when I click on the button camera directly shifting to a new position. I want the camera to move slowly to a new position.
Below is my code, can anyone please help me with this.
=========================================================================
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Cameramove : MonoBehaviour
{
public GameObject cam;
Vector3 moveToPosition;// This is where the camera will move after the start
float speed = 2f; // this is the speed at which the camera moves
public void move()
{
//Assigning new position to moveTOPosition
moveToPosition = new Vector3(200f, 400f, -220f);
float step = speed * Time.deltaTime;
cam.transform.position = Vector3.Lerp(cam.transform.position, moveToPosition, step);
cam.transform.position = moveToPosition;
}
}
It's easier to use lerp with frames and you need to use it in an Update function. Try using the example from the Unity docs:
public int interpolationFramesCount = 45; // Number of frames to completely interpolate between the 2 positions
int elapsedFrames = 0;
void Update()
{
float interpolationRatio = (float)elapsedFrames / interpolationFramesCount;
Vector3 interpolatedPosition = Vector3.Lerp(Vector3.up, Vector3.forward, interpolationRatio);
elapsedFrames = (elapsedFrames + 1) % (interpolationFramesCount + 1); // reset elapsedFrames to zero after it reached (interpolationFramesCount + 1)
Debug.DrawLine(Vector3.zero, Vector3.up, Color.green);
Debug.DrawLine(Vector3.zero, Vector3.forward, Color.blue);
Debug.DrawLine(Vector3.zero, interpolatedPosition, Color.yellow);
}
Try using smooth damp.
Here is the new code you should try:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Cameramove : MonoBehaviour
{
Vector3 matric;
public GameObject cam;
Vector3 moveToPosition;
float speed = 2f;
bool move_ = false;
void Update(){
if(move_){
//Assigning new position to moveTOPosition
moveToPosition = new Vector3(200f, 400f, -220f);
cam.transform.position =
Vector3.SmoothDamp(cam.transform.position,
moveToPosition,
ref matric, speed);
}
}
public void move()
{
move_ = true;
}
}

Unity - Quaternion.Slerp instantly rotating

I am trying to have my object smoothly rotate on the Z axis from 0 to 180, back and forth on every button press.
The Quaternion.Slerp setup i'm using does not smoothly rotate to the target rotation, rather it instantly jumps to a number close to it. After many button presses that call the Quaternion.Slerp, it it finally halfs works in that it goes from 0 to 180, but still instantly and not smoothly.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float moveSpeed;
public bool movePlayer;
private float maxMoveSpeed;
public float waitToMove;
Rigidbody2D thisRigidbody;
//SCOOP variables
private GameObject scoop;
private GameObject scoopRotation;
Quaternion currentScoopRotation;
public Quaternion targetScoopRotation;
Quaternion lastScoopRotation;
public float scoopRotateTime;
// Use this for initialization
void Start ()
{
thisRigidbody = gameObject.GetComponent<Rigidbody2D> ();
maxMoveSpeed = moveSpeed;
//SCOOP finders
scoop = GameObject.FindGameObjectWithTag ("Scoop");
currentScoopRotation = scoop.transform.rotation;
}
// Update is called once per frame
void Update ()
{
if(movePlayer)
thisRigidbody.velocity = new Vector2 (moveSpeed, thisRigidbody.velocity.y);
//Rotates SCOOP using Quaternions + Spacebar
if (Input.GetKeyDown(KeyCode.Space)) {
lastScoopRotation = currentScoopRotation;
scoop.transform.transform.rotation = Quaternion.Lerp (currentScoopRotation, targetScoopRotation, scoopRotateTime * Time.time);
currentScoopRotation = targetScoopRotation;
targetScoopRotation = lastScoopRotation;
changeMoveDirection ();
}
}
void changeMoveDirection()
{
moveSpeed *= -1;
}
IEnumerator changeDirectionCO()
{
//thisRigidbody.velocity = new Vector2 (0f,0f);
//moveSpeed = 0;
yield return new WaitForSeconds (waitToMove);
moveSpeed *= -1;
}
}

Shooting to the center of the screen

This code is used to fire laser straight forward.
using UnityEngine;
using System.Collections;
public class LeftGun : MonoBehaviour {
public Rigidbody laser;
public AudioClip LaserShot;
float shotSpeed = 0.1f;
bool canShoot = true;
// Update is called once per frame
void Update () {
if(!Engine.escape)
{
shotSpeed -= Time.deltaTime;
if(shotSpeed <= 0f)
canShoot = true;
if(Input.GetButton("Fire1") && canShoot)
{
shotSpeed = 0.1f;
canShoot = false;
PlayerGUI.ammunition--;
audio.PlayOneShot(LaserShot);
Rigidbody clone = Instantiate(laser,transform.position, transform.rotation) as Rigidbody;
clone.velocity = transform.TransformDirection(-80, 0, 0);
Destroy(clone.gameObject, 3);
}
}
}
I would like to fire to the center of the screen (where crosshair is). How can I achive that?
Example image: http://i.imgur.com/EsVsQNd.png
You can use Camera.ScreenPointToRay. To get the ray from center of the main camera, use:
float x = Screen.width / 2f;
float y = Screen.height / 2f;
var ray = Camera.main.ScreenPointToRay(new Vector3(x, y, 0));
clone.velocity = ray.direction * laserSpeed;
laserSpeed is a public float which is the speed with which you want the laser to travel at. You can change it according to your needs (for the code you provided, laserSpeed would be 80).

Categories