Player keeps rotating when going left in Unity 2d - c#

I'm using Unity to move my player sprite in a 2D platformer where it'll go right if right key is pressed & left if left key is pressed.
The right movement is working fine, but whenever the player moves left, I'm changing the Y rotation to 180 and the player is supposed to show left animation only but it keeps rotating back and forth when going left.
See the video sample.
This is my code:
private Rigidbody2D rb;
private void FixedUpdate() {
InputManager();
}
private void InputManager()
{
float hDir = Input.GetAxis("Horizontal");
if (state != State.hurt) {
if(!anm.GetCurrentAnimatorStateInfo(0).IsTag("attack"))
{
if (hDir < 0) // Go left
{
rb.velocity = new Vector2(-speedX, rb.velocity.y);
transform.Rotate(0f, 180f, 0f);
}
else if (hDir > 0) // Go right
{
rb.velocity = new Vector2(speedX, rb.velocity.y);
transform.Rotate(0f, 0f, 0f);
}
}
}
}
How can I make my player stick to left animation when going on left? Please do not suggest changing localScale as I know it works but for shooting purpose it's best that my player rotates.

Here is a thing transform.Rotate(0,180,0); is used to rotate 180 degree in y axis each time when this line of code execute that's why you player does not stop rotating
Here is the code you can use it will stop you player rotate according to the directions
private void InputManager()
{
float hDir = Input.GetAxis("Horizontal");
if (state != State.hurt)
{
if (!anm.GetCurrentAnimatorStateInfo(0).IsTag("attack"))
{
if (hDir < 0) // Go left
{
rb.velocity = new Vector2(-speedX, rb.velocity.y);
this.transform.rotation = Quaternion.AngleAxis(180, Vector3.up);
}
else if (hDir > 0) // Go right
{
rb.velocity = new Vector2(speedX, rb.velocity.y);
this.transform.rotation = Quaternion.AngleAxis(0, Vector3.up);
}
}
}
}

You need to add a bool Variable that is checking if the player is facing right, as well as a Flip Function that flips him:
bool bFacingRight = true;
private Rigidbody2D rb;
int _switch;
private void FixedUpdate() {
InputManager();
}
private void InputManager()
{
if (state == State.hurt || anm.GetCurrentAnimatorStateInfo(0).IsTag("attack"))
return;
float hDir = Input.GetAxis("Horizontal");
// Move the character by finding the target velocity
rb.velocity = new Vector2(hDir * 10f, rb.velocity.y);
if (hDir < 0 && bFacingRight) { // Flip Left
_switch = 0;
Flip(_switch);
}
else if (hDir > 0 && !bFacingRight) { // Flip Right
_switch= 1;
Flip(_switch);
}
}
private void Flip(int swth)
{
// Switch the way the player is labelled as facing.
bFacingRight = !bFacingRight;
// Multiply the player's x local scale by -1.
switch(swth)
{
case 0:
this.transform.rotation = Quaternion.AngleAxis(180, Vector3.up);
break;
case 1:
this.transform.rotation = Quaternion.AngleAxis(0, Vector3.up);
break;
}
}

Related

How can I rotate the capsule only on the Y?

RotateTo is call from the Update. I want it to rotate on the Y only.
now it seems like it's rotating on all axis X,Y,Z
private void RotateTo()
{
var distance = Vector3.Distance(capsule.position, curvedLinePoints[rotationIndex].transform.position);
if(distance < 0.1f)
{
rotationIndex++;
}
// Determine which direction to rotate towards
Vector3 targetDirection = curvedLinePoints[rotationIndex].transform.position -capsule.position;
// The step size is equal to speed times frame time.
float singleStep = rotationSpeed * Time.deltaTime;
// Rotate the forward vector towards the target direction by one step
Vector3 newDirection = Vector3.RotateTowards(capsule.forward, targetDirection, singleStep, 0.0f);
// Calculate a rotation a step closer to the target and applies rotation to this object
capsule.rotation = Quaternion.LookRotation(newDirection);
}
This is the full script.
The transform is moving along g waypoints there are more than 4000 waypoints the capsule should only rotate looking each time to the next curvedLinePoint from the List curvedLinePoints.
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class WaypointsFollower : MonoBehaviour
{
public float speed;
public Waypoints waypoints;
public Transform capsule;
public bool go;
public bool goForward;
public float rotationSpeed;
private int index = 0;
private int rotationIndex = 0;
private int counter = 0;
private int c = 0;
private List<GameObject> curvedLinePoints = new List<GameObject>();
public int numofposbetweenpoints;
private bool getonce;
private bool getBackwardIndexOnce = true;
private void Start()
{
waypoints = GameObject.Find("Waypoints").GetComponent<Waypoints>();
curvedLinePoints = GameObject.FindGameObjectsWithTag("Curved Line Point").ToList();
if(waypoints.moveInReverse == false)
{
goForward = true;
}
else
{
goForward = false;
}
if(goForward)
{
index = 0;
}
}
private void Update()
{
if (getonce == false)
{
numofposbetweenpoints = curvedLinePoints.Count;
getonce = true;
}
if (go == true && waypoints.lineRendererPositions.Count > 0)
{
if(goForward == false && getBackwardIndexOnce)
{
index = waypoints.lineRendererPositions.Count - 1;
getBackwardIndexOnce = false;
}
RotateTo();
Move();
}
}
private void Move()
{
Vector3 newPos = transform.position;
float distanceToTravel = speed * Time.deltaTime;
bool stillTraveling = true;
while (stillTraveling)
{
Vector3 oldPos = newPos;
// error exception out of bound on line 55 to check !!!!!
newPos = Vector3.MoveTowards(oldPos, waypoints.lineRendererPositions[index], distanceToTravel);
distanceToTravel -= Vector3.Distance(newPos, oldPos);
if (newPos == waypoints.lineRendererPositions[index]) // Vector3 comparison is approximate so this is ok
{
// when you hit a waypoint:
if (goForward)
{
bool atLastOne = index >= waypoints.lineRendererPositions.Count - 1;
if (!atLastOne)
{
index++;
counter++;
if (counter == numofposbetweenpoints)
{
c++;
counter = 0;
}
if (c == curvedLinePoints.Count - 1)
{
c = 0;
}
}
else { index--; goForward = false; }
}
else
{ // going backwards:
bool atFirstOne = index <= 0;
if (!atFirstOne)
{
index--;
counter++;
if (counter == numofposbetweenpoints)
{
c++;
counter = 0;
}
if (c == curvedLinePoints.Count - 1)
{
c = 0;
}
}
else { index++; goForward = true; }
}
}
else
{
stillTraveling = false;
}
}
transform.position = newPos;
}
private void RotateTo()
{
var distance = Vector3.Distance(capsule.position, curvedLinePoints[rotationIndex].transform.position);
if(distance < 0.1f)
{
rotationIndex++;
}
// Determine which direction to rotate towards
Vector3 targetDirection = curvedLinePoints[rotationIndex].transform.position -capsule.position;
// The step size is equal to speed times frame time.
float singleStep = rotationSpeed * Time.deltaTime;
// Rotate the forward vector towards the target direction by one step
Vector3 newDirection = Vector3.RotateTowards(capsule.forward, targetDirection, singleStep, 0.0f);
// Calculate a rotation a step closer to the target and applies rotation to this object
capsule.rotation = Quaternion.LookRotation(newDirection);
}
}
This is a screenshot of the hierarchy the platform is the moving transform in the script and the capsule is the capsule that should only rotate facing each time the next curvedLinePoint. There are over 4000 waypoints but only 10 curvedLinePoints. a bit confusing. The capsule should rotate facing each time the next curvedLinePoint while the transform is moving along the waypoints.
Screenshot
I tried this now :
private void RotateTo()
{
var distance = Vector3.Distance(capsule.position, curvedLinePoints[rotationIndex].transform.position);
if(distance < 0.1f)
{
rotationIndex++;
}
var lookPos = curvedLinePoints[rotationIndex].transform.position - capsule.position;
lookPos.y = 0;
var rotation = Quaternion.LookRotation(lookPos);
capsule.rotation = Quaternion.Slerp(capsule.rotation, rotation, Time.deltaTime * rotationSpeed);
}
and it's rotating bu when I'm looking on the capsule I don't see any of the axis pointing the next point for example in this screenshot the blue is facing to the right the green up the red more ore less down while the point it's moving to is on the left cube so the capsule rotates but why none of the axis is pointing at its direction?
Rotation
I also added eyes to the capsule on the blue axis thinking the blue axis is forward but the capsule is rotating the eyes are never facing the next target.
This screenshot is just to show the eyes on the blue axis direction.
Eyes

I'm using Unity C# and Whenever I press down my finger to control the ball, the ball slows down how do I prevent that?

my ball slows down when I press the screen, which is making the game go very slowly, When I let go the ball starts speeding up again because of gravity.
{
private Vector3 touchPosition;
private Rigidbody2D rb;
private Vector3 direction;
private float moveSpeed = 10;
// Use this for initialization
private void Start()
{
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
private void Update()
{
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
touchPosition = Camera.main.ScreenToWorldPoint(touch.position);
touchPosition.z = 0;
direction = (touchPosition - transform.position);
rb.velocity = new Vector2(direction.x, 0) * moveSpeed;
if (touch.phase == TouchPhase.Ended)
rb.velocity = Vector2.zero;
}
}
}
Each time you press the button, you're telling the RigidBody you want the y velocity to be 0, essentially stopping to ball from falling.
Try this instead:
private void Update ( )
{
if ( Input.touchCount > 0 )
{
Touch touch = Input.GetTouch ( 0 );
touchPosition = Camera.main.ScreenToWorldPoint ( touch.position );
touchPosition.z = 0;
direction = ( touchPosition - transform.position );
var v = rb.velocity;
v.x = direction.x * moveSpeed;
rb.velocity = v;
if ( touch.phase == TouchPhase.Ended )
rb.velocity = Vector2.zero;
}
}
Or, you could even just get the x component in the first place with:
var x = touchPosition.x - transform.position.x;
rb.velocity = new Vector2 ( x, rb.velocity.y );
Either way should do the trick. The second is slightly more performant.
If you are looking to maintaining the current velocity of the object(horizontaly), then
rb.velocity = new Vector2(direction.normalized.x* rb.velocity.x, 0);
You are currently resetting the velocity of the object to the movement speed to its basic speed (and the distance between your finger, which I dont believe you want). In addition, it is unclear if you have vertical movement with the 0 in y, which will stop the object's vertical movement. If you do you need the vertical movement to be maintain, you need to replace 0 with rb.velocity.y.
rb.velocity = new Vector2(direction.normalized.x* rb.velocity.x * moveSpeed, rb.velocity.y );
or
rb.velocity = new Vector2(direction.normalized.x * moveSpeed,1)* rb.velocity;

Dash against slopes using physics in Unity 2D

I'm working on a 2D project in Unity.
The character controller is physics based, so I use rigidbody to move the player. Everything is working fine except when I try to apply a high speed movement to the character, like a dash.
This is how the code looks like.
I just check if the player is dashing, so I increase the Vector2 movement in a certain amount.
private void DashMovement() {
if (isDashing) {
movement.x *= dashFactor;
}
}
I'm also calculating the ground angle, so I set the movement vector to follow the ground inclination.
private void OnSlopeMovement() {
if (isGrounded && !isJumping) {
float moveDistance = Mathf.Abs(movement.x);
float horizontalOnSlope = Mathf.Cos(groundAngle * Mathf.Deg2Rad) * moveDistance * Mathf.Sign(movement.x);
float verticalOnSlope = Mathf.Sin(groundAngle * Mathf.Deg2Rad) * moveDistance;
if (horizontalOnSlope != 0)
movement.x = horizontalOnSlope;
if (isGrounded && verticalOnSlope != 0)
movement.y = verticalOnSlope;
}
SetMaxFallVelocity();
}
So I set the rigidbody velocity for making it move.
private void Move() {
movement.x *= Time.fixedDeltaTime;
if(isGrounded && !isJumping) movement.y *= Time.fixedDeltaTime;
Vector3 targetVelocity = new Vector2(movement.x, movement.y);
PlayerController.rb2d.velocity = Vector3.SmoothDamp(PlayerController.rb2d.velocity, targetVelocity, ref velocity, movementSmoothing);
}
The problem appears when I apply a speed high enough. I understand this issue is because of physics.
I think the ray that checks the ground and is used to calculate the groundAngle doesn't work fast enough to keep track of that movement, so I can not keep the player fixed on the ground.
I would like to find a solution without making the player kinematic, or stopping the dash on slopes.
This is how it looks ingame.
And this is how the rigidbody movement remain right over the ground, following the slopes angle.
EDIT:
This is how I get the ground angle:
private void GroundAngle() {
Vector2 rayOrigin = feetCollider.bounds.center;
rayOrigin.y += 0.1f;
Vector2 rayDirection = (Input.GetAxisRaw("Horizontal") == 0) ? Vector2.right : new Vector2(Input.GetAxisRaw("Horizontal"), 0);
int groundCollisions = Physics2D.RaycastNonAlloc(rayOrigin, Vector2.down, groundResults, Mathf.Infinity, groundMask);
if (groundCollisions > 0) {
groundAngle = Vector2.Angle(groundResults[0].normal, rayDirection) - 90f;
//Debug.DrawRay(rayOrigin, Vector2.down, Color.green);
if (groundAngle > 0 && !isDashing) {
rayOrigin.x += Input.GetAxisRaw("Horizontal") * .125f;
Physics2D.RaycastNonAlloc(rayOrigin, Vector2.down, groundResults, Mathf.Infinity, groundMask);
groundAngle = Vector2.Angle(groundResults[0].normal, rayDirection) - 90f;
//Debug.DrawRay(rayOrigin, Vector2.down, Color.blue);
}
}
}
Thanks to #Ruzhim for the help. I just post a first "solution" for the problem.
According to Ruzhim advises, I've used him code this way.
private void SetPositionAfterTick() {
if (isDashMovement) {
Vector2 currentPosition = new Vector2(transform.position.x, transform.position.y);
currentPosition.y = feetCollider.bounds.min.y;
Vector2 feetPosAfterTick = currentPosition + PlayerController.rb2d.velocity * Time.deltaTime;
float maxFloorCheckDist = .1f;
RaycastHit2D groundCheckAfterTick = Physics2D.Raycast(feetPosAfterTick + Vector2.up * maxFloorCheckDist, Vector2.down, maxFloorCheckDist * 5f);
if (groundCheckAfterTick) {
Vector2 wantedFeetPosAfterTick = groundCheckAfterTick.point;
if (wantedFeetPosAfterTick != feetPosAfterTick) {
//PlayerController.rb2d.transform.position = (wantedFeetPosAfterTick + new Vector2(0f, feetCollider.bounds.min.y - PlayerController.rb2d.position.y));
PlayerController.rb2d.velocity = Vector2.zero;
}
}
}
}
This is how it looks like.
This is good enough to continue polishing that mechanic. I still need to set the position in some way. The rigidbody's position calculation is not working as it
is raised right now, as the condition (wantedFeetPosAfterTick != feetPosAfterTick) is always true, so the character goes throw the floor and fall.
As you can see, I also need to control the down slopes movement, as it uses the slopes movement sometimes, and dash straight forward others.
This is how asker Rubzero implemented the below code to work for them:
private void SetPositionAfterTick() {
if (isDashMovement) {
Vector2 currentPosition = new Vector2(transform.position.x, transform.position.y);
currentPosition.y = feetCollider.bounds.min.y;
Vector2 feetPosAfterTick = currentPosition + PlayerController.rb2d.velocity * Time.deltaTime;
float maxFloorCheckDist = .1f;
RaycastHit2D groundCheckAfterTick = Physics2D.Raycast(feetPosAfterTick + Vector2.up * maxFloorCheckDist,
Vector2.down, maxFloorCheckDist * 5f);
if (groundCheckAfterTick) {
Vector2 wantedFeetPosAfterTick = groundCheckAfterTick.point;
if (wantedFeetPosAfterTick != feetPosAfterTick) {
//PlayerController.rb2d.transform.position = (wantedFeetPosAfterTick + new Vector2(0f, feetCollider.bounds.min.y -
PlayerController.rb2d.position.y));
PlayerController.rb2d.velocity = Vector2.zero;
}
}
}
}
This is how it looks like.
This is good enough to continue polishing that mechanic. I still need
to set the position in some way. The rigidbody's position calculation
is not working as it is raised right now, as the condition
(wantedFeetPosAfterTick != feetPosAfterTick) is always true, so the
character goes throw the floor and fall.
As you can see, I need to control the down slopes movement, as it uses
the slopes movement sometimes, and dash straight forward others.
I agree with AresCaelum; using physics to do slope movement is pretty much the opposite of what you want to be doing if you don't want to preserve momentum when you're done going up/down the slope. Specifically, your problem is here:
float moveDistance = Mathf.Abs(movement.x);
float horizontalOnSlope = Mathf.Cos(groundAngle * Mathf.Deg2Rad) * moveDistance * Mathf.Sign(movement.x);
float verticalOnSlope = Mathf.Sin(groundAngle * Mathf.Deg2Rad) * moveDistance;
This is a problem because the more the player moves horizontally in a frame, the more they will move vertically based on the slope of the ramp they are on. However, this assumption doesn't hold if they should only be traveling up the ramp during only part of the movement during the frame. So, you need a way to handle that situation.
One solution is to use a raycast from where the player would be then if it's above the floor, alter the vertical velocity so that it would place them at that floor's position instead.
First, determine if slope movement has occurred in a physics frame...
private bool slopeMovementOccurred = false;
void FixedUpdate() {
slopeMovementOccurred = false;
// ...
}
private void OnSlopeMovement() {
if (isGrounded && !isJumping) {
slopeMovementOccurred = true;
// ...
}
SetMaxFallVelocity();
}
... and if it has, determine where the player is going to be after the physics update. Then do a physics2d raycast from above that position (by some amount) downward (double the previous amount) to find where the player's position should be, and then change the rb2d.velocity such that it will place the player exactly at the height they should be at.
Assuming you can calculate some kind of Vector2 feetOffset that has the local position of the player's feet:
void FixedUpdate() {
// ...
StickToSlopeLanding();
}
void StickToSlopeLanding() {
if (slopeMovementOccurred) {
Vector2 curVelocity = PlayerController.rb2d.velocity;
Vector2 feetPosAfterTick = PlayerController.transform.position
+ PlayerController.feetOffset
+ curVelocity * Time.deltaTime;
float maxFloorCheckDist = 1.0f;
// determine where the player should "land" after this frame
RaycastHit2D groundCheckAfterTick = Physics2D.Raycast(
feetPosAfterTick + Vector2.up * maxFloorCheckDist,
-Vector2.up, maxFloorCheckDist * 2f);
if (groundCheckAfterTick.collider != null) {
Vector2 wantedFeetPosAfterTick = groundCheckAfterTick.point;
// if basic physics won't take them to landing position
if (wantedFeetPosAfterTick != feetPosAfterTick) {
Vector2 wantedVelocity = curVelocity
+ Vector2.up
* ((wantedFeetPosAfterTick.y - feetPosAfterTick.y)
/ Time.deltaTime);
// adjust velocity so that physics will take them to landing position
PlayerController.rb2d.velocity = wantedVelocity;
// optionally, set a flag so that next frame
// it knows the player should be grounded
}
}
}
}
Hopefully this gets you towards a solution that will work.
Note: you may need to also move the rigidbody so that it doesn't try to clip through the corner at the top of the ramp, and you can determine where to put the rigidbody using another raycast, setting the velocity from that point to be horizontal:
void StickToSlopeLanding() {
if (slopeMovementOccurred) {
Vector2 curVelocity = PlayerController.rb2d.velocity;
Vector2 feetPosAfterTick = PlayerController.transform.position
+ PlayerController.feetOffset
+ curVelocity * Time.deltaTime;
float maxFloorCheckDist = 1.0f;
// determine where the player should "land" after this frame
RaycastHit2D groundCheckAfterTick = Physics2D.Raycast(
feetPosAfterTick + Vector2.up * maxFloorCheckDist,
-Vector2.up, maxFloorCheckDist * 2f);
if (groundCheckAfterTick.collider != null) {
Vector2 wantedFeetPosAfterTick = groundCheckAfterTick.point;
// if basic physics won't take them to landing position
if (wantedFeetPosAfterTick != feetPosAfterTick) {
// look for corner of ramp+landing.
// Offsets ensure we don't raycast from inside/above it
float floorCheckOffsetHeight = 0.01f;
float floorCheckOffsetWidth = 0.5f;
RaycastHit2D rampCornerCheck = Physics2D.Raycast(
wantedFeetPosAfterTick
- floorCheckOffsetHeight * Vector2.up
- floorCheckOffsetWidth * Mathf.Sign(movement.x) * Vector2.right,
Mathf.Sign(movement.x) * Vector2.right);
if (rampCornerCheck.collider != null) {
// put feet at x=corner position
Vector2 cornerPos = Vector2(rampCornerCheck.point.x,
wantedFeetPosAfterTick.y);
PlayerController.rb2d.position = cornerPos
- PlayerController.feetOffset;
// adjust velocity so that physics will take them from corner
// to landing position
Vector2 wantedVelocity = (wantedFeetPosAfterTick - cornerPos)
/ Time.deltaTime;
PlayerController.rb2d.velocity = wantedVelocity;
// optionally, set a flag so that next frame
// it knows the player should be grounded
}
}
}
}
}

Child object rotation relative to parent

I've been trying to rotate my player's gun target along with the player. My player keeps shooting to right side even though he's facing left.
I've created a target called Firepoint, it's set to as a child Object of the player. I want it to change as the character changes it's direction.
Any help is appreciated.
Here's the code of the player.
public void Move()
{
float controlThrow = CrossPlatformInputManager.GetAxis("Horizontal");
Vector2 playerVelocity = new Vector2(controlThrow * runSpeed, myRigidBody.velocity.y);
myRigidBody.velocity = playerVelocity;
bool playerHasHorizontalSpeed = Mathf.Abs(myRigidBody.velocity.x) > Mathf.Epsilon;
myAnimator.SetBool("Walking", playerHasHorizontalSpeed);
}
public void Flipsprite()
{
bool playerhashorizontalspeed = Mathf.Abs(myRigidBody.velocity.x) > Mathf.Epsilon;
if (playerhashorizontalspeed)
{
transform.localScale = new Vector2(Mathf.Sign(myRigidBody.velocity.x), 1f);
transform.rotation = new Vector2(Mathf.Sign(firePoint.transform.localScale.x), 1f);
}
}
The problem here is that the rotation is not effected by scaling. Only the relative scales and positions.
Also why are you using > Mathf.Epsilon and not simply > 0. As far as I understand you only need to check if it is not 0 ... using Mathf.Epsilon is such a small difference that it actually doesn't matter.
public void Move()
{
float controlThrow = CrossPlatformInputManager.GetAxis("Horizontal");
Vector2 playerVelocity = new Vector2(controlThrow * runSpeed, myRigidBody.velocity.y);
myRigidBody.velocity = playerVelocity;
bool playerHasHorizontalSpeed = Mathf.Abs(myRigidBody.velocity.x) > 0;
myAnimator.SetBool("Walking", playerHasHorizontalSpeed);
}
// store the last direction
int direction;
public void Flipsprite()
{
bool playerhashorizontalspeed = Mathf.Abs(myRigidBody.velocity.x) > 0;
if (playerhashorizontalspeed)
{
// update the direction
direction = Mathf.Sign(myRigidBody.velocity.x);
transform.localScale = new Vector2(direction, 1f);
}
}
Then when you are shooting multiply the direction also with direction
private IEnumerator FireContinuously()
{
while (true)
{
GameObject laser = Instantiate(bullet, firePoint.position, firePoint.rotation);
laser.GetComponent<Rigidbody2D>().velocity = new Vector2(projectileSpeed * direction, 0);
yield return new WaitForSeconds(projectileFiringPeriod);
}
}
a small hint:
If you make the type of
public RigidBody2D bullet
and drag in the according prefab again than you don't need to use GetComponent but could directly use
var laser = Instantiate(bullet, firePoint.position, firePoint.rotation);
laser.velocity = ...

How to rotate an Object with touch input and stop it slowly after that in Unity?

I got some code from here:
https://answers.unity.com/questions/34317/rotate-object-with-mouse-cursor-that-slows-down-on.html
private float rotationSpeed = 10.0F;
private float lerpSpeed = 1.0F;
private Vector3 theSpeed;
private Vector3 avgSpeed;
private bool isDragging = false;
private Vector3 targetSpeedX;
void OnMouseDown() {
isDragging = true;
}
void Update() {
if (Input.GetMouseButton(0) && isDragging) {
theSpeed = new Vector3(-Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"), 0.0F);
avgSpeed = Vector3.Lerp(avgSpeed, theSpeed, Time.deltaTime * 5);
} else {
if (isDragging) {
theSpeed = avgSpeed;
isDragging = false;
}
float i = Time.deltaTime * lerpSpeed;
theSpeed = Vector3.Lerp(theSpeed, Vector3.zero, i);
}
transform.Rotate(Camera.main.transform.up * theSpeed.x * rotationSpeed, Space.World);
transform.Rotate(Camera.main.transform.right * theSpeed.y * rotationSpeed, Space.World);
}
This code rotates an object with mouse click and drag and after this click, the object stops slowly. I want this function now on mobile. This is my code for the mobile version:
// Update is called once per frame
public void Update() {
// Track a single touch as a direction control.
if (Input.touchCount > 0) {
Touch touch = Input.GetTouch(0);
// Handle finger movements based on touch phase.
switch (touch.phase) {
// Record initial touch position.
case TouchPhase.Began:
startPos = touch.position;
directionChosen = false;
break;
// Determine direction by comparing the current touch position with the initial one.
case TouchPhase.Moved:
direction = touch.position - startPos;
break;
// Report that a direction has been chosen when the finger is lifted.
case TouchPhase.Ended:
directionChosen = true;
stopSlowly = true;
Debug.Log("end");
break;
}
}
if (directionChosen) {
// Something that uses the chosen direction...
theSpeed = new Vector3(-direction.x, direction.y, 0.0F);
avgSpeed = Vector3.Lerp(avgSpeed, theSpeed, Time.deltaTime * 5);
} else {
if (stopSlowly) {
Debug.Log("TESTOUTPUT");
theSpeed = avgSpeed;
isDragging = false;
}
float i = Time.deltaTime * lerpSpeed;
theSpeed = Vector3.Lerp(theSpeed, Vector3.zero, i);
}
transform.Rotate(camera.transform.up * theSpeed.x * rotationSpeed, Space.World);
transform.Rotate(camera.transform.right * theSpeed.y * rotationSpeed, Space.World);
And here are some variables, I use Vector2 variables for startPos and direction:
private float rotationSpeed = 1f;
private float lerpSpeed = 1.0F;
private Vector3 theSpeed;
private Vector3 avgSpeed;
private bool isDragging = false;
private Vector3 targetSpeedX;
public Vector2 startPos;
public Vector2 direction;
public bool directionChosen;
public bool stopSlowly;
Now if I press play and rotate the Object on my phone, it rotates but it does not end on its own. It also rotates very fast. When I touched the Object one time, it stops immediately.
Please can someone say me what exactly is wrong with my code. My goal is just a rotation, initialized from touch input and an slow end until its stand still.
Thanks
I use some physics now to solve this problem:
// React on User Touch Input -> Rotate gameObject
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved) {
// Get movement of the finger since last frame
Vector2 touchDeltaPosition = Input.GetTouch(0).deltaPosition;
// Add Torque to gameObject
rb.AddTorque(camera.transform.up * -touchDeltaPosition.x/* * optionalForce*/);
rb.AddTorque(camera.transform.right * touchDeltaPosition.y/* * optionalForce*/);
} else if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Ended) {
// throw anker, stop rotating slowly
rb.angularDrag = 0.7f;
}
This code is for touch Input and rotates an object + stops it down slowly. You need an Rigidbody on your object which you want to rotate. Here its called rb. camera is my main Camera.
your condition is very confusing.
try something like this
// Handle finger movements based on touch phase.
switch (touch.phase) {
// Record initial touch position.
case TouchPhase.Began:
startPos = touch.position;
break;
// Determine direction by comparing the current touch position with the initial one.
case TouchPhase.Moved:
direction = touch.position - startPos;
isDragging = true;
break;
// Report that a direction has been chosen when the finger is lifted.
case TouchPhase.Ended:
isDragging = false;
stopSlowly = true;
Debug.Log("end");
break;
}
if (isDragging) {
// Something that uses the chosen direction...
theSpeed = new Vector3(-direction.x, direction.y, 0.0F);
avgSpeed = Vector3.Lerp(avgSpeed, theSpeed, Time.deltaTime * 5);
} else {
if(stopSlowly) {
Debug.Log("TESTOUTPUT");
theSpeed = avgSpeed;
stopSlowly = false;
}
float i = Time.deltaTime * lerpSpeed;
theSpeed = Vector3.Lerp(theSpeed, Vector3.zero, i);
}

Categories