how to build gyroscope above the current phone direction - c#

public class GyroControl : MonoBehaviour
{
private bool gyroEnabled;
private Gyroscope gyro;
private GameObject cameraContainer;
private Quaternion rot;
private void Start()
{
cameraContainer = new GameObject("Camera Container");
cameraContainer.transform.position = transform.position;
transform.SetParent(cameraContainer.transform);
gyroEnabled = EnableGyro();
}
private bool EnableGyro()
{
if (SystemInfo.supportsGyroscope)
{
gyro = Input.gyro;
gyro.enabled = true;
cameraContainer.transform.rotation = Quaternion.Euler(90f, 0f, -90f);
rot = new Quaternion(0, 0, 1, 0);
return true;
}
return false;
}
private void Update()
{
if (gyroEnabled)
{
transform.localRotation = gyro.attitude * rot;
}
}
}
i have a game that build with using gyroscope but the gyroscope use world rotation i don't want that i want whenever i start the game and my phone direction anywhere it makes it the start rotation , i mean if i start the game i will use the same camera rotation and move right and left by the gyro scope value .
i tried this :
private Quaternion initialRot;
/
private bool EnableGyro()
{
if (SystemInfo.supportsGyroscope)
{
gyro = Input.gyro;
gyro.enabled = true;
initialRot = gyro.attitude;
cameraContainer.transform.rotation = Quaternion.Euler(0f, 0f, 0f);
return true;
}
return false;
}
/
private void Update()
{
if (gyroEnabled)
{
transform.localRotation = gyro.attitude * Quaternion.Inverse(initialRot);
}
}
in the end i want to make the gyro value build above the current phone direciotn

Your second script is the most logical solution.
Try using vectors instead of Quaternions, as they should be easier to manage and debug.
The initialRot variable, transform it into Vector3 adds in the Update () method:
private Vector3 initialRot;
...
private bool EnableGyro()
{
if (SystemInfo.supportsGyroscope)
{
gyro = Input.gyro;
gyro.enabled = true;
initialRot = gyro.attitude.eulerAngles;
cameraContainer.transform.rotation = Quaternion.Euler(0f, 0f, 0f);
return true;
}
return false;
}
...
private void Update()
{
if (gyroEnabled)
{
transform.localEulerAngles = gyro.attitude.eulerAngles + initialRot;
}
}

You're almost correct. You need to do left multiplication with the inverse instead of right.
init:
initialRot = getDeviceRotation()
step:
localRot = inverse(initialRot)*getDeviceRotation()
If you only want to initialize the rotation about the gravity axis, you can implement and use the align function at https://stackoverflow.com/a/73103883/3159048
init:
initialRot = align(getDeviceRotation(), gravityVec, gravityVec)

Related

Passing List to another GameObject script, it becomes empty after first operation

I am trying to move a GameObject along a path by stages. Conceptually a first script, connected to the controller, defines the path via a List of Vector3 and a second one connected to the object moves it. To move it first rotates to face the destination and then it simply moves by incrementing transform.position by small steps.
The problem is that once the first part of the path has been completed the rest seems to cancel out (the Count became 0) and the robot stops.
This only happens by giving the list from a second script, trying it with a pre-defined list in the same script works fine.
This is the motion code:
public List<Vector3> pathRover;
[SerializeField] private float roverSpeed;
[SerializeField] private float roverRotateSpeed;
private float dotto;
private bool isRotating = false;
private bool isLerping = false;
private Vector3 startPosition;
private Vector3 targetPosition;
private void FixedUpdate()
{
if (isRotating)
{
//To determine whether the robot faces the direction of movement
dotto = Vector3.Dot(transform.TransformDirection(Vector3.forward), (new Vector3(targetPosition.x, 0, targetPosition.z) - new Vector3(startPosition.x, 0, startPosition.z)).normalized);
if (dotto < 0.98f) // rotate until reached then move
{
transform.Rotate(0, Time.deltaTime * roverRotateSpeed, 0);
Debug.Log(dotto);
}
else
{
isLerping = true;
isRotating = false;
}
}
else if (isLerping)
{
var step = roverSpeed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, targetPosition, step);
if (Vector3.Distance(transform.position, targetPosition) <= 1f)
{
NextStep();
}
}
}
public void StartMoving(List<Vector3> pathReceived)
{
if (pathReceived.Count > 1)
{
pathRover.Clear();
for (int i = 1; i < pathReceived.Count; i++)
{
pathRover.Add(pathReceived[i]);
}
startPosition = transform.position;
targetPosition = new Vector3(pathRover[0].x, pathRover[0].y + 0.7f, pathRover[0].z); //0.7f for the height of the rover from the ground
isRotating = true;
}
else
{
StopMoving();
}
}
public void StopMoving()
{
isRotating = false;
isLerping = false;
pathRover.Clear();
}
public void NextStep()
{
isLerping = false;
StartMoving(pathRover);
}
From the other script:
roverMover.StartMoving(percorsoList);
No error appears in the debug console, I don't know where I am wrong.
I guess the problem is you are starting the move right at the Start of the script but you call StartMoving after a while. You have to move only when StartMove is called.
public List<Vector3> pathRover;
[SerializeField] private float roverSpeed;
[SerializeField] private float roverRotateSpeed;
private float dotto;
private bool isRotating = false;
private bool isLerping = false;
private Vector3 startPosition;
private Vector3 targetPosition;
boolean startMove = false;
private void FixedUpdate()
{
if(startMove)
Move();
}
public void Move(){
if (isRotating)
{
//To determine whether the robot faces the direction of movement
dotto = Vector3.Dot(transform.TransformDirection(Vector3.forward), (new Vector3(targetPosition.x, 0, targetPosition.z) - new Vector3(startPosition.x, 0, startPosition.z)).normalized);
if (dotto < 0.98f) // rotate until reached then move
{
transform.Rotate(0, Time.deltaTime * roverRotateSpeed, 0);
Debug.Log(dotto);
}
else
{
isLerping = true;
isRotating = false;
}
}
else if (isLerping)
{
var step = roverSpeed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, targetPosition, step);
if (Vector3.Distance(transform.position, targetPosition) <= 1f)
{
NextStep();
}
}
}
public void StartMoving(List<Vector3> pathReceived)
{
startMove= true;
if (pathReceived.Count > 1)
{
pathRover.Clear();
for (int i = 1; i < pathReceived.Count; i++)
{
pathRover.Add(pathReceived[i]);
}
startPosition = transform.position;
targetPosition = new Vector3(pathRover[0].x, pathRover[0].y + 0.7f, pathRover[0].z); //0.7f for the height of the rover from the ground
isRotating = true;
}
else
{
StopMoving();
}
}
public void StopMoving()
{
isRotating = false;
isLerping = false;
pathRover.Clear();
}
public void NextStep()
{
isLerping = false;
StartMoving(pathRover);
}

Unity3D Configurable Joint component accessing through GetComponentInChildren

I have a capsule and a sphere connected by a Configurable Joint. I move the player using the capsule rigidbody and the sphere acts as a caster wheel(like a unicycle with suspension).
As the sphere is a child of the capsule, I am using GetComponentInChildren to try and access the Configurable Joint's, Y Drive's, Position Spring (float value).
I got lost trying to google this problem.
Here is the relevant code, everything in //Comment does not work:
public class PlayerMovement : MonoBehaviour
{
private Rigidbody rb;
public float moveSpeed = 10f;
public float distanceGround;
public bool isGrounded = false;
public bool isCrouch = false;
void Awake()
{
rb = GetComponent<Rigidbody>();
}
void Start()
{
distanceGround = GetComponent<Collider>().bounds.extents.y;
}
void FixedUpdate()
{
Movement();
}
private void Movement()
{
float inputX = Input.GetAxis("LStickHorz");
float InputZ = -Input.GetAxis("LStickVert");
float multiplier = 1f;
if (!Physics.Raycast (transform.position, -Vector3.up, distanceGround + 1.5f))
{
isGrounded = false;
print("IN AIR.....");
}
else
{
isGrounded = true;
print("....onGround");
//Debug.DrawRay(?,?, Color.red, 1.25f);
}
if (Physics.Raycast (transform.position, -Vector3.up, distanceGround + .2f))
{
isCrouch = true;
print("VVVVVVVVVVVVVV");
//ConfigurableJoint cj = gameObject.GetComponentInChildren(typeof(ConfigurableJoint)) as ConfigurableJoint;
//set y spring value
//cj.yDrive.positionSpring = 50f;
}
else
{
isCrouch = false;
}
if (!isGrounded)
{
multiplier = .2f;
}
if (isCrouch)
{
multiplier = .2f;
}
Vector3 moveVector = new Vector3(inputX * multiplier, 0.0f, InputZ * multiplier);
//if ()
rb.AddForce(moveVector * moveSpeed);
}
}
Let's start with your first comment, the function Debug.DrawRay(). If you look at the documentation here it will tell you all parameters of the function and show you an example. For this function, the first two parameters are position and direction:
Debug.DrawRay(transform.position, Vector3.up * 5, Color.red, 1.25f)
The second issue is you cannot set the positionSpring field directly. You will need to store a reference to the yDrive in another variable, change the value of positionSpring, then set yDrive to the temp variable:
// Get the COnfigurableJoint component
ConfigurableJoint cj = gameObject.GetComponent<ConfigurableJoint>();
// Grab a reference to the JointDrive
JointDrive jd = cj.yDrive;
// Set the value of positionSpring here
jd.positionSpring = 50.0f;
// Apply the changes you made to the yDrive back to the ConfigurableJoint
cj.yDrive = jd;

Unity c# Flick object to direction regardless of camera angle

I have this following particular code to flick an object forward by swiping in the direction that i want. The issue is that my camera angle is rotated so whenever i flick the object to the center or left, the flick isnt accurate. When i flick anywhere to the right, the object is thrown precisely. How can i adjust this code so that the object is throw to the world space direction regardless of camera rotation please. Thanks.
Code:`public class SwipeScript : MonoBehaviour
{
public float force = 2f;
public bool isTarget = false;
public float zFactor = 2f;
public Vector3 startPosition;
private Vector2 startSwipe;
private Vector2 endSwipe;
private Rigidbody currentBoxRb;
void Start()
{
currentBoxRb = StackerManager.currentBox.GetComponent<Rigidbody>();
startPosition = new Vector3(transform.position.x, transform.position.y, transform.position.z);
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
startSwipe = Camera.main.ScreenToViewportPoint(Input.mousePosition);
}
if (Input.GetMouseButtonUp(0))
{
endSwipe = Camera.main.ScreenToViewportPoint(Input.mousePosition);
if (isTarget == true)
{
Swipe();
isTarget = false;
}
}
}
void Swipe()
{
Vector3 swipe = endSwipe - startSwipe;
swipe.z = swipe.y / zFactor;
swipe.y = -0.001f;
currentBoxRb.isKinematic = false;
currentBoxRb.AddForce(swipe * force, ForceMode.Impulse);
}
private void OnMouseDown()
{
currentBoxRb.constraints = RigidbodyConstraints.None;
isTarget = true;
}
}

How to prevent a player from moving through walls in Unity3d

I've got the following player controller:
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
[RequireComponent(typeof(NetworkIdentity))]
public class PlayerController : NetworkBehaviour {
public Vector3 size = new Vector3(1, 1, 1);
public float speed = 10;
public float rotateSpeed = 9;
private Transform _transform;
private Map _map;
private BoxCollider _collider;
private bool _active = false;
private Vector3 _lastPosition;
private bool _isGrounded = false;
void Start () {
_transform = transform;
Messenger.AddListener ("MAP_LOADED", OnMapLoaded);
_transform.localPosition = new Vector3 (-100, -100, -100);
gameObject.name = "Player " + gameObject.GetComponent<NetworkIdentity> ().netId.Value;
_collider = gameObject.GetComponent<BoxCollider> ();
_map = GameObject.Find ("Map").GetComponent<Map> ();
_collider.size = size;
}
void OnMapLoaded () {
if (isLocalPlayer) {
// Hook up the camera
PlayerCamera cam = Camera.main.GetComponent<PlayerCamera>();
cam.target = transform;
// Move the player to the it's spawn location
_transform.localPosition = _map.GetPlayerSpawn();
}
// Set the player as active
_active = true;
}
void Update () {
if (!isLocalPlayer || !_active) {
return;
}
_lastPosition = _transform.position;
float transAmount = speed * Time.deltaTime;
float rotateAmount = rotateSpeed * Time.deltaTime;
if (Input.GetKey ("up")) {
transform.Translate (0, 0, transAmount);
}
if (Input.GetKey ("down")) {
transform.Translate (0, 0, -transAmount);
}
if (Input.GetKey ("left")) {
transform.Rotate (0, -rotateAmount, 0);
}
if (Input.GetKey ("right")) {
transform.Rotate (0, rotateAmount, 0);
}
if (!_isGrounded) {
Vector3 down = _transform.TransformDirection(Vector3.down);
_transform.position += down * Time.deltaTime * _map.gravity;
}
}
void FixedUpdate () {
//
// Check what is below us
//
Vector3 down = _transform.TransformDirection(Vector3.down);
RaycastHit[] hits;
hits = Physics.RaycastAll(_transform.position, down, size.y + 0.001f);
_isGrounded = false;
foreach (RaycastHit hit in hits) {
if (hit.collider.gameObject.tag.ToUpper() == "GROUND") {
_isGrounded = true;
}
}
}
void OnTriggerEnter(Collider collider) {
Debug.Log ("Triggered by " + collider.gameObject.tag.ToUpper ());
if (collider.gameObject.tag.ToUpper () == "GROUND") {
transform.position = _lastPosition;
}
}
}
In Update I'm taking the user's input and moving the transform around. In FixedUpdate I'm checking to see if the player is on the ground and setting a flag appropriately. And finally in OnTriggerEnter I'm checking to see if I'm trying to go through anything.
If in OnTriggerEnter I hit something I try to set the player's position back to a good one, but that's not happening. My guess is because _lastPosition isn't what I'm expecting it to be.
Is there a better way to do this?
Use rigidbody.Move(position) instead of transform.Translate(position).
Note: Using transform.translate causing performance issues and you must handle collision detection manually.

Why does this strange jittering occur?

I have a scene in which the player can pick up and drop objects, as well as move and look around.
All player objects are children of an empty game object "MainCharacter":
MainCharacter >
Capsule (With RigidBody and PlayerMoveScript) >
PlayerBase (empty - used for checking if grounded)
MainCamera >
Hands(With PickUpDrop script)
The object I pick up Lerps to my Hands position, however after my capsule collides with any walls there is a strange jittering which I cannot work out how to fix!!
Heres the .exe:GameTest
Heres the data folder : Data
Here are the scripts:
Pick Up and Drop Script:
public bool handsFull = false;
public float distanceMax = 20f;
public Transform handPosition;
public LayerMask canPickUp;
public GameObject taggedGameObject;
public bool colliderTriggered;
public bool bounds;
public PickedUpObject pickedUpScript;
public Rigidbody player;
// Use this for initialization
void Start () {
print(FindClosestPickup().name);
handPosition = transform;
pickedUpScript = null;
}
// Update is called once per frame
void Update () {
if (Input.GetKeyDown (KeyCode.E) && !bounds) {
if (Physics.CheckSphere (handPosition.position, 2f, canPickUp)) {
if (handsFull) {
Drop ();
}
if (!handsFull) {
PickedUp ();
}
handsFull = !handsFull;
}
}
if (handsFull) {
RotateMovePickedUpObject();
}
}
private void PickedUp(){
//Closest object to top of list
taggedGameObject = (GameObject)FindClosestPickup();
taggedGameObject.collider.isTrigger = true;
taggedGameObject.rigidbody.useGravity = false;
taggedGameObject.rigidbody.isKinematic = true;
pickedUpScript = taggedGameObject.GetComponent<PickedUpObject> ();
Debug.Log ("Pick Up");
}
private void RotateMovePickedUpObject(){
//Rotate
if(Input.GetKeyDown(KeyCode.End)){
taggedGameObject.transform.localRotation *= Quaternion.Euler(0, 0, 45);
}
if(Input.GetKeyDown(KeyCode.Delete)){
taggedGameObject.transform.localRotation *= Quaternion.Euler(0, 45, 0);
}
if(Input.GetKeyDown(KeyCode.PageDown)){
taggedGameObject.transform.localRotation *= Quaternion.Euler(0, -45, 0);
}
if(Input.GetKeyDown(KeyCode.Home)){
taggedGameObject.transform.localRotation *= Quaternion.Euler(0, 0, -45);
}
if(Input.GetKeyDown(KeyCode.PageUp)){
taggedGameObject.transform.localRotation *= Quaternion.Euler(-45, 0, 0);
}
if(Input.GetKeyDown(KeyCode.Insert)){
taggedGameObject.transform.localRotation *= Quaternion.Euler(45, 0, 0);
}
taggedGameObject.transform.position = Vector3.Lerp(taggedGameObject.transform.position, handPosition.position, (1 - Mathf.Exp( -20 * Time.smoothDeltaTime )) * 10);
}
private void Drop(){
taggedGameObject.collider.isTrigger = false;
taggedGameObject.rigidbody.useGravity = true;
taggedGameObject.rigidbody.isKinematic = false;
taggedGameObject = null;
Debug.Log ("Drop");
pickedUpScript = null;
}
private GameObject FindClosestPickup() {
//Find closest gameobject with tag
GameObject[] gos;
gos = GameObject.FindGameObjectsWithTag("pickup");
GameObject closest = null;
float distance = Mathf.Infinity;
Vector3 position = transform.position;
foreach (GameObject go in gos) {
Vector3 diff = go.transform.position - position;
float curDistance = diff.sqrMagnitude;
if (curDistance < distance) {
closest = go;
distance = curDistance;
}
}
return closest;
}
}
The Picked Up Objects Script:
public PickUpDrop pickUpScript;
public GameObject thisOne;
public Color thecolor;
public bool inObject;
// Use this for initialization
void Start () {
thisOne = this.gameObject;
}
// Update is called once per frame
void Update ()
{
thecolor = thisOne.renderer.material.color;
if (pickUpScript.taggedGameObject != thisOne)
{
gameObject.renderer.material.color = Color.gray;
}
if (pickUpScript.taggedGameObject == thisOne)
{
Color color = renderer.material.color;
color.a = 0.5f;
renderer.material.color = color;
}
}
void OnTriggerEnter ()
{
if (thisOne == pickUpScript.taggedGameObject)
{
inObject = true;
pickUpScript.bounds = true;
gameObject.renderer.material.color = Color.red;
}
}
void OnTriggerExit()
{
if(thisOne == pickUpScript.taggedGameObject)
{
inObject = false;
pickUpScript.bounds = false;
gameObject.renderer.material.color = Color.gray;
}
}
}
taggedGameObject.transform.position = Vector3.Lerp(taggedGameObject.transform.position, handPosition.position, (1 - Mathf.Exp( -20 * Time.smoothDeltaTime )) * 10);
This line will keep moving the object towards the hand's position. If you have a rigidbody attached to the game object you're moving then the physics acting on that object during the physics calculation will conflict with the manual movement of the object during the Update function.
It depends on what you would like to happen when this conflict occurs as to the solution. If you simply want the 'jittering' to stop and still be able to hold objects against other physical objects, then use this;
taggedGameObject.rigidbody.AddForce( ( taggedGameObject.transform.position - handPosition.position ) * force );
This will keep all interactions with the rigidbody. You'll have to tweak the force you move the object with, and perhaps disable gravity on the tagged game object while it's in the players hands. But it should have the desired effect.

Categories

Resources