Unity 3D Ball Follow the finger - unity3d

I am trying to create a 3d game like ketchapp ball race, in which the cube slides along a road, and the left right movement is controlled using touch
The problem I am facing is that the touch senstivity seems to react different on different devices, due to which I am not able to calculate the left-right displacement for all devices.
This is how I am calculating the left-right displacement of the cube:
Vector2 touchDeltaPosition = Input.GetTouch(0).deltaPosition ;
transform.Translate(touchDeltaPosition.x * .1f * Time.deltaTime, 0, 0);
However this is not working properly all device . Any help will be highly appreciated

See this answer: https://stackoverflow.com/a/25740565/10063126
Basically, ScreenToWorldPoint was used.
World position is computed; not screen touch position.
But you have to manually solve for delta position.
Example:
Vector3 currPos = Input.mousePosition;
Vector3 startPos = Camera.main.ScreenToWorldPoint(currPos);
Vector3 endPos = Camera.main.ScreenToWorldPoint(prevPos);
Vector3 deltaPos = endPos - startPos;
transform.Translate(deltaPos.x * sensitivity * Time.deltaTime, 0, 0);
prevPos = currPos;

How about using 2 buttons on your screen one for left control and one for right control and then when the left button is pressed you can give a value to go left and same for right button. This way your ball's movement will be independent from the touched position's X value.

Related

Unity 2D, rotate Vector2 to NEW Vector2 in animation

My game is 2D from a top down-ish perspective, my character movement vector2 being fed into the animator blend to determine which direction my sprite faces: (example sprite)
Vector2 movement = new Vector2(Input.GetAxis("Horizontal"),
Input.GetAxisRaw("Vertical"));
anim.SetFloat("hor", movement.x);
anim.SetFloat("ver", movement.y);
However, I would like my sprite to rotate to it's new target vector2 rather than instantly switch to it. So if I was facing right, and I pushed left, the movement vector2 would travel over time to a new movementTarget vector2, the sprite changing from facing right, to up, to left.
I cannot figure or find a way to do this and have been on it many hours. I've tried things like Vector3.RotateTowards and angles, but each approach I can't get what I'm looking for as this aspect of math just confuses me.
Could someone point me in the right direction?
Vector2 targetMovement = new Vector2(Input.GetAxis("Horizontal"),
Input.GetAxisRaw("Vertical"));
if (targetMovement != movement) coroutine?????
I don't want to rotate the sprite image, or the object transform, just the movement Vector2 variable over time. So if I am facing right (1,0) and press left, I want the Vector to travel through (0,1 - up) then finally to (-1,0 - left) but gradually.
Managed to do it like this. Unsure if best way?
float currAngle, targAngle;
Vector2 movement = new Vector2(Input.GetAxis("Horizontal"),
Input.GetAxisRaw("Vertical"));
if (movement != Vector2.zero)
targAngle = Mathf.Atan2(movement.y, movement.x) * Mathf.Rad2Deg;
if (Mathf.Abs(currAngle - targAngle) > 1f) {
currAngle = Mathf.LerpAngle(currAngle, targAngle, 10f * Time.deltaTime);
Vector2 newVec = new Vector2(Mathf.Cos(currAngle * Mathf.Deg2Rad),
Mathf.Sin(currAngle * Mathf.Deg2Rad));
anim.SetFloat("hor", newVec.x);
anim.SetFloat("ver", newVec.y);
}

Rotating player is messing up my movement

I wrote a simple player movement script which moves my player like this:
private void MovePlayer()
{
// Initialize Directions For Player Movement
movement = transform.right * horizontal * playerSpeed + transform.forward * vertical * playerSpeed;
// Move Player
rb.AddForce(movement, ForceMode.Acceleration);
}
and I am trying to rotate my player towards the axes, for example if the player is pressing a the horizontal will be -1 and I want to rotate my player left horizontal * 90f, now when I try this, my horizontal axis is acting like my vertical, if I press A it will bring my player backwards, if I press D it will do the same thing, this is how I rotate the player:
// buggy code:
private void RotatePLayerTowardsAxis()
{
// Rotate PLayer Horizontaly
transform.rotation = Quaternion.Euler(0f, horizontal * 90, 0f);
}
is there a way I can do this?
Edit:
The vertical is still pushing me up and down.
First, it is important to check if you are looking at the scene in Local or Global view. Check your axes in Local mode:
If your character model faces towards the blue axis, then everything should be okay.
If you want to rotate your character only by 90 degrees all the time, then it can be done somehow like this:
transform.rotation = Quaternion.Euler(0, 90, 0);
You can use the following as well, but this might not fit your needs:
transform.Rotate(transform.up, 90);
This will make your character rotate by 90 degrees AROUND the up axis. If you want it to rotate always around the world up axis:
transform.Rotate(Vector3.up, 90);
However, transform.rotation = Quaternion.Euler(0, 90, 0); might be better for you, as it always "resets" the rotation when you overwrite it. This will make the character fixed to a direction. So if you press left, the charater will always look into the left by 90 degree. And if you press right after the left turn, your character will do a 180° turn instead of looking forward. I hope you get what I'm trying to say. This means, that your character will be bound to the world axis instead of its own. To modify this (if you want to), write something like this:
transform.rotation += Quaternion.Euler(0, 90, 0);
Hope I could help!

Cursor GameObject vanishing after some time

cursors.transform.position = Vector3.MoveTowards(cursors.transform.position, Camera.main.ScreenToWorldPoint(Input.mousePosition), 10f * Time.deltaTime);
I want to make a cursor that moves smoothly and not instant towards the mouseposition, and for a few seconds, it works, then vanishes within a few seconds, anyone know why this happens ?
I would like to ask you, is your cursor game object a 2D object that you want to move along the screen ( x, y coords only ) or you want to move it in world space ( z axis is included ) ?
Your cursor might be moving through the camera's clipping plane
You could try:
Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
mousePos.z = 0;
cursors.transform.position = Vector3.MoveTowards(cursors.transform.position, mousePos, 10f * Time.deltaTime);

Eliminating camera jitters caused by repositioning camera within defined bounds

This is the image of what I'm trying to achieve, in a 3D space. I want the object to follow my finger within the green zone, but stay on the edge of the green zone if I move my finger outside of it. I have achieved this with the code below, but when moving my finger around the red zone a lot of jitters and clipping occurs as the object keeps snapping back within it's bounds. The jitters I'm seeing are caused when holding my finger in the red zone out of the players circle bounds. Instead of being "stuck" in the bounds the player is trying to continue and then being positioned back within the bounds, causing jitters. I'm looking for a way to limit the movement of the player within the bounds without having to reset it's position. My main camera is attached to the moving object so it's important that I eliminate the jitters. How can I smooth this out?
public class Player : MonoBehaviour
{
public Camera movementCam;
readonly float radius = 0.45f;
readonly float speed = 3f;
Ray firstTouchPos;
Vector2 playerPos;
[SerializeField] Vector3 targetPosition;
readonly float followDelay = 20f;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
firstTouchPos = movementCam.ScreenPointToRay(Input.mousePosition);
playerPos = transform.position;
}
if (Input.GetMouseButton(0))
{
Ray currentTouchPos = movementCam.ScreenPointToRay(Input.mousePosition);
Vector2 direction = currentTouchPos.origin - firstTouchPos.origin;
float distance = Vector3.Distance(transform.position, Vector3.zero);
targetPosition = distance >= radius ? (Vector3) . (direction.normalized * radius) : (Vector3)(playerPos + direction * speed);
}
transform.position = Vector3.Lerp(transform.position, targetPosition, followDelay);
}
}
Your issue is incorrectly clamping, a simple fix would be:
if (Input.GetMouseButton(0))
{
Ray currentTouchPos = movementCam.ScreenPointToRay(Input.mousePosition);
Vector2 direction = currentTouchPos.origin - firstTouchPos.origin;
float distance = Vector3.Distance(transform.position, Vector3.zero);
targetPosition = (Vector3)(playerPos + direction * speed);
if (targetPosition.sqrMagnitude > radius * radius) //if our calculated position is greater than the radius...
targetPosition = targetPosition.normalized * radius; //set our calculated position to be exactly on the radius.
}
The jitter was caused by your object leaving the radius one frame, and on the next frame would be clamped back to the radius, only for it to attempt to move outside the radius again the next frame.
This way removes the ternary operator, which means it will behave consistently across frames, rather than switching between clamp and movement each frame.
Here are some additional pieces of advice for this issue, once you fix the above problem:
You should multiply speed and followDelay by time.deltaTime in order to smooth them across frames correctly.
You should probably apply your camera motion during LateUpdate() instead of Update(), LateUpdate() happens after all your updates happen, what can happen is during Update() objects can move around before and after your camera code is called, causing it to behave slightly inconsistently from frame to frame, applying the motion in LateUpdate() to the camera means your camera moves only when all your objects have 'settled' into place after their update, making it behave more consistently.
Additionally you're technically using Lerp() wrong here, it shouldn't cause jitter but it's not exactly how lerp should be used. Are you sure you don't want Vector3.MoveTowards() instead?

Topdown camera focus with angle

I'm making a topdown game with the camera at 40 degree angle. What I want to do is when i click an gameobject, It will move the camera and position the object at the left side from the center of the camera view regardless of its rotation. So that I can place a menu at the right side. How do I get the offset of the angled camera so that the object is in the middle left side of the camera view?
Right now i use lerp but it overshoots the target because of the cameras angle. Sorry for the noob question I'm new to unity3d.
transform.position = Vector3.Lerp(transform.position, new Vector3(target.transform.position.x, transform.position.y, target.transform.position.z), 0.1f);
First of all you should start by finding point that your camera will move/lerp to.
In your case in can be simplified to 2D-Space:
It shouldnt be tough to find that one.
Use transform.forward of camera to get vector (Vector3 cameraDir) of direction your camera is looking at
Rotate by horizontal fov / 4 around y axis:
Vector3 cameraDirRotated = Quaternion.AngleAxis(hFov/4f, Vector3.up) * cameraDir;
-cameraDirRotated will be vector from Cube To point P you're looking for, u can also scale it:
Vector3 PtoMoveTo = cube.transform.position - cameraDirRotated.normalized * 5f;
Full:
Vector3 FindCameraTarget(Transform targetObj, float hFov)
{
Vector3 cameraDir = transform.forward;
Vector3 cameraDirRotated = Quaternion.AngleAxis(hFov / 4f, Vector3.up) * cameraDir;
Vector3 target = targetObj.transform.position - cameraDirRotated.normalized * 5f;
return target;
}
Then:
transform.position = Vector3.Lerp(transform.position, FindCameraTarget(target, 90f) , 2f * Time.deltaTime);
For performance u can save that target vector once if Cube is not moving. Search web how to precisely count horizontal fov. Multiply speed by Time.timeDelta if u lerp in Update().