I am trying to rotate floor using Input.acceleration. I want to rotate floor around the point where player is standing and to limit my rotations at certain angles also stop at 0 if Input.acceleration is close to zero. considering that i'm newbie at game programming I've came up with this code:
using UnityEngine;
using System.Collections;
public class Tilt : MonoBehaviour {
public float maxRotationAngle = 350; // max rotation right
public float minRotationAngle = 10; // max rotation left
public float rotationSpeed = 20; //rotation speed
public Transform rotateAround; //rotation point
private bool stopRotation = false; //if this is true rotation stops
private int stopDir; //direction where rotation stops -1 equals left 0 center 1 right
void Update () {
int tiltDir = 0; //input tilt direction
float accel = Input.acceleration.x; //input tilt value
float currentRotation = transform.eulerAngles.z; //current rotation
//set rotation direction
if (accel > 0) {
tiltDir = 1;
}else if (accel < 0){
tiltDir = -1;
}
//stop rotation left
if (!stopRotation && (currentRotation < maxRotationAngle && currentRotation > 270)) {
stopRotation = true;
stopDir = -1;
}
//stop rotation right
if (!stopRotation && (currentRotation > minRotationAngle && currentRotation < 270)) {
stopRotation = true;
stopDir = 1;
}
//allow rotation right
if (stopRotation && stopDir < 0 && Input.acceleration.x > 0) {
stopRotation = false;
}
//allow rotation left
if (stopRotation && stopDir > 0 && Input.acceleration.x < 0) {
stopRotation = false;
}
//stop rotation center
if(!stopRotation && currentRotation < 0.2 || (currentRotation > 359.8 && currentRotation < 360)){
if(accel > -0.1 && accel < 0.1){
stopRotation = true;
stopDir = 0;
}
}
//allow rotation from center
if(stopRotation && stopDir == 0 && (accel < -0.1 || accel > 0.1)){
stopRotation = false;
}
//apply rotation
if(!stopRotation){
transform.RotateAround(rotateAround.position, new Vector3(0, 0, tiltDir), rotationSpeed * Mathf.Abs(accel) * Time.deltaTime);
}
}
}
This is working but this approach is not exact and i think there are cheaper ways of doing this. So Is there a better way?
I came up with this, which I think accomplishes what you wanted, although I may have misread your code. I've removed your magic number, changed the angles to map between -180 and 180 and renamed your variables to have full names for better maintainability.
public float maxRotationAngle = 170;
public float minRotationAngle = -170;
public float minimumAcceleration = 0.1f;
public float rotationSpeed = 20;
public Transform rotateAroundTransform;
void Update ()
{
float deltaAcceleration = Mathf.Abs(Input.acceleration.x);
float currentRotation = transform.eulerAngles.z;
//stop rotation outside of angle range and motion range
if (currentRotation > minRotationAngle &&
currentRotation < maxRotationAngle &&
deltaAcceleration < minimumAcceleration)
{
//set rotation direction
int tiltDirection = Input.acceleration.x > 0 ? 1 : -1;
transform.RotateAround(rotateAroundTransform.position, new Vector3(0, 0, tiltDirection), rotationSpeed * deltaAcceleration * Time.deltaTime);
}
}
Hope that helps!
Related
I'm making a game and I can't get my image to move properly on a swipe. I tried doing angle calculations and such to sense where the swipe was by getting the x and y of the final and initial positions and subtracting them but it is not working for all angles. Up Right and Down Right aren't working but all the other directions are. I don't understand why because if down and up left are working, up and down right should work as well but they aren't.
Please help. I have no idea what to do.
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Rect;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.widget.ImageView;
import java.lang.Math;
import android.view.View;
import android.widget.*;
public class gameStart extends AppCompatActivity {
int Δx = 0;
int Δy = 0;
int x = 0;
int y = 0;
int speedx = 0;
int speedy = 0;
private ImageView character;
float charX = 0;
float charY = 0;
boolean left = false;
boolean right = false;
boolean up = false;
boolean down = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game_start);
/**Gets the size of the screen.*/
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int height = displayMetrics.heightPixels; //May want to use dpi instead of pixels. Not sure yet.
int width = displayMetrics.widthPixels;
//Gets the width and height of the object as to set a constant speed for all screen sizes.
speedx = (int) (0.9*width)/100; //Change the decimal to change the percentage that the character moves in a specific direction.
speedy = (int) (0.9*height)/100;
View i = findViewById(R.id.square);
/**Gets the position of the character*/
character = (ImageView) findViewById(R.id.square);
charX = character.getX();
charY = character.getY();
}
public boolean onTouchEvent(MotionEvent event){
if(event.getAction() == MotionEvent.ACTION_DOWN) {
x = (int)event.getX();
y = (int)event.getY();
}
else if(event.getAction() == MotionEvent.ACTION_UP) {
int x2 = (int)event.getX();
int y2 = (int)event.getY();
//Get ΔX and Δy
Δx = x2 - x;
Δy = y2 - y;
swipe();
}
return true;
}
/** public boolean onDown(MotionEvent event){
//Initial location of swipe
System.out.println("Down");
if(!onDown(event)){
System.out.println("Swipe");
}
return false;
}
*/
public int swipe(){
//Determine the swipe of the user mathematically
if(Δx!=0) {
double radAngle = Math.atan(Δy / Δx);
double angle = Math.toDegrees(radAngle);
//Swipe Right Up
if (angle < 45 && Δx > 0 && Δy < 0) {
System.out.println("Swipe Right Up");
charX += speedx;
character.setX(charX);
}
//Swipe Right Down
if (angle > -45 && Δy > 0 && Δx > 0) {
System.out.println("Swipe Right Down");
charX += speedx;
character.setX(charX);
}
//Swipe Down Right
if (angle <= -45 && Δy > 0 && Δx > 0) {
System.out.println("Swipe Down Right");
charY += speedy;
character.setY(charY);
}
//Swipe Down Left
if (angle <= -45 && Δy > 0 && Δx < 0) {
System.out.println("Swipe Down Left");
charY += speedy;
character.setY(charY);
}
//Swipe Left Up
if (angle < 45 && Δx < 0 && Δy < 0) {
System.out.println("Swipe Left Up");
charX -= speedx;
character.setX(charX);
}
//Swipe Left Down
if (angle > -45 && Δx < 0 && Δy > 0) {
System.out.println("Swipe Left Down");
charX -= speedx;
character.setX(charX);
}
//Swipe Up Right
if (angle >= 45 && Δy < 0 && Δx > 0) {
System.out.println("Swipe Up Right");
charY -= speedy;
character.setY(charY);
}
//Swipe Up Left
if (angle >= 45 && Δy < 0 && Δx < 0) {
System.out.println("Swipe Up Left");
charY -= speedy;
character.setY(charY);
}
}
//Determine the swipe of the user mathematically
if(Δy!=0 && Δx==0) {
//Swipe Down
if (Δy > 0 && Δx==0) {
System.out.println("Swipe STRAIGHT down");
charY += speedy;
character.setY(charY);
}
//Swipe up
if (Δy < 0 && Δx==0) {
System.out.println("Swipe STRAIGHT Up");
charY -= speedy;
character.setY(charY);
}
}
return 0;
}
}
My code is not working, I am trying to clamp the camera, but it's not working. It's snapping to 45 instantly. How can I clamp the camera?
Here is my Code.
using UnityEngine;
using System.Collections;
public class MoveCamera : MonoBehaviour
{
public float sensitivity = 4.0f;
private Vector3 mouseOrigin;
private bool isRotating;
private float minX = -45.0f;
private float maxX = 45.0f;
private float minY = -10.0f;
private float maxY = 10.0f;
float rotationY = 0.0f;
float rotationX = 0.0f;
void Start()
{
}
void Update ()
{
if (Input.GetMouseButtonDown (0)) {
mouseOrigin = Input.mousePosition;
isRotating = true;
}
if (!Input.GetMouseButton (0))
isRotating = false;
if (isRotating) {
Vector3 pos = Camera.main.ScreenToViewportPoint (Input.mousePosition - mouseOrigin);
transform.RotateAround (transform.position, transform.right, -pos.y * sensitivity);
transform.RotateAround (transform.position, Vector3.up, pos.x * sensitivity);
rotationY = Mathf.Clamp (transform.localEulerAngles.y, minY, maxY);
rotationX = Mathf.Clamp (transform.localEulerAngles.x, minX, maxX);
transform.localEulerAngles = new Vector3 (-rotationY, rotationX, 0);
}
}
}
Here's an example of limiting the Y axis rotation, you can adapt it for X too. You didn't state what the limit should be based on so here it's based on the rotation of another object (public Transform target), this could be your player or whatever.
public float sensitivity = 16.0f;
public Transform target;
void Update()
{
if (Input.GetMouseButton(0))
{
//Debug.Log(Quaternion.Angle(transform.rotation, target.rotation));
float angle = Quaternion.Angle(transform.rotation, target.rotation);
if(angle < 45 || angle > 315)
{
Vector3 pos = Camera.main.ScreenToViewportPoint(Input.mousePosition);
transform.RotateAround(pos, Vector3.up, Time.deltaTime * sensitivity);
}
}
}
If instead you want to limit based on world space just check the rotation of the camera:
public float sensitivity = 16.0f;
//public Transform target;
void Update()
{
if (Input.GetMouseButton(0))
{
float angle = transform.eulerAngles.y;
Debug.Log(angle);
if (angle < 45 || angle > 315)
{
Vector3 pos = Camera.main.ScreenToViewportPoint(Input.mousePosition);
transform.RotateAround(pos, Vector3.up, Time.deltaTime * sensitivity);
}
}
}
Note in both cases the use of Time.deltaTime to ensure the rotation appears to happen at the same speed regardless of the players frame-rate.
If you want to reverse the rotation invert the axis argument of RotateAround:
transform.RotateAround(pos, -Vector3.up, Time.deltaTime * sensitivity);
I fixed it. Here is Complete code.
using UnityEngine;
using System.Collections;
public class MoveCamera : MonoBehaviour
{
public float sensitivity = 4.0f;
private Vector3 mouseOrigin;
private bool isRotating;
public GameObject cam;
void Start()
{
}
protected float ClampAngle(float angle, float min, float max) {
angle = NormalizeAngle(angle);
if (angle > 180) {
angle -= 360;
} else if (angle < -180) {
angle += 360;
}
min = NormalizeAngle(min);
if (min > 180) {
min -= 360;
} else if (min < -180) {
min += 360;
}
max = NormalizeAngle(max);
if (max > 180) {
max -= 360;
} else if (max < -180) {
max += 360;
}
return Mathf.Clamp(angle, min, max);
}
protected float NormalizeAngle(float angle) {
while (angle > 360)
angle -= 360;
while (angle < 0)
angle += 360;
return angle;
}
void Update ()
{
if (Input.GetMouseButtonDown (0)) {
mouseOrigin = Input.mousePosition;
isRotating = true;
}
if (!Input.GetMouseButton (0))
isRotating = false;
if (isRotating) {
cam.transform.localEulerAngles = new Vector3(0, ClampAngle(cam.transform.localEulerAngles.y, -45, 45), 0);
Vector3 pos = Camera.main.ScreenToViewportPoint (Input.mousePosition - mouseOrigin);
transform.RotateAround (transform.position, transform.right, -pos.y * sensitivity);
transform.RotateAround (transform.position, Vector3.up, pos.x * sensitivity);
}
}
}
Making a shop (about 50 objects in it that can be bought), so I need a scrollable area as not everything can go on on it.
This is the part when you are holding and sliding your finger.
public boolean pan(float x, float y, float deltaX, float deltaY) {
float scaleY = viewport.getWorldHeight() / (float)viewport.getScreenHeight();
camera.translate((int) 0, (int) (deltaY * scaleY));
return true;
}
The moment you release the finger this fires up.
public boolean fling(float velocityX, float velocityY, int button) {
float scaleY = viewport.getWorldHeight() / (float)viewport.getScreenHeight();
translation = scaleY * velocityY;
return false;
}
The logic to move the camera from fling is this:
if (translation != 0) {
camera.translate(0, translation * delta);
if (translation >= 0) {
up = true;
translation -= increasing * delta;
} else {
up = false;
translation += increasing * delta;
}
if (translation <= 0 && up) {
translation = 0;
} else if (translation >= 0 && !up) {
translation = 0;
}
increasing += 10000*delta;
}
So I have been playing around with these a little but cannot get a perfect scrolling speed. Has anybody done this before and knows the perfect starting speed ('translation') and stopping speed ('increasing')?
In one of my Android applications (Made with Unity), I would like to move the camera by scrolling with finger on the screen and simultaneously not detect hit, when I touch on any object during scrolling. My problem is that when I want to scroll down the camera with my finger, it firstly also detects hits with the objects. I have one script which is attached to Main Camera.
Here's the code for better understanding.
//Update function for scrolling and detecting touch.
//Do not want to detect touch on objects when scrolling.
void Update () {
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began) {
checkTouch(Input.GetTouch(0).position);
}
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved) {
Vector2 touchDeltaPosition = Input.GetTouch(0).deltaPosition;
transform.Translate(0, -touchDeltaPosition.y * Time.deltaTime, 0);
transform.position = new Vector3(0, Mathf.Clamp(transform.position.y, -30, 0), -10);
}
}
void checkTouch(Vector3 pos){
Vector3 wp = Camera.main.ScreenToWorldPoint (pos);
Vector2 touchpos = new Vector2 (wp.x, wp.y);
hit = Physics2D.OverlapPoint (touchpos);
if (hit) {
//Debug.Log (hit.transform.gameObject.name);
//hit.transform.gameObject.SendMessage ("Clicked", null, SendMessageOptions.DontRequireReceiver);
if (hit.transform.gameObject.tag == "item"){
//do something
}
}
}
I think you can try use something like this
void Update()
{
if (Input.touchCount <= 0)
return;
bool lMove = false;
if (Input.GetTouch(0).phase == TouchPhase.Moved)
{
Debug.Log("Touch phase = Moved");
lMove = true;
Vector2 touchDeltaPosition = Input.GetTouch(0).deltaPosition;
transform.Translate(0, -touchDeltaPosition.y * Time.deltaTime, 0);
transform.position = new Vector3(0, Mathf.Clamp(transform.position.y, -30, 0), -10);
}
if (Input.GetTouch(0).phase == TouchPhase.Ended)
{
Debug.Log("Touch phase = Ended");
if (!lMove)
{
//onClick
checkTouch(Input.GetTouch(0).position);
}
}
}
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class LineDirDetector: MonoBehaviour {
public Text texto01;
//inside class
Vector2 firstPressPos;
Vector2 secondPressPos;
Vector2 currentSwipe;
void Update()
{
Swipe();
}
public void Swipe() {
if (Input.touches.Length > 0) {
Touch t = Input.GetTouch(0);
if (t.phase == TouchPhase.Began) {
//save began touch 2d point
firstPressPos = new Vector2(t.position.x, t.position.y);
}
if (t.phase == TouchPhase.Ended) {
//save ended touch 2d point
secondPressPos = new Vector2(t.position.x, t.position.y);
//create vector from the two points
currentSwipe = new Vector3(secondPressPos.x - firstPressPos.x, secondPressPos.y - firstPressPos.y);
//normalize the 2d vector
currentSwipe.Normalize();
//swipe upwards
if (currentSwipe.y > 0 && currentSwipe.x > -0.5 f && currentSwipe.x < 0.5 f) {
Debug.Log("up swipe");
texto01.text = "ARRIBA";
}
//swipe down
if (currentSwipe.y < 0 && currentSwipe.x > -0.5 f && currentSwipe.x < 0.5 f) {
Debug.Log("down swipe");
texto01.text = "ABAJO";
}
//swipe left
if (currentSwipe.x < 0 && currentSwipe.y > -0.5 f && currentSwipe.y < 0.5 f) {
Debug.Log("left swipe");
texto01.text = "IZQUIERDA";
}
//swipe right
if (currentSwipe.x > 0 && currentSwipe.y > -0.5 f && currentSwipe.y < 0.5 f) {
Debug.Log("right swipe");
texto01.text = "DERECHA";
}
}
}
}
}
Here is my problem , i have a camera that i move right , left , down and up with Touch in android device , and i have a gui button who shows me a text when i double tap on it. The problem that when i touch the gui button , the camera move. I want when i touch the gui button , the camera stops moving and when i touch anywhere else in the screen the camera moves.
Here is my code:
public float tapSpeed = 0.5f;
private float lastTapTime = 0;
public Touch touch;
public Vector2 startPos;
public Vector2 endPos;
public bool fingerHold = false;
private float CameraYLimitUp;
private float CameraYLimitDown;
private float CameraXLimitRight;
private float CameraXLimitLeft;
public GUIText guiTextTap;
void Awake()
{
CameraYLimitUp = 0;
CameraYLimitDown = 27;
CameraXLimitRight = -15;
CameraXLimitLeft = 22;
}
void Update()
{
// Camera moves left right up down with touch
if (Input.touchCount > 0)
{
touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Began)
{
startPos = touch.position;
fingerHold = true;
print("touch began");
}
else if (touch.phase == TouchPhase.Moved)
{
endPos = touch.position;
}
else if (touch.phase == TouchPhase.Ended)
{
fingerHold = false;
print("touch end");
}
}
if (fingerHold)
{
float deltaX = endPos.x - startPos.x;
float deltaY = endPos.y - startPos.y;
bool horizontal = false;
if (Mathf.Abs(deltaX) > Mathf.Abs(deltaY))
horizontal = true;
if (horizontal)
{
if (deltaX < 0 && transform.position.x < CameraXLimitLeft)
transform.Translate(Vector3.left * Time.deltaTime * 20);
else if (deltaX > 0 && transform.position.x > CameraXLimitRight)
transform.Translate(Vector3.right * Time.deltaTime * 20);
}
else
{
if (deltaY < 0 && transform.position.y < CameraYLimitDown)
transform.Translate(Vector3.down * Time.deltaTime * 20);
else if (deltaY > 0 && transform.position.y > CameraYLimitUp)
transform.Translate(Vector3.up * Time.deltaTime * 20);
}
}
}
void OnGUI()
{
if (GUI.Button(new Rect(480 , 289.5f , 100, 100), "GUI Test"))
{
if ((Time.time - lastTapTime) < tapSpeed)
{
Debug.Log("Gui Button Taped");
guiTextTap.text = "Gui Button Taped";
}
lastTapTime = Time.time;
}
}
I Uploaded my project , you can find it here : https://mega.co.nz/#!0EkHQRDI!yDcUfJR_B5poXokku7fExOc-NtlDyYDeTCaBiAePzMs
Thanks a lot for your help
Checking the GUI hot control id would solve that issue, i.e. if the value of GUIUtility.hotControl is greater than 0, it means that the user holds down a button. Hence, you could simply modify your if statement as below to bypass the camera movement when the user presses down the button:
void Update()
{
...
...
// Check additionally if the GUI button is currently free
if (GUIUtility.hotControl == 0 && fingerHold)
{
...
...
}
}