Moving object to touch position acting unexpectedly - android

Good evening, quick question.
Im developing a top-down 2D platformer game in Unity3D. Here is a picture of the game.
I have pretty much everything worked out on a desktop, but when attempting to set up the controls for mobile, I can't seem to get it to work the way it should. All I need is to get the player to move in the direction of wherever the user touches the screen. With the current code im using, the player just rotates in 4 directions, up, down, left and right. He also moves a little, but never goes far from his spawn point.
Please take a look at my revised code:
public Camera camera;
public float movespeed = 0;
// Use this for initialization
void Start () {
movespeed = 2.75F;
}
// Update is called once per frame
void Update () {
if (Input.touchCount > 0) {
// The screen has been touched so store the touch
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Stationary || touch.phase == TouchPhase.Moved) {
// If the finger is on the screen, move the object smoothly to the touch position
Vector3 touchPosition = camera.ScreenToWorldPoint(new Vector3(touch.position.x, touch.position.y, -13));
Quaternion rot = Quaternion.LookRotation(transform.position - touchPosition, Vector3.back);
transform.rotation = rot;
transform.eulerAngles = new Vector3 (0, 0, transform.eulerAngles.z);
rigidbody2D.angularVelocity = 0;
//float input = Input.GetAxis ("Vertical");
transform.position = Vector3.Lerp(transform.position, touchPosition, Time.deltaTime);
}
}
}
}
Any ideas on how I can get my player to move to the touched are of the screen? Any help would be much appreciated. Thanks in advance.

If I have understood correctly, you want your player game object to move towards the point on the screen that is being touched. I think it's probably best to describe the behavior of your code so that you can hopefully better understand what might be happening.
From the code posted, I can see one possible issue. Look again at this line:
Quaternion rot = Quaternion.LookRotation(transform.position - touchPosition, Vector3.back);
Here, you are asking Unity to calculate the unit quaternion that represents a rotation from the direction of Vector3.forward to the direction from of the player game object from the touch position. This probably isn't what you want. From the description of the problem, you want the game object to rotate to face the point on the screen being touched (rather than the opposite direction). You can either change the order of the subtraction operands or, preferably, use instead the Transform.LookAt method.
After this, you update the transform's rotation:
transform.rotation = rot;
That's fine, but note that you wouldn't need to do this when using Transform.LookAt.
You then set the transform's rotation again using in this line:
transform.eulerAngles = new Vector3 (0, 0, transform.eulerAngles.z);
I'm not entirely sure why you are doing this. If you only want one axis of rotation, you can use, for example:
transform.LookAt(new Vector3(touchPosition.x, touchPosition.y, transform.position.z))
This should rotate the player's transform around the z-axis to look in the direction of the point being touched.
Finally, you linearly interpolate the transform's position from its current position to the point being touched:
transform.position = Vector3.Lerp(transform.position, touchPosition, Time.deltaTime);
This isn't necessary. Instead, you should just move the player's transform forward. The player should be looking in the direction of the touched screen point. Hence, translating the player forward will move the player towards said screen point:
transform.position += transform.forward * speed * Time.deltaTime;
When the player is very close to the touched screen point it will overshoot and immediately rotate to look in the opposite direction. This will occur repeatedly. You should include some distance that specifies when the player is assumed to have reached the target point.

Related

Panning the view of a gameObject instead of the camera in Unity3d?

I'm having a hard time to pan a view of a gameObject in Unity3d. I'm new to scripting and I'm trying to develop an AR (Augmented Reality) application for Android.
I need to have a gameObject (e.g. a model of a floor), from the normal top down view, rendered to a "pseudo" iso view, inclined to 45 degrees. As the gameObject is inclined, I need to have a panning function on its view, utilizing four (4) buttons (for left, right, forward(or up), backward(or down)).
The problem is that, I cannot use any of the known panning script snippets around the forum, as the AR camera has to be static in the scene.
Need to mention that, I need the panning function to be active only at the isometric view, (which I already compute with another script), not on top down view. So there must be no problem with the inclination of the axes of the gameObject, right?
Following, are two mockup images of the states, the gameObject (model floor) is rendered and the script code (from Unity reference), that I'm currently using, which is not very much functional for my needs.
Here is the code snippet, for left movement of the gameObject. I use the same with a change in -, +speed values, for the other movements, but I get it only move up, down, not forth, backwards:
#pragma strict
// The target gameObject.
var target: Transform;
// Speed in units per sec.
var speedLeft: float = -10;
private static var isPanLeft = false;
function FixedUpdate()
{
if(isPanLeft == true)
{
// The step size is equal to speed times frame time.
var step = speedLeft * Time.deltaTime;
// Move model position a step closer to the target.
transform.position = Vector3.MoveTowards(transform.position, target.position, step);
}
}
static function doPanLeft()
{
isPanLeft = !isPanLeft;
}
It would be great, if someone be kind enough to take a look at this post, and make a suggestion on how this functionality can be coded the easiest way, as I'm a newbie?
Furthermore, if a sample code or a tutorial can be provided, it will be appreciated, as I can learn from this, a lot. Thank you all in advance for your time and answers.
If i understand correctly you have a camera with some fixed rotation and position and you have a object you want to move up/down/left/right from the cameras perspective
To rotated an object to a set of angles you simply do
transform.rotation = Quaternion.Euler(45, 45, 45);
Then to move it you use the cameras up/right/forward in worldspace like this to move it up and left
transform.position += camera.transform.up;
transform.position -= camera.transform.right;
If you only have one camera in your scene you can access its transform by Camera.main.transform
An example of how to move it when someone presses the left arrow
if(Input.GetKeyDown(KeyCode.LeftArrow))
{
transform.position -= camera.transform.right;
}

Unity2D - How to rotate a 2D object on touch/click/press

First of all, I'll let you know that I'm new to Unity and to coding overall (I do know some very basic javascript coding). My question: How can I rotate a 2D object (prefab) 120 degrees on a certain axis (in my case the z-axis, so it rotates like you're looking at a steering wheel) every time I touch on the screen. Right now I have it like this:
function TouchOnScreen ()
{
if (Input.touchCount > 0)
{
var touch = Input.touches[0];
if (touch.position.x < Screen.width/2)
{
transform.rotation = Quaternion.Euler(0,0,120);
Debug.Log("RotateRight");
}
else if (touch.position.x > Screen.width/2)
{
transform.rotation = Quaternion.Euler(0,0,-120);
Debug.Log("RotateLeft");
}
}
}
This code rotates the object whenever I press on a certain side of the screen, but not how I want it to. I want it to rotate so you see the object rotating from A to B, but not (like it is now) in one frame from A to B. Also, this code lets me only rotate one time to each direction.
How can I make it that whenever I press on a certain side of the screen, that it adds or subtracts to/from the previous rotated angle, so I can keep on rotating.
NOTE: Please use javascript, and if you know a simpler code, let me know!
Help is highly appreciated, thanks in advance!
Instead of
transform.rotation = Quaternion.Euler(0,0,-120);
You use:
var lSpeed = 10.0f; // Set this to a value you like
transform.rotation = Quaterion.Lerp ( transform.rotation, Quaternion.Euler(0,0,-120), Time.deltaTime*lSpeed);

Calculate object position direction after collision

I am writing my own game engine (a very base one), I want to learn how physics work in game development and not using an already built game engine. I am writing my code in Java for Android devices (using SurfaceView).
The problem is that I don't know how to calculate the position for my object after a collision. I have created my own collision detection and it is working perfectly.
As you can see, the red rectangle is the area where my ball should move. The arrows is showing where the ball should move after a collision happens. The ball have different position, marked with 1 - 11 (note, while rendering the "world" you see only one ball!).
The balls are actually rectangles! But you can not see the edges.
I have created my own Game Object class, where I'm keeping data about the object position, velocity, origin, etc.:
public abstract class GameObject
{
public Vector2 dimension;
public Vector2 position;
public Vector2 velocity;
public Vector2 origin;
public Rectangle rectangle;
public GameObject(Resources resources)
{
this.dimension = new Vector2();
this.position = new Vector2();
this.velocity = new Vector2();
this.origin = new Vector2();
this.rectangle = new Rectangle();
}
public void update(float deltaTime)
{
position.x += velocity.x;
position.y += velocity.y;
rectangle.set(position.x, position.y, dimension.x, dimension.y);
origin.x = position.x + dimension.x / 2;
origin.y = position.y + dimension.y / 2;
}
}
This method is called if a ball collide with one of the red rectangle margins:
protected void onBallCollideWithLevelEdge(Ball ball)
{
// Calculate next position:
??????????
}
My ball have a velocity and a position. Should I save the previous position of the ball?
1) Why do you represents balls as rectangles? Circle is far more easy to handle, expecially if you want to extend collision to ball-ball.
2) If you are trying to make a physics engine you must have coordinates of all objects and the respective first and second derivatives, aka speed and acceleration. Moreover you need a mass for each object and maybe some other parameters, for example material (for friction) and elasticity, but this is not needed at the beginning.
3) When a collision with walls happens you have current ball position and velocity. Given this data you have to calculate normal force. Normal force is such that ball cannot pass through the wall, so I'd calculate it's magnitude using something like this:
Nx = DELTAx*k;
Ny = DELTAy*k;
where k is some elasticity constant that you can trim and x is the measure of how much the ball has penetrated in the wall. Note that this is good only for "slow" objects. If you deal with bullets you'd better using something like rays or.
Another way could be to calculate kinetic energy at the time of collision and transfer it to elastic energy. Once you have elastic energy you can release it in a direction normal to the wall, transforming it to a force.
Once you have the force, it becomes an acceleration by dividing it for the mass.
4) at each simulation iteration you add speed to position, and acceleration to speed, remembering of multiplying it for the integration time (dt). This time can be set arbitrarly and it's a constant. If you want a 100Hz simulation you set dt to 10ms. You also have to recalculate acceleration as the sum of forces divided by the mass.
5) As you note I never talked about direction because you don't need it if you are reasoning decomposing coordinates in each axis (x,y in a 2D engine). If the normal force is "right", as in your example, the Ny component will be set to zero, while Nx will be tranformed into acceleration and will change the horizontal speed. This also will change the ball's direction.
These are only advices, actually you should start by studying kinematics and later something of rational mechanics.
I had an function that looked something like this:
Position calculateValidPosition(Position start, Position end)
Position middlePoint = (start + end) /2
if (middlePoint == start || middlePoint == end)
return start
if( isColliding(middlePont) )
return calculateValidPosition(start, middlePoint)
else
return calculate(middlePoint, end)
I just made this code on the fly, so there would be a lot of room for improvements... starting by not making it recursive.
This function would be called when a collision is detected, passing as a parameter the last valid position of the object, and the current invalid position. On each iteration, the first parameter is always valid (no collition), and the second one is invalid (there is collition).
But I think this can give you an idea of a possible solution, so you can adapt it to your needs.

Unity2D Android Touch misbehaving

I am attempting to translate an object depending on the touch position of the user.
The problem with it is, when I test it out, the object disappears as soon as I drag my finger on my phone screen. I am not entirely sure what's going on with it?
If somebody can guide me that would be great :)
Thanks
This is the Code:
#pragma strict
function Update () {
for (var touch : Touch in Input.touches)
{
if (touch.phase == TouchPhase.Moved) {
transform.Translate(0, touch.position.y, 0);
}
}
}
The problem is that you're moving the object by touch.position.y. This isn't a point inworld, it's a point on the touch screen. What you'll want to do is probably Camera.main.ScreenToWorldPoint(touch.position).y which will give you the position inworld for wherever you've touched.
Of course, Translate takes a vector indicating distance, not final destination, so simply sticking the above in it still won't work as you're intending.
Instead maybe try this:
Vector3 EndPos = Camera.main.ScreenToWorldPoint(touch.position);
float speed = 1f;
transform.position = Vector3.Lerp(transform.position, EndPos, speed * Time.deltaTime);
which should move the object towards your finger while at the same time keeping its movements smooth looking.
You'll want to ask this question at Unity's dedicated Questions/Answers site: http://answers.unity3d.com/index.html
There are very few people that come to stackoverflow for Unity specific question, unless they relate to Android/iOS specific features.
As for the cause of your problem, touch.position.y is define in screen space (pixels) where as transform.Translate is expecting world units (meters). You can convert between the two using the Camera.ScreenToWorldPoint() method, then creating a vector out of the camera position and screen world point. With this vector you can then either intersect some geometry in the scene or simply use it as a point in front of the camera.
http://docs.unity3d.com/Documentation/ScriptReference/Camera.ScreenToWorldPoint.html

Dragging Camera based on Touch (Unity)

In my game, I want the camera to move based on the user swiping their finger. My issue is that when someone removes their finger from the screen, and places it down again, the camera jumps to a new position... I am guessing it has to do with the coordinates, I say this because if I click somewhere far from where I removed my finger from the screen, the camera jumps. Here is the code:
var speed : int = 1;
var lastPoint : Vector2; //make this private if you want to.
function Update()
{
var offset : float; //offset of the touch from last frame
if(Input.touches.Length 0)//make sure we have a touch in the first place
{
var evt : Touch = Input.touches[0]; //setting up touch events so we can get fancy.
if(evt.phase == TouchPhase.Began) //this is the first frame the screen has been touched for, simply save the point.
{
lastPoint == evt.position;
}
else if(evt.phase == TouchPhase.Moved
{
offset = evt.position.x - lastPoint.x ;//take the difference
//I'm going to use Transform.Rotate because it's handy dandy
transform.Rotate(0,offset * speed,0);
//save the new "lastPoint"
lastPoint = evt.position;
}
else if(evt.phase == TouchPhase.Ended)
{
//If you want the object to drift after you spin it you can make a function to go here.
//To do this, take the speed of the rotation and continue to rotate all while subtracting off of the speed.
//I would use the Transform.Rotate function on this too.
//If you need me to I could write this function too.
}
}
}
What is the solution to have the camera resume, and not jump once someone puts their finger down again?
I am also willing to redo it, if there is a better solution/more efficient method of solving the issue..
Thanks a lot!
The supplied code seems fine, all you need to do is when the user is not pressing, you update the lastPoint every frame. Or if you know when the user start to press, just set the lastPoint to the current pos before calculating the offset. This way the offset is zero the first frame the user touch the screen.

Categories

Resources