Unity - How to rotate an object based on touch? - c#

I'm creating a game for iOS devices. I want my player or gameobject to rotate based on touch. I'm using the following code in touchPhase.Moved
if (Input.touchCount > 0 && Input.GetTouch (0).phase == TouchPhase.Moved)
{
coinTouched = true;
if (coinTouched)
{
Vector2 currentTouchPosition = Input.GetTouch (0).position;
endPos = new Vector3 (currentTouchPosition.x, 0, currentTouchPosition.y);
endTime = Time.time;
gameObject.transform.rotation = Quaternion.Euler(0f,Input.GetTouch(0).deltaPosition.x * 1.0f,0f);
}
}
But it is behaving awkward. it rotates good for almost 180 degree and then it moves in the opposite direction and after another 180 it rotates in the opposite direction and so on. Please help me.
Thank You.

Your code is a little weird. Meaning you use the x and y values in the wrong spots of the Vecotr. I'm going to assume you did this on purpose to get the cube to turn correctly. I would use the Rotate instead of changing the rotation value.
Here is a better than I can do:
http://answers.unity3d.com/questions/255118/rotating-an-object-with-touch.html

Related

Not able to clamp camera's rotation

So I have this code in my LateUpdate function attached to my camera gameObject. I'm trying to rotate around a unity default cube as if it was an orbit. I have got the motion right but I'm not able to clamp the value... Here's the code.
if (Input.GetMouseButtonDown(0))
{
mInitialPosition = Input.mousePosition.x;
}
if (Input.GetMouseButton(0))
{
mChangedPosition = Input.mousePosition.x;
float difference = mChangedPosition - mInitialPosition;
if (mChangedPosition < mInitialPosition || mChangedPosition > mInitialPosition)
{
Rotation(-difference);
}
}
private void Rotation(float inDifference)
{
if (transform.eulerAngles.y < 60f && transform.eulerAngles.y > -60f)
{
transform.RotateAround(mTargetToRotateAround.position, transform.up, inDifference * Time.deltaTime);
}
}
Im tried to clamp the value this way as mathf.clamp dint seem to work out for me... So here i am telling it to do the rotation function responsible for the rotation to happen only when camera-y rotation is below 60f and above -60f. But the rotation behaves super weird and i am super confused. So I did a bit of research on what value does the camera transform show outside in inspector window. Then i realized it was euler angles and not quaternion. Now i changed my code to euler but when i debug.log the value of camera.transform.eulerangles.y the value goes from 0 to 360. But in inspector the y value when reaching less than 0 starts printing -1 and so but in debug it shows 360,359 and so on.
How to get the exact rotation value that there printed in inspector so I can clamp my camera accordingly?
Or is there any way to clamp my camera dont want it to go more that 60 degrees on both left and right!

Rotating player towards their heading

I'm trying to replicate a movement system from an old flash game I'm basing a game I'm making in unity on (just for practice, mostly.) The main problem I have is that the player doesn't 'look' towards where he is going. He just looks in the direction all the time.
Here's what mine currently looks like
and here's what I want it to look like.
I've tried doing it but I couldn't find a solution that worked nicely (and the code for it is long gone). If someone could help me implement such a thing, that would be great!
The code for my player control:
public void PlayerFixedUpdate () {
if (Input.GetKey(KeyCode.A) && transform.position.x > -44){
if (body.velocity.x > -15){
body.AddForce(new Vector2(-15,0),ForceMode2D.Force);
}
}
if (Input.GetKey(KeyCode.D) && transform.position.x < 9){
if (body.velocity.x < 15){
body.AddForce(new Vector2(15,0),ForceMode2D.Force);
}
}
if (Input.GetKey(KeyCode.W) && transform.position.y < 24){
if (body.velocity.y < 15*body.mass){
body.AddForce(new Vector2(0,15),ForceMode2D.Force);
}
}
if (Input.GetKey(KeyCode.S) && transform.position.y > -1){
if (body.velocity.y > -15*body.mass){
body.AddForce(new Vector2(0,-15),ForceMode2D.Force);
}
}
}
Depends how your object is set up, but one solution would be to set the rotation in the direction of the velocity component.
void rotateFace()
{
Vector2 dir = rbody.velocity.normalized; // where rbody is your rigidbody2D
transform.rotation = Quaternion.Euler(0, 0, Mathf.Atan2(dir.y, dir.x)*Mathf.Rad2Deg - 90); //may not need 90deg offset here
}
You may want to include a check for zero velocity, in which case you should do nothing to maintain the last rotation.
The second link shows like they are moving in one direction always and that is just the direction in which the character is facing, basically what they do is Just rotate the character using the player input and keep applying velocity in the local forward direction of the player.

Gyroscope with compass help needed

I need to have a game object point north AND I want to combine this with gyro.attitude input. I have tried, unsuccessfully, to do this in one step. That is, I couldn't make any gyro script, which I found on the net, work with the additional requirement of always pointing north. Trust me, I have tried every script I could find on the subject. I deduced that it's impossible and probably was stupid to think it could be done; at least not this way (i.e. all-in-one). I guess you could say I surmised that you can't do two things at once. Then I thought possibly I could get the same effect by breaking-up the duties. That is, a game object that always points north via the Y axis. Great, got that done like this:
_parentDummyRotationObject.transform.rotation = Quaternion.Slerp(_parentDummyRotationObject.transform.rotation, Quaternion.Euler(0, 360 - Input.compass.trueHeading, 0), Time.deltaTime * 5f);
And with the game object pointing north on the Y, I wanted to add the second game-object, a camera in this case, with rotation using gyro input on the X and Z axis. The reason I have to eliminate the Y axes on the camera is because I get double rotation. With two things rotating at once (i.e. camera and game-object), a 180 degree rotation yielded 360 in the scene. Remember I need the game object to always point north (IRL) based on the device compass. If my device is pointing towards the East, then my game-object would be rotated 90 degrees in the unity scene as it points (rotation) towards the north.
I have read a lot about gyro camera controllers and one thing I see mentioned a lot is you shouldn't try to do this (limit it) on just 1 or 2 axis, when using Quaternions it's impossible when you don't know what you're doing, which I clearly do not.
I have tried all 3 solutions from this solved question: Unity - Gyroscope - Rotation Around One Axis Only and each has failed to rotate my camera on 1 axis to satisfy my rotational needs. Figured I'd try getting 1 axis working before muddying the waters with the 2nd axis. BTW, my requirements are simply that the camera should only rotate on 1 axis (in any orientation) based on the X axis of my device. If I could solve for X, then I thought it'd be great to get Z gyro input to control the camera as well. So far I cannot get the camera controlled on just 1 axis (X). Anyway, here are my findings...
The first solution, which used Input.gyro.rotationRateUnbiased, was totally inaccurate. That is, if I rotated my device around a few times and then put my phone/device down on my desk, the camera would be in a different rotation/location each time. There was no consistency. Here's my code for the first attempt/solution:
<code>
private void Update()
{
Vector3 previousEulerAngles = transform.eulerAngles;
Vector3 gyroInput = Input.gyro.rotationRateUnbiased;
Vector3 targetEulerAngles = previousEulerAngles + gyroInput * Time.deltaTime * Mathf.Rad2Deg;
targetEulerAngles.y = 0.0f;
targetEulerAngles.z = 0.0f;
transform.eulerAngles = targetEulerAngles;
}
</code>
The second solution was very consistent in that I could rotate my device around and then put it down on the desk and the unity camera always ended up in the same location/rotation/state so-to-speak. The problem I had was the camera would rotate on the one axis (X in this case), but it did so when I rotated my device on either the y or x axis. Either type of rotation/movement of my phone caused the unity camera to move on the X. I don't understand why the y rotation of my phone caused the camera to rotate on X. Here is my code for solution #2:
private void Start()
{
Input.gyro.enabled = true;
startEulerAngles = transform.eulerAngles;
startGyroAttitudeToEuler = Input.gyro.attitude.eulerAngles;
}
private void Update()
{
Vector3 deltaEulerAngles = Input.gyro.attitude.eulerAngles - startGyroAttitudeToEuler;
deltaEulerAngles.y = 0.0f;
deltaEulerAngles.z = 0.0f;
transform.eulerAngles = startEulerAngles - deltaEulerAngles;
}
The 3rd solution: I wasn't sure how to complete this last solution, so it never really worked. With the 2 axis zeroed-out, the camera just flipped from facing left to right and back, or top to bottom and back; depending on which axis were commented out. If none of the axis were commented-out (like the original solution) the camera would gyro around on all axis. Here's my code for attempt #3:
private void Start()
{
_upVec = Vector3.zero;
Input.gyro.enabled = true;
startEulerAngles = transform.eulerAngles;
}
private void Update()
{
Vector3 gyroEuler = Input.gyro.attitude.eulerAngles;
phoneDummy.transform.eulerAngles = new Vector3(-1.0f * gyroEuler.x, -1.0f * gyroEuler.y, gyroEuler.z);
_upVec = phoneDummy.transform.InverseTransformDirection(-1f * Vector3.forward);
_upVec.z = 0;
// _upVec.x = 0;
_upVec.y = 0;
transform.LookAt(_upVec);
// transform.eulerAngles = _upVec;
}
Originally I thought it was my skills, but after spending a month on this I'm beginning to think that this is impossible to do. But that just can't be. I know it's a lot to absorb, but it's such a simple concept.
Any ideas?
EDIT: Thought I'd add my hierarchy:
CameraRotator (parent with script) -> MainCamera (child)
CompassRotator (parent) -> Compass (child with script which rotates parent)
I'd do this in the following way:
Camara with default 0, 0, 0 rotation
Screenshot
Object placed at the center of the default position of the camera.
Script for the Camera:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
Camera m_MainCamera;
// Start is called before the first frame update
void Start()
{
// Disable the sleep timeout during gameplay.
// You can re-enable the timeout when menu screens are displayed as necessary.
Screen.sleepTimeout = SleepTimeout.NeverSleep;
// Enable the gyroscope.
if (SystemInfo.supportsGyroscope)
{
Input.gyro.enabled = true;
}
m_MainCamera = Camera.main;
m_MainCamera.enabled = true;
}
// Update is called once per frame
void Update()
{
if (m_MainCamera.enabled)
{
// First - Grab the Gyro's orientation.
Quaternion tAttitude = Input.gyro.attitude;
// The Device uses a 'left-hand' orientation, we need to transform it to 'right-hand'
Quaternion tGyro = new Quaternion(tAttitude.x, tAttitude.y, -tAttitude.z, -tAttitude.w);
// the gyro attitude is tilted towards the floor and upside-down reletive to what we want in unity.
// First Rotate the orientation up 90deg on the X Axis, then 180Deg on the Z to flip it right-side up.
Quaternion tRotation = Quaternion.Euler(-90f, 0, 0) * tGyro;
tRotation = Quaternion.Euler(0, 0, 180f) * tRotation;
// You can now apply this rotation to any unity camera!
m_MainCamera.transform.localRotation = tRotation;
}
}
}
With this script my Object always face SOUTH no matter what.
If you want the object to face NORTH you just have to turn the view 180º on the Y axis as a last rotation:
Quaternion tRotation = Quaternion.Euler(-90f, 0, 0) * tGyro;
tRotation = Quaternion.Euler(0, 0, 180f) * tRotation;
//Face NORTH:
tRotation = Quaternion.Euler(0,180f, 0) * tRotation;
Hope this might help ;)

Show object in front of the player always

I have stuck in this simple problem but unable to understand that why i am unable to control it.
I have these line of code which is displaying my canvas object in front of my player(camRotationToWatch object name in code) at certain rotation of the player.
if (camRotationToWatch.transform.localEulerAngles.x >= navigationCanvasXMinmumLimit && camRotationToWatch.transform.localEulerAngles.x <= navigationCanvasXMaximumLimit)
{
if (!navCanvasHasDisplay)
{
navigationCanvas.SetActive(true);
//Debug.Log(camRotationToWatch.transform.forward);
Vector3 navCanvas = camRotationToWatch.transform.position + camRotationToWatch.transform.forward * navCanvasDisplayDistanceFromCam;
navCanvas = new Vector3(navCanvas.x, 2f, navCanvas.z);
navigationCanvas.transform.position = new Vector3(navCanvas.x, navCanvas.y, navCanvas.z);
navigationCanvas.transform.rotation = camRotationToWatch.transform.rotation;
navCanvasHasDisplay = true;
}
}
else
{
//navigationCanvas.SetActive(false);
if (locationPanel.activeSelf == false && infoPanel.activeSelf == false) {
navigationCanvas.SetActive(false);
navCanvasHasDisplay = false;
}
}
This code is actually work fine when camRotationToWatch object rotate from down to up and Canvas show at correct position but as I try to to rotate camRotationToWatch from up to down it display(active) Canvas at very top position. How can I restrict canvas to show at same position (No matter player rotate from up to down or down to up) but display on front of the player object?
Kinda hard trying to figure out what exactly you want to do. But this did what I think you where trying to do
public GameObject follow; // The object you want to rotate around
public float distance = 2; // Distance to keep from object
private void Update() {
Vector3 forward = follow.transform.forward;
forward.y = 0; // This will result in Vector3.Zero if looking straight up or down. Carefull
transform.position = follow.transform.position + forward * distance;
transform.rotation = Quaternion.LookRotation(forward, Vector3.up);
}
I believe your "unexpected behavior" is due to the use of euler angles since they are not always entirely predictable. Try using Quaternions or Vector3.Angle() when possible.
If you want to limit the angle (say... if looking down or up more than 45° disable the object) you could do the following:
if (Vector3.Angle(forward, follow.transform.forward) > maxAngle) { ... }
This probably isn't a complete answer but something that might help. This line:
Vector3 navCanvas = camRotationToWatch.transform.position + camRotationToWatch.transform.forward * navCanvasDisplayDistanceFromCam;
You are creating a position at a fixed distance from camRotationToWatch. But if that object is looking up or down, that position is not horizontally at navCanvasDisplayDistanceFromCam. If it's looking straight up, then this position is in fact directly above.
So when you do this to set a fixed vertical height:
navCanvas = new Vector3(navCanvas.x, 2f, navCanvas.z);
you aren't getting the distance from camRotationToWatch that you think you are.
Instead of using camRotationToWatch.transform.forward, create a vector from it and zero out the Y component, and normalize before using it to offset the position. (You will need to watch out for zero length vectors with that though).
Whether that fixes your problem or not, it's too hard to guess but it should help improve your results some.
EDIT: Here is an example of how you can avoid the issue with the canvas being too close:
Vector3 camForward = camRotationToWatch.transform.forward;
camForward.y = 0;
if (camForward.magnitude == 0)
{
//TODO: you'll need to decide how to deal with a straight up or straight down vector
}
camForward.Normalize();
//Note: now you have a vector lying on the horizontal plane, pointing in
//the direction of camRotationToWatch
Vector3 navCanvas = camRotationToWatch.transform.position + camForward *
navCanvasDisplayDistanceFromCam;
//Note: if you want the canvas to be at the player's height (or some offset from),
//use the player's y
navCanvas = new Vector3(navCanvas.x, Player.transform.y, navCanvas.z);
navigationCanvas.transform.position = navCanvas;
Again, this might not fix all your issues but will help to ensure your canvas lies at a set distance horizontally from the Player and will also compensate for the player's up and down motion.

GetAxis("Vertical")

I'm trying to use GetAxis to get the value from the vertical axis of the player in my game. My goal here is for my code to see if the player is under .6 y, aka anything under .6 for his position to be changed back to the spawn point.
This is my code right here, Spawn is referred to a gameobject in Unity.
if (Input.GetAxis ("Vertical") < 0.6) {
transform.position = Spawn[0].position;
}
Not sure what you exactly mean by axis, but if you mean position is game you can use:
if (transform.position.y < 0.6f) {
transform.position = Spawn[0].position;
}

Categories

Resources