Rotate unity gameobject smoth in the other direction - unity3d

i want to rotate (actually just to the left and right side) an object by swiping over the screen. I have working code already but when i swipe from the left to the right of my screen, the whole movement is kind of lagging.
The object has the following script.
Any help is appreciated... this is driving me crazy.
Thank you for your time!
[ICODE]void Update()
{
if (Input.touchCount == 0)
{
oldTouchPositions[0] = null;
oldTouchPositions[1] = null;
}
else if (Input.touchCount == 1)
{
if (oldTouchPositions[0] == null || oldTouchPositions[1] != null)
{
oldTouchPositions[0] = Input.GetTouch(0).position;
oldTouchPositions[1] = null;
}
else
{
Debug.Log("Dragging Detected");
Vector2 newTouchPosition = Input.GetTouch(0).position;
float dis = (Vector2.Distance((Vector2)oldTouchPositions[0], newTouchPosition)) / 4;
if (((Vector2)oldTouchPositions[0])[0] < newTouchPosition[0])
{
//Debug.Log("Left"); dunno if correct
vertical = (vertical - velcoidadeDeGiro * dis) % 360;
transform.localRotation = Quaternion.AngleAxis(vertical, Vector3.up);
oldTouchPositions[0] = newTouchPosition;
}
else
{
//Debug.Log("Right");
vertical = (vertical - velcoidadeDeGiro * dis) % 360;
transform.localRotation = Quaternion.AngleAxis(vertical, Vector3.down);
oldTouchPositions[0] = newTouchPosition;
}
}
}[/ICODE]

Related

Unity 2d C# character flipping but weapon doesn't

It was made so that when my character look to a side its model would flip from right to left. The problem is that the weapon that he carries doesn't and it just upside down.
For reference in visuals use the game Nuclear Throne.
The code for my character is this:
void Update
{
if (mousePos.x < transform.position.x && FacingRight)
{
Flip();
}
else if (mousePos.x > transform.position.x && !FacingRight)
{
Flip();
}
}
void Flip()
{
FacingRight = !FacingRight;
transform.Rotate(0f, 180f, 0f);
}
and for the weapon, which I put in the Aim empty game object
void Update()
{
Vector2 direction = (PointerPosition - (Vector2)transform.position).normalized;
transform.right = direction;
Vector2 scale = transform.localScale;
if(direction.x < 0)
{
scale.y = -1;
}
else if (direction.x > 0)
{
scale.y = 1;
}
transform.localScale = scale;
}
For when my weapon looks left my y scale to be -1 and to cause the weapon to flip.

How to prevent camera from going through specific layers

I have a camera controller that can move, zoom and rotate the camera. It's pretty much the exact camera controller from Cities Skyline. i.e top-down with some freedom of movement.
I am using CheckSphere to detect when the camera collides with wall/ground layers, and this works perfectly. However my issue is I do not know how to reset it's position to the last valid one, and to keep it there until the camera chooses a valid direction. At the moment as soon as my CheckSphere hits a wall, the camera is stuck and no longer responds to input.
I tried to store the last valid position, rotation and zoom and simply force this when CheckSphere hits something, but it's not working.
Is there some way I can can use this method with CheckSphere in a way that the camera won't get stuck every time it hits something it's not allowed to hit?
void HandleInput()
{
if (Physics.CheckSphere(cameraTransform.position, 7, collideWith))
{
newPosition = oldPosition;
newRotation = oldRotation;
newZoom = oldZoom;
Debug.Log("Did Hit");
}
else
{
//Speed controls
if (Input.GetKey(KeyCode.LeftShift))
{
movementSpeed = fastSpeed;
}
else
{
movementSpeed = normalSpeed;
}
// Adjust movement speed based on camera zoom
movementSpeed *= (cameraTransform.localPosition.y / zoomSpeedFactor);
Vector3 adjustedForward = transform.forward;
adjustedForward.y = 0;
//Movement controls
if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow))
{
newPosition += (adjustedForward * movementSpeed);
}
if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow))
{
newPosition += (adjustedForward * -movementSpeed);
}
if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
{
newPosition += (transform.right * movementSpeed);
}
if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
{
newPosition += (transform.right * -movementSpeed);
}
//Rotation controls
if (Input.GetMouseButtonDown(2))
{
rotateStartPosition = Input.mousePosition;
}
if (Input.GetMouseButton(2))
{
rotateCurrentPosition = Input.mousePosition;
Vector3 difference = rotateStartPosition - rotateCurrentPosition;
rotateStartPosition = rotateCurrentPosition;
newRotation *= Quaternion.Euler(Vector3.up * (-difference.x / 5f));
newRotation *= Quaternion.Euler(Vector3.right * (difference.y / 5f));
Vector3 euler = newRotation.eulerAngles;
euler.x = ClampAngle(euler.x, verticalRotationClamp.x, verticalRotationClamp.y);
euler.z = 0;
newRotation.eulerAngles = euler;
}
//Zoom controls
if (Input.mouseScrollDelta.y != 0 && !EventSystem.current.IsPointerOverGameObject())
{
newZoom -= Input.mouseScrollDelta.y * zoomAmount;
newZoom.y = ClampValue(newZoom.y, zoomClamp.x, zoomClamp.y);
newZoom.z = ClampValue(newZoom.z, -zoomClamp.y, -zoomClamp.x);
}
oldPosition = new Vector3(newPosition.x, newPosition.y, newPosition.z);
oldRotation = new Quaternion(newRotation.x, newRotation.y, newRotation.z, newRotation.w);
oldZoom = new Vector3(newZoom.x, newZoom.y, newZoom.z);
Debug.Log("Did not Hit");
}
transform.position = Vector3.Lerp(transform.position, newPosition, Time.unscaledDeltaTime * acceleration);
transform.rotation = Quaternion.Lerp(transform.rotation, newRotation, Time.unscaledDeltaTime * acceleration);
cameraTransform.localPosition = Vector3.Lerp(cameraTransform.localPosition, newZoom, Time.unscaledDeltaTime * acceleration);
}

Unity camera trembling on collision

The script works perfectly, exactly as it should, except when zooming too much and the SphereCast collides with the mesh. When it hits a mesh, I want the camera to just stop, and not try to go through the mesh.
if(Input.touchCount == 2)
{
Touch first = Input.GetTouch(0);
Touch second = Input.GetTouch(1);
origin = mainCamera.transform.position;
direction = mainCamera.transform.forward;
RaycastHit hit;
if(Physics.SphereCast(origin, sphereRadius, direction, out hit, maxDistance))
{
inCollision = true;
}
else
{
inCollision = false;
}
if(first.phase == TouchPhase.Began || second.phase == TouchPhase.Began)
{
initialDistance = Vector3.Distance(first.position, second.position);
}
if(first.phase == TouchPhase.Moved || second.phase == TouchPhase.Moved)
{
movedDistance = Vector3.Distance(first.position, second.position) - initialDistance;
if(inCollision)
{
movedDistance = -Mathf.Abs(movedDistance);
}
mainCamera.transform.localPosition = new Vector3(0, 0, mainCamera.transform.localPosition.z + movedDistance * zoomSensitivity * Time.deltaTime);
initialDistance = Vector3.Distance(first.position, second.position);
}
}
I tried to:
Set movedDistance to 0 when SphereCast hits the mesh;
Clamp mainCamera.transform.localPosition.z to mainCamera.transform.localPosition.z, but only when SphereCast hits the mesh, so the z doesn't zoom more than it's current value.
As commented before you all the time move forward, collide, move backwards, don't collide anymore, move forward etc.
You could probably rather not move backwards but check if you would collide if you would move and do not move at all in this case:
if(first.phase == TouchPhase.Began || second.phase == TouchPhase.Began)
{
initialDistance = Vector3.Distance(first.position, second.position);
}
else if(first.phase == TouchPhase.Moved || second.phase == TouchPhase.Moved)
{
movedDistance = Vector3.Distance(first.position, second.position) - initialDistance;
// Only check until here if you WOULD collide
origin = mainCamera.transform.position;
var targetPosition = origin + mainCamera.transform.forward * movedDistance * Time.deltaTime * zoomSensitivity;
direction = mainCamera.transform.forward;
// only move if there WILL BE no collision
if(!Physics.SphereCast(targetPosition, sphereRadius, direction, out var hit, maxDistance))
{
mainCamera.position = targetPosition;
}
initialDistance = Vector3.Distance(first.position, second.position);
}
From the example for SphereCast you can see that you could even take the hit.distance into account in order to at least move the camera the closest possible.

Unity X-Axis rotation quirk

I have a script that rotates an object whilst a button is pressed. The rotation plane depends on which axis is selected in the Dropdown menu. The script works mostly fine for the Y and Z axis, but has unexpected behaviour on the X-Axis.
When holding in the left rotate button, the volume will rotate to -90 and get 'stuck'. I then hold in the right rotate button and it doesn't go further than 90 before getting stuck again. What's even weirder is that quite often after getting stuck in a particular direction and switching to the alternate direction, instead of the volume going back the other way, it continues in the direction it was going had it not gotten stuck in the first place. This causes the left and right rotation buttons to be swapped around.
Here is the code with all the main operations.
public void Update()
{
axis = axisDropdown.value;
Vector3 originalRot = transform.eulerAngles;
if (buttonHeld)
{
if (rotateRight)
{
if (axis == 0)
{
originalRot.x += 1;
transform.rotation = Quaternion.Euler(originalRot);
}
else if (axis == 1)
{
originalRot.y += 1;
transform.rotation = Quaternion.Euler(originalRot);
}
else if (axis == 2)
{
originalRot.z += 1;
transform.rotation = Quaternion.Euler(originalRot);
}
else
{
print("Error: Selected axis option is invalid");
}
}
else
{
if (axis == 0)
{
originalRot.x -= 1;
transform.rotation = Quaternion.Euler(originalRot);
}
else if (axis == 1)
{
originalRot.y -= 1;
transform.rotation = Quaternion.Euler(originalRot);
}
else if (axis == 2)
{
originalRot.z -= 1;
transform.rotation = Quaternion.Euler(originalRot);
}
else
{
print("Error: Selected axis option is invalid");
}
}
}
}
I have read of other similar problems to mine, but they all seem to be slightly different so any help would be appreciated.
This is indeed caused by the gimbal lock effect. It occurred because I was trying to alter the Euler angles of my object rather than just rotating around the quaternions.
Here is the working code to avoid the issue:
public void Update()
{
axis = axisDropdown.value;
Vector3 originalRot = transform.eulerAngles;
if (buttonHeld)
{
if (rotateRight)
{
if (axis == 0)
{
transform.RotateAround(volume.transform.position, Vector3.right, 50 * Time.deltaTime);
}
else if (axis == 1)
{
transform.RotateAround(volume.transform.position, Vector3.up, 50 * Time.deltaTime);
}
else if (axis == 2)
{
transform.RotateAround(volume.transform.position, Vector3.forward, 50 * Time.deltaTime);
}
else
{
print("Error: Selected axis option is invalid");
}
}
else
{
if (axis == 0)
{
transform.RotateAround(volume.transform.position, Vector3.left, 50 * Time.deltaTime);
}
else if (axis == 1)
{
transform.RotateAround(volume.transform.position, Vector3.down, 50 * Time.deltaTime);
}
else if (axis == 2)
{
transform.RotateAround(volume.transform.position, Vector3.back, 50 * Time.deltaTime);
}
else
{
print("Error: Selected axis option is invalid");
}
}
}
}

How to check rotation of an object in Unity3d?

I'm a unity3d learner. I have a problem with rotation of an object. I want to rotate objects about 40 degrees along the z axis. If the objects rotation has reached 40 degrees, I want something to happen. Here is my code.
foreach(Touch touch in Input.touches) {
if(touch.phase != TouchPhase.Ended && touch.phase != TouchPhase.Canceled) {
var target = Quaternion.Euler (0, 0,-40);
transform.rotation = Quaternion.Slerp(transform.rotation, target, Time.deltaTime * smooth);
if (transform.rotation.eulerAngles.z == -40) {
toggle = true;
speech = "blah blah blah";
snake = man;
}
}
}
The if(transform.rotation.eulerAngles.z == -40) line of code is not working. So I don't know if the rotation degree has reached 40 degree or not. How do I check if the rotation degree has reached 40 degrees?
I don't understand your code intent.
EulerAngles is not set negative only positive value(Vector3)
-if(eulerAngles.z == -40) is not work you try change value -40 -> 320
If you want scenario ontouch -> object rotation -> event
try this code.
float rotTime = 1f; // rotation duration
Vector3 rotValue = new Vector3(0, 0, -40f); // rotation value
void Update () {
foreach (Touch touch in Input.touches)
if (touch.phase == TouchPhase.Began) OnTouchEvent();
}
void OnTouchEvent()
{
StopCoroutine("rotationCoroutine");
StartCoroutine("rotationCoroutine");
}
IEnumerator rotationCoroutine()
{
float startTime = Time.time;
Vector3 startRot = transform.eulerAngles;
Vector3 endRot = startRot;
endRot += rotValue;
while (Time.time - startTime <= rotTime)
{
transform.eulerAngles = Vector3.Slerp(startRot, endRot,(Time.time - startTime) / rotTime);
yield return null; // wait 1 frame
}
//rotation end
MyAction();
}
void MyAction()
{
Debug.Log("rotation end");
//toggle = true;
//speech = "blah blah";
//snake = man;
}
Good Luck :D