Unity 2D, rotate Vector2 to NEW Vector2 in animation - unity3d

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);
}

Related

Unity rotation calculation

//RAYCAST
RaycastHit hit = new RaycastHit();
if(Physics.Raycast(impact.position, bloom, out hit, 1000f, canBeShot))
{
GameObject newBulletHole = Instantiate(bulletHolePrefab, hit.point + hit.normal * 0.001f, Quaternion.identity) as GameObject;
newBulletHole.transform.LookAt(hit.point + hit.normal);
Destroy(newBulletHole, 5f);
}
//Bullet
bulletSpawnPoint = GameObject.Find("BulletSpawn").transform;
var bullet = Instantiate(bulletPrefab, bulletSpawnPoint.position, **bulletSpawnPoint.rotation**);
bullet.GetComponent<Rigidbody>().velocity = bulletSpawnPoint.forward * loadout[currentIndex].bulletSpeed;
I need to get the perfect "bulletSpawnPoint.rotation" depending of my bullet hole created by the raycast hit. Thanks
enter image description here
So you want to spawn the bullet and then use Rigitbody to move it to the newBulletHole gameobject.
Easy way would be to store position of the bullet hole and then pass it into LookAt method of the bullet Transform before adding velocity.
A bit more advanced way (and this is what you are asking in your question, afaik): calculate the direction vector (bulletSpawnPoint.transform.position - newBulletHole.transform.position) and then get Quaternion (i.e. rotation) with LookRotation

Unity: How to find a empty hole in a wall for player?

I'm trying to figure out simple custom 2D physics for platformer. At the moment I'm using ray casts to figure out collision between the player and map. However using ray cast has some problems. For example, if the player is falling (has somewhat high downwards velocity) its unable to pick up holes in the wall because it moves past them due to going too far down to be detected as empty space.
One solution is to move to tile based system instead of using ray casts but I would preferably not to do so.
So I'm wondering is there some kinda solution to figure out empty holes in wall, even small edge ones without huge performance impact.
High quality drawn illustration, assume leftwards velocity:
Physics2D.BoxCast is how I would tackle this. It does what you expect, instead of a ray it calculates as if a full box was traversing the distance.
Usage is very similar to raycasting. Example:
public Collider2D mainCollider;
public Vector2 velocity;
void Update() {
Vector2 origin = new Vector2(transform.position.x, transform.position.y);
Vector2 size = mainCollider.bounds.size;
Vector2 direction = velocity * Time.deltaTime;
float maxDist = velocity.magnitude;
var hit = Physics2D.BoxCast(origin, size, 0, direction, maxDepth);
if (hit == null) {
transform.position += direction;
} else {
transform.position += direction.normalized * hit.distance;
}
}
If boxes are not your taste, there's also a Physics2D.CapsuleCast and Physics2D.CircleCast.

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?

Unity 3D Ball Follow the finger

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.

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().