Unity - Clamp Rotation between arbitrary angles - c#

I have a task where I have to clamp an angle between other two angle.
The catch is that the limits can be >360 or <0
(ex. [-45,45] or [275,45]).
Is there a clean way to do this taking into account all the special
cases?
(ex. range [-45,45] and input angle of 225 should be -45).
Thanks in advance!
P.S. I am using unity, so I have all the default Quaternion methods at hand.
Current Code:
Quaternion inputAngle = Quaternion.identity;
if (Character.IsFacingRight)
inputAngle = Quaternion.FromToRotation(forwardVector, playerInput);
else
inputAngle = Quaternion.FromToRotation(playerInput, forwardVector);
Quaternion minAngle = Quaternion.Euler(0F, 0F, addedForce.force.angle);
Quaternion angleRange = Quaternion.Euler(0F, 0F, addedForce.force.angleRange);
Quaternion maxAngle = angleRange * minAngle;
// var yaw = Math.Atan2(2.0 * (inputAngle.y * inputAngle.z + inputAngle.w * inputAngle.x), inputAngle.w * inputAngle.w - inputAngle.x * inputAngle.x - inputAngle.y * inputAngle.y + inputAngle.z * inputAngle.z);
// var pitch = Math.Asin(-2.0 * (inputAngle.x * inputAngle.z - inputAngle.w * inputAngle.y));
float roll = (float)Math.Atan2(2.0 * (inputAngle.x * inputAngle.y + inputAngle.w * inputAngle.z), inputAngle.w * inputAngle.w + inputAngle.x * inputAngle.x - inputAngle.y * inputAngle.y - inputAngle.z * inputAngle.z);
Quaternion correctedRotation = Quaternion.Euler(0F, 0F, roll / Mathf.PI * 180F);
float endAngleZ = ClampRotation2(correctedRotation.eulerAngles.z, minAngle.eulerAngles.z, maxAngle.eulerAngles.z);
Quaternion endAngle = Quaternion.Euler(0F, 0F, endAngleZ);
ClampRotation2:
public static float ClampRotation2(float angle, float min, float max)
{
if (angle < 0) angle += 360;
if (max < 0) max += 360;
if (min < 0) min += 360;
if (min > max) min -= 360;
return Mathf.Clamp(angle, min, max);
}

OK, so I found the solution which clamps the angle correctly in all cases,
Brought to you by Quaternion.Angle() I present :
Quaternion inputAngle = Quaternion.identity;
if (Character.IsFacingRight)
inputAngle = Quaternion.FromToRotation(forwardVector, playerInput);
else
inputAngle = Quaternion.FromToRotation(playerInput, forwardVector);
Quaternion minAngle = Quaternion.Euler(0F, 0F, addedForce.force.angle);
Quaternion angleRange = Quaternion.Euler(0F, 0F, addedForce.force.angleRange);
Quaternion maxAngle = angleRange * minAngle;
float roll = (float)Math.Atan2(2.0 * (inputAngle.x * inputAngle.y + inputAngle.w * inputAngle.z), inputAngle.w * inputAngle.w + inputAngle.x * inputAngle.x - inputAngle.y * inputAngle.y - inputAngle.z * inputAngle.z);
float correctedRotation = roll / Mathf.PI * 180F;
float minAngleF = minAngle.eulerAngles.z;
float maxAngleF = maxAngle.eulerAngles.z;
if (correctedRotation < 0) correctedRotation += 360;
if (maxAngleF < 0) maxAngleF += 360;
if (minAngleF < 0) minAngleF += 360;
if (minAngleF > maxAngleF) minAngleF -= 360;
if (correctedRotation < minAngleF || correctedRotation > maxAngleF)
{
float rotationToMax = Quaternion.Angle(Quaternion.Euler(0F, 0F, correctedRotation), Quaternion.Euler(0F, 0F, maxAngleF));
float rotationToMin = Quaternion.Angle(Quaternion.Euler(0F, 0F, correctedRotation), Quaternion.Euler(0F, 0F, minAngleF));
if (Mathf.Abs(rotationToMax) < Mathf.Abs(rotationToMin))
correctedRotation = maxAngleF;
else
correctedRotation = minAngleF;
}
Quaternion endAngle = Quaternion.Euler(0F, 0F, correctedRotation);

Related

Converting Calculating To Movement Overtime?

I am moving an object in a parabolic arc this way:
public IEnumerator ParabolicMovement()
{
Vector3 startPos;
Vector3 targetPos;
float speed = 6;
float arcHeight = 3;
Vector3 nextPos = Vector3.zero;
while (transform.position != targetPos)
{
// Compute the next position, with arc added in
float x0 = startPos.x;
float x1 = targetPos.x;
float dist = x1 - x0;
float nextX = Mathf.MoveTowards(transform.position.x, x1, (speed) * Time.deltaTime);
float baseY = Mathf.Lerp(startPos.y, targetPos.y, (nextX - x0) / dist);
float arc = arcHeight * (nextX - x0) * (nextX - x1) / (-0.25f * dist * dist);
nextPos = new Vector3(nextX, baseY + arc, transform.position.z);
transform.position = nextPos;
yield return null;
}
}
This works, but I now want to take this and make it happen over a specific amount of time. I removed the loop from the original method and broke it up into two separate methods to accomplish this:
public IEnumerator BeginJumpOverTime()
{
float duration = 1f;
float startTime = Time.time;
float endTime = startTime + duration;
while (Time.time <= endTime)
{
float tNormalized = Mathf.Clamp((Time.time - startTime) / duration, 0f, 1f);
Vector2 newXAndY = CalculateXAndY(tNormalized);
transform.position = newXAndY;
yield return null;
}
}
public Vector2 CalculateXAndY(float t)
{
Vector3 startPos = GameEngine.Instance.battleManager.TurnHero.transform.position;
Vector3 targetPos = GameEngine.Instance.battleManager.TargetEnemy.transform.position;
float speed = 6;
float arcHeight = 3;
Vector3 nextPos = Vector3.zero;
// Compute the next position to make the parabola
float x0 = startPos.x;
float x1 = targetPos.x;
float dist = x1 - x0;
float nextX = Mathf.MoveTowards(transform.position.x, x1, (speed) * (Time.deltaTime) );
float baseY = Mathf.Lerp(startPos.y, targetPos.y, (nextX - x0) / dist);
float arc = arcHeight * (nextX - x0) * (nextX - x1) / (-0.25f * dist * dist);
nextPos = new Vector3(nextX, baseY + arc, transform.position.z);
return (nextPos);
}
I'm pretty certain this concept should work, I just can't seem to figure out where to factor tNormalized when it's passed into CalculateXandY(). Is anyone math savvy able to assist me with this? Thanks a ton!
Kind regards,

How does Quaternion.eulerAngles work in Unity? [duplicate]

I've used two examples (from this site too), but results are not the same as those that said Unity.
Quaternion.Euler and .eulerAngles are Unity functions. FromQ doesn't perform singularity check, FromQ2 does.
Results:
eulers = (100,55,-11):
Quaternion.Euler(eulers) == (0.6, 0.4, -0.4, 0.5)
ToQ(eulers)); == (0.5, -0.4, 0.2, 0.7) // 0.5, -0.4 right but in wrong order
FromQ(ToQ(eulers)) == (55.0, 100.0, -11.0)
FromQ2(ToQ(eulers)) == (-55.5, -6.3, 71.0) // something right
Quaternion.Euler(eulers).eulerAngles == (80.0, 235.0, 169.0)
FromQ2(Quaternion.Euler(eulers)) == (65.8, 1.9, 99.8)
ToQ(eulers).eulerAngles == (70.0, 286.9, 341.4)
FromQ(Quaternion.Euler(eulers)) == (-65.8, 76.0, 4.6)
It must be:
FromQ() = FromQ2() = .eulerAngles,
ToQ() = Quaternion.Euler()
The code is here: http://pastebin.ru/eAlTHdYf
Can anyone correct this code? I need code that will return the values ​​that are identical to the values that Unity functions returns.
UPDATE
Here is fixed code: http://pastebin.com/riRLRvch.
Both functions (FromQ and ToQ) work well. But I have a problem with a singularity. It can't detect the singularity properly.
For example (90, 0, 50) in quaternion is (0.6, -0.3, 0.3, 0.6).
test = x * y + z * w = 0 (must be close to 0.5 or -0.5)
FromQ can't calculate correct result so we have the singularity here. The same for (90, 50, 0) - (0.6, 0.3, -0.3, 0.6).
I see only one solution - calculate "test" as xw-yz. But I'm not sure this is right.
How to fix it?
I've found solution
public static Quaternion ToQ (Vector3 v)
{
return ToQ (v.y, v.x, v.z);
}
public static Quaternion ToQ (float yaw, float pitch, float roll)
{
yaw *= Mathf.Deg2Rad;
pitch *= Mathf.Deg2Rad;
roll *= Mathf.Deg2Rad;
float rollOver2 = roll * 0.5f;
float sinRollOver2 = (float)Math.Sin ((double)rollOver2);
float cosRollOver2 = (float)Math.Cos ((double)rollOver2);
float pitchOver2 = pitch * 0.5f;
float sinPitchOver2 = (float)Math.Sin ((double)pitchOver2);
float cosPitchOver2 = (float)Math.Cos ((double)pitchOver2);
float yawOver2 = yaw * 0.5f;
float sinYawOver2 = (float)Math.Sin ((double)yawOver2);
float cosYawOver2 = (float)Math.Cos ((double)yawOver2);
Quaternion result;
result.w = cosYawOver2 * cosPitchOver2 * cosRollOver2 + sinYawOver2 * sinPitchOver2 * sinRollOver2;
result.x = cosYawOver2 * sinPitchOver2 * cosRollOver2 + sinYawOver2 * cosPitchOver2 * sinRollOver2;
result.y = sinYawOver2 * cosPitchOver2 * cosRollOver2 - cosYawOver2 * sinPitchOver2 * sinRollOver2;
result.z = cosYawOver2 * cosPitchOver2 * sinRollOver2 - sinYawOver2 * sinPitchOver2 * cosRollOver2;
return result;
}
public static Vector3 FromQ2 (Quaternion q1)
{
float sqw = q1.w * q1.w;
float sqx = q1.x * q1.x;
float sqy = q1.y * q1.y;
float sqz = q1.z * q1.z;
float unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
float test = q1.x * q1.w - q1.y * q1.z;
Vector3 v;
if (test>0.4995f*unit) { // singularity at north pole
v.y = 2f * Mathf.Atan2 (q1.y, q1.x);
v.x = Mathf.PI / 2;
v.z = 0;
return NormalizeAngles (v * Mathf.Rad2Deg);
}
if (test<-0.4995f*unit) { // singularity at south pole
v.y = -2f * Mathf.Atan2 (q1.y, q1.x);
v.x = -Mathf.PI / 2;
v.z = 0;
return NormalizeAngles (v * Mathf.Rad2Deg);
}
Quaternion q = new Quaternion (q1.w, q1.z, q1.x, q1.y);
v.y = (float)Math.Atan2 (2f * q.x * q.w + 2f * q.y * q.z, 1 - 2f * (q.z * q.z + q.w * q.w)); // Yaw
v.x = (float)Math.Asin (2f * (q.x * q.z - q.w * q.y)); // Pitch
v.z = (float)Math.Atan2 (2f * q.x * q.y + 2f * q.z * q.w, 1 - 2f * (q.y * q.y + q.z * q.z)); // Roll
return NormalizeAngles (v * Mathf.Rad2Deg);
}
static Vector3 NormalizeAngles (Vector3 angles)
{
angles.x = NormalizeAngle (angles.x);
angles.y = NormalizeAngle (angles.y);
angles.z = NormalizeAngle (angles.z);
return angles;
}
static float NormalizeAngle (float angle)
{
while (angle>360)
angle -= 360;
while (angle<0)
angle += 360;
return angle;
}
This question is almost three years old, but I needed the same code and the ones posted here seemed to be incorrect, so I tweaked them and found this:
public static Quaternion Euler(float yaw, float pitch, float roll) {
yaw*=Mathf.Deg2Rad;
pitch*=Mathf.Deg2Rad;
roll*=Mathf.Deg2Rad;
double yawOver2 = yaw * 0.5f;
float cosYawOver2 = (float)System.Math.Cos(yawOver2);
float sinYawOver2 = (float)System.Math.Sin(yawOver2);
double pitchOver2 = pitch * 0.5f;
float cosPitchOver2 = (float)System.Math.Cos(pitchOver2);
float sinPitchOver2 = (float)System.Math.Sin(pitchOver2);
double rollOver2 = roll * 0.5f;
float cosRollOver2 = (float)System.Math.Cos(rollOver2);
float sinRollOver2 = (float)System.Math.Sin(rollOver2);
Quaternion result;
result.w = cosYawOver2 * cosPitchOver2 * cosRollOver2 + sinYawOver2 * sinPitchOver2 * sinRollOver2;
result.x = sinYawOver2 * cosPitchOver2 * cosRollOver2 + cosYawOver2 * sinPitchOver2 * sinRollOver2;
result.y = cosYawOver2 * sinPitchOver2 * cosRollOver2 - sinYawOver2 * cosPitchOver2 * sinRollOver2;
result.z = cosYawOver2 * cosPitchOver2 * sinRollOver2 - sinYawOver2 * sinPitchOver2 * cosRollOver2;
return result;
}
According to a few quick tests, this matches Quaternion.Euler 100%
This might only be worth a partial answer but here is "ToQ() = Quaternion.Euler()":
public static Quaternion ToQ(Vector3 v)
{
return ToQ(v.y,v.x,v.z);
}
public static Quaternion ToQ(float yaw, float pitch, float roll)
{
yaw*=Mathf.Deg2Rad;
pitch*=Mathf.Deg2Rad;
roll*=Mathf.Deg2Rad;
float rollOver2 = roll * 0.5f;
float sinRollOver2 = (float)Math.Sin((double)rollOver2);
float cosRollOver2 = (float)Math.Cos((double)rollOver2);
float pitchOver2 = pitch * 0.5f;
float sinPitchOver2 = (float)Math.Sin((double)pitchOver2);
float cosPitchOver2 = (float)Math.Cos((double)pitchOver2);
float yawOver2 = yaw * 0.5f;
float sinYawOver2 = (float)Math.Sin((double)yawOver2);
float cosYawOver2 = (float)Math.Cos((double)yawOver2);
Quaternion result;
result.w = cosYawOver2 * cosPitchOver2 * cosRollOver2 + sinYawOver2 * sinPitchOver2 * sinRollOver2;
result.x = cosYawOver2 * sinPitchOver2 * cosRollOver2 + sinYawOver2 * cosPitchOver2 * sinRollOver2;
result.y = sinYawOver2 * cosPitchOver2 * cosRollOver2 - cosYawOver2 * sinPitchOver2 * sinRollOver2;
result.z = cosYawOver2 * cosPitchOver2 * sinRollOver2 - sinYawOver2 * sinPitchOver2 * cosRollOver2;
return result;
}
The 'FromQ' part of your question is a different matter. Euler angle comparison is a pain in the behind.
Here's my solution. This is very very close to Unity's Quaternion.Euler and quaternion.eulerAngles. The discrepancies are small enough that they shouldn't matter for any application.
public static Vector3 QuaternionToEuler(Quaternion q)
{
Vector3 euler;
// if the input quaternion is normalized, this is exactly one. Otherwise, this acts as a correction factor for the quaternion's not-normalizedness
float unit = (q.x * q.x) + (q.y * q.y) + (q.z * q.z) + (q.w * q.w);
// this will have a magnitude of 0.5 or greater if and only if this is a singularity case
float test = q.x * q.w - q.y * q.z;
if (test > 0.4995f * unit) // singularity at north pole
{
euler.x = Mathf.PI / 2;
euler.y = 2f * Mathf.Atan2(q.y, q.x);
euler.z = 0;
}
else if (test < -0.4995f * unit) // singularity at south pole
{
euler.x = -Mathf.PI / 2;
euler.y = -2f * Mathf.Atan2(q.y, q.x);
euler.z = 0;
}
else // no singularity - this is the majority of cases
{
euler.x = Mathf.Asin(2f * (q.w * q.x - q.y * q.z));
euler.y = Mathf.Atan2(2f * q.w * q.y + 2f * q.z * q.x, 1 - 2f * (q.x * q.x + q.y * q.y));
euler.z = Mathf.Atan2(2f * q.w * q.z + 2f * q.x * q.y, 1 - 2f * (q.z * q.z + q.x * q.x));
}
// all the math so far has been done in radians. Before returning, we convert to degrees...
euler *= Mathf.Rad2Deg;
//...and then ensure the degree values are between 0 and 360
euler.x %= 360;
euler.y %= 360;
euler.z %= 360;
return euler;
}
public static Quaternion EulerToQuaternion(Vector3 euler)
{
float xOver2 = euler.x * Mathf.Deg2Rad * 0.5f;
float yOver2 = euler.y * Mathf.Deg2Rad * 0.5f;
float zOver2 = euler.z * Mathf.Deg2Rad * 0.5f;
float sinXOver2 = Mathf.Sin(xOver2);
float cosXOver2 = Mathf.Cos(xOver2);
float sinYOver2 = Mathf.Sin(yOver2);
float cosYOver2 = Mathf.Cos(yOver2);
float sinZOver2 = Mathf.Sin(zOver2);
float cosZOver2 = Mathf.Cos(zOver2);
Quaternion result;
result.x = cosYOver2 * sinXOver2 * cosZOver2 + sinYOver2 * cosXOver2 * sinZOver2;
result.y = sinYOver2 * cosXOver2 * cosZOver2 - cosYOver2 * sinXOver2 * sinZOver2;
result.z = cosYOver2 * cosXOver2 * sinZOver2 - sinYOver2 * sinXOver2 * cosZOver2;
result.w = cosYOver2 * cosXOver2 * cosZOver2 + sinYOver2 * sinXOver2 * sinZOver2;
return result;
}

C# CS0165 on the result of Quaternion

i want to convert my Quaternions in to euler angles but in this function I get an error on result.W. The error is CS0165.
public static Quaternion Euler(string[]text)
{
double yaw = Convert.ToDouble(text[1]);
double pitch = Convert.ToDouble(text[2]);
double roll = Convert.ToDouble(text[3]);
yaw = (Math.PI / 180) * yaw;
pitch = (Math.PI / 180) * pitch;
roll = (Math.PI / 180) * roll;
double yawOver2 = yaw * 0.5f;
float cosYawOver2 = (float)System.Math.Cos(yawOver2);
float sinYawOver2 = (float)System.Math.Sin(yawOver2);
double pitchOver2 = pitch * 0.5f;
float cosPitchOver2 = (float)System.Math.Cos(pitchOver2);
float sinPitchOver2 = (float)System.Math.Sin(pitchOver2);
double rollOver2 = roll * 0.5f;
float cosRollOver2 = (float)System.Math.Cos(rollOver2);
float sinRollOver2 = (float)System.Math.Sin(rollOver2);
Quaternion result;
result.W = cosYawOver2 * cosPitchOver2 * cosRollOver2 + sinYawOver2 * sinPitchOver2 * sinRollOver2;
result.X = sinYawOver2 * cosPitchOver2 * cosRollOver2 + cosYawOver2 * sinPitchOver2 * sinRollOver2;
result.Y = cosYawOver2 * sinPitchOver2 * cosRollOver2 - sinYawOver2 * cosPitchOver2 * sinRollOver2;
result.Z = cosYawOver2 * cosPitchOver2 * sinRollOver2 - sinYawOver2 * sinPitchOver2 * cosRollOver2;
return result;
}
What could be the problem?
Use of unassigned local variable 'name': https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/cs0165
You cannot access W because most probably in your Quaternion definition you use properties or some other code that requires explicit object creation.

Rotate arrow without using Unity3d physics engine

I have this code that simulates the movement of a projectile without using the unity physics engine
IEnumerator LaunchProjectile(int angle, float speed)
{
// Move projectile to the position of throwing object + add some offset if needed.
Projectile.position = transform.position + new Vector3(0, 0f, 0);
Projectile.rotation = transform.root.rotation;
Debug.Log(transform.root.eulerAngles);
// Calculate distance to target
float target_Distance = speed * (Mathf.Sin(2 * firingAngle * Mathf.Deg2Rad) / gravity);
// Extract the X Y componenent of the velocity
float Vx = Mathf.Sqrt(speed) * Mathf.Cos(firingAngle * Mathf.Deg2Rad);
float Vy = Mathf.Sqrt(speed) * Mathf.Sin(firingAngle * Mathf.Deg2Rad);
// Calculate flight time.
float flightDuration = target_Distance / Vx;
this.arrowSimulationScript = Projectile.gameObject.GetComponentInChildren<ArrowSimulation>();
float elapse_time = 0;
while (!arrowSimulationScript.Collided())
{
Projectile.Translate(0, (Vy - (gravity * elapse_time)) * Time.deltaTime, Vx * Time.deltaTime);
Projectile.LookAt(Projectile.position - new Vector3(0, (Vy - (gravity * elapse_time)) * Time.deltaTime, Vx * Time.deltaTime));
arrowSimulationScript.Velocity = new Vector3(0, (Vy - (gravity * elapse_time)) * Time.deltaTime, Vx * Time.deltaTime).magnitude;
elapse_time += Time.deltaTime;
yield return null;
}
}
The arrow is fired in the direction of the object which has this script attached. To make the arrow rotate I use this line of code:
Projectile.LookAt(Projectile.position - new Vector3(0, (Vy - (gravity * elapse_time)) * Time.deltaTime, Vx * Time.deltaTime));
The arrow moves towards the right direction but with the tip facing the z axis direction, instead of the direction of the bow.
Here is a video of the problem:
https://www.youtube.com/watch?v=cyK6DXxTw_E
If I comment out that line of code the arrow fly with the tip facing the direction of the bow, but it doesn't rotate.
Try this
while (!arrowSimulationScript.Collided())
{
Vector3 delta = new Vector3(0, (Vy - (gravity * elapse_time)) * Time.deltaTime, Vx * Time.deltaTime);
Vector3 newPos = Projectile.position + delta;
Vector3 offset = (newPos - Projectile.position);
Vector3 magnitude = offset.magnitude;
Vector3 newDir = offset.normalized;
Projectile.rotation = Quaternion.LookRotation(newDir, Vector3.Cross(newDir, Projectile.right)));
arrowSimulationScript.Velocity = magnitude;
elapse_time += Time.deltaTime;
Projectile.position = newPos;
yield return null;
}

How to stop Roll Rotation in Mouse Look Script

I am using FPS in Unity3D and I want only Pitch and Yaw. After some moves my Mouse Look Script start Rotating around z-axis (i.e. ROLL). How to stop that?
This is the Script that i am using for Mouse Look.
using UnityEngine;
using System.Collections;
public class MouseLooking : MonoBehaviour
{
float sensitivityX = 10f;
float sensitivityY = 10f;
public float minimumX = -360;
public float maximumX = 360;
public float minimumY = -60;
public float maximumY = 60;
public float delayMouse = 3;
public float noiseX = 0.1f;
public float noiseY = 0.1f;
public bool Noise;
private float rotationX = 0;
private float rotationY = 0;
private float rotationXtemp = 0;
private float rotationYtemp = 0;
private Quaternion originalRotation;
private float noisedeltaX;
private float noisedeltaY;
private float stunY;
private float breathHolderValtarget = 1;
private float breathHolderVal = 1;
private TouchScreenVal touch;
void Start ()
{
if (rigidbody)
rigidbody.freezeRotation = true;
originalRotation = transform.localRotation;
sensitivityX = sensitivityY = 10;
touch = new TouchScreenVal (new Rect (0, 0, Screen.width, Screen.height));
}
void Update ()
{
sensitivityY = sensitivityX;
// Screen.lockCursor = true;
stunY += (0 - stunY) / 20f;
if (Noise) {
noisedeltaX += ((((Mathf.Cos (Time.time) * Random.Range (-10, 10) / 5f) * noiseX) - noisedeltaX) / 100);
noisedeltaY += ((((Mathf.Sin (Time.time) * Random.Range (-10, 10) / 5f) * noiseY) - noisedeltaY) / 100);
} else {
noisedeltaX = 0;
noisedeltaY = 0;
}
#if UNITY_EDITOR
rotationXtemp += (Input.GetAxis ("Mouse X") * sensitivityX) + (noisedeltaX * breathHolderVal);
rotationYtemp += (Input.GetAxis ("Mouse Y") * sensitivityY) + (noisedeltaY * breathHolderVal);
rotationX += (rotationXtemp - rotationX) / delayMouse;
rotationY += (rotationYtemp - rotationY) / delayMouse;
#else
if (Constants.isGameOver == false) {
int count = Input.touchCount;
if (Input.touchCount > 0) {
for(int i =0 ; i< count ; i++)
{
Touch touch1 = Input.GetTouch (i);
if ((touch1.phase == TouchPhase.Moved ) || touch1.phase == TouchPhase.Stationary) {
rotationX = rotationXtemp + ( Input.GetTouch (i).deltaPosition.x * sensitivityX* Time.deltaTime) + (noisedeltaX * breathHolderVal);
rotationY = rotationYtemp + ( Input.GetTouch(i).deltaPosition.y * sensitivityY* Time.deltaTime) + (noisedeltaY * breathHolderVal);
// rotationX = rotationXtemp + (touch.OnDragDirection(true).x * sensitivityX * Time.deltaTime) + (noisedeltaX * breathHolderVal);
// rotationY = rotationYtemp + (-touch.OnDragDirection(true).y * sensitivityY * Time.deltaTime) + (noisedeltaY * breathHolderVal);
}
}
}
else
{
rotationX = rotationXtemp + (touch.OnDragDirection(true).x * sensitivityX * Time.deltaTime) + (noisedeltaX * breathHolderVal);
rotationY = rotationYtemp + (-touch.OnDragDirection(true).y * sensitivityY * Time.deltaTime) + (noisedeltaY * breathHolderVal);
}
}
#endif
if (rotationX >= 360) {
rotationX = 0;
rotationXtemp = 0;
}
if (rotationX <= -360) {
rotationX = 0;
rotationXtemp = 0;
}
rotationX = ClampAngle (rotationX, minimumX, maximumX);
rotationY = ClampAngle (rotationY, minimumY, maximumY);
rotationYtemp = ClampAngle (rotationYtemp, minimumY, maximumY);
Quaternion xQuaternion = Quaternion.AngleAxis (rotationX, Vector3.up);
Quaternion yQuaternion = Quaternion.AngleAxis (rotationY + stunY, Vector3.left);
transform.localRotation = originalRotation * xQuaternion * yQuaternion;
breathHolderVal += (breathHolderValtarget - breathHolderVal) / 10;
#if !UNITY_EDITOR
rotationXtemp = rotationX;
rotationYtemp = rotationY;
#endif
}
public void Holdbreath (float val)
{
breathHolderValtarget = val;
}
public void Stun (float val)
{
stunY = val;
}
static float ClampAngle (float angle, float min, float max)
{
if (angle < -360.0f)
angle += 360.0f;
if (angle > 360.0f)
angle -= 360.0f;
return Mathf.Clamp (angle, min, max);
}
}
You can't use floats to store the x and y rotation, you need to store it all in a quaternion. So when you update from the mouse input, add it directly to the quaternion.
See Quaternion rotation without Euler angles for example.

Categories