Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by S_Byrnes · Jan 11, 2016 at 10:51 AM · rotationjavascriptinputtouchdegrees

2D Rotation Lerp Back To 0 Degrees, Please Help

Hi all, I'm working on making a 2D platformer game that has a shooting element. What I have is a script that gets the touch input and rotates the gun towards the touch location.

What I need to do is have it always try to move back to 0 degrees gradually. I've tried a Lerp but I couldn't get it to work correctly.

Here is what I have:

 for (var touch: Touch in Input.touches) {
 
     mouse_pos = Input.mousePosition;
     if (touch.position.x > Screen.width / 2){
         mouse_pos = Input.touches[0].position;
         mouse_pos.z = 5.23; //The distance between the camera and object
         object_pos = Camera.main.WorldToScreenPoint(target.position);
         mouse_pos.x = mouse_pos.x - object_pos.x;
         mouse_pos.y = mouse_pos.y - object_pos.y;
         angle = Mathf.Atan2(mouse_pos.y, mouse_pos.x) * Mathf.Rad2Deg;
         angle = Mathf.Clamp(angle, -22, 40);
         transform.rotation = Quaternion.Euler(Vector3(0, 0, angle));
         }
     }

So if you know how I might achieve this I'd greatly appreciate all suggestions or solutions, thank you very much!

Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image S_Byrnes · Jan 13, 2016 at 05:54 AM 0
Share

Alright so I've got it half working. But now whenever I try to shoot below 0 degrees, it does a full 360 spin around to get back to 0 ins$$anonymous$$d of going back the way it came.

Here's what I have now, any sugestions?:

  for (var touch: Touch in Input.touches) {
 
     if (touch.position.x > Screen.width / 2){
         mouse_pos = Input.touches[0].position;
         mouse_pos = Input.mousePosition;
 
             mouse_pos.z = 5.23; //The distance between the camera and object
             object_pos = Camera.main.WorldToScreenPoint(target.position);
             mouse_pos.x = mouse_pos.x - object_pos.x;
             mouse_pos.y = mouse_pos.y - object_pos.y;
             angle = $$anonymous$$athf.Atan2(mouse_pos.y, mouse_pos.x) * $$anonymous$$athf.Rad2Deg;
             angle = $$anonymous$$athf.Clamp(angle, -22, 40);
             transform.rotation = Quaternion.Euler(0f, 0f, $$anonymous$$athf.Lerp(transform.rotation.eulerAngles.z, angle, Time.deltaTime * 80f));
         }
     }
 
 if (angle > 0){
     angle = 0;
 }
 
 if (angle < 0){
     angle = 0;
 }
 
 transform.rotation = Quaternion.Euler(0f, 0f, $$anonymous$$athf.Lerp(transform.rotation.eulerAngles.z, angle, Time.deltaTime * 6f));
 }
 

2 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by ZefanS · Jan 13, 2016 at 08:42 AM

Basically, the gun rotates back the almost-360-degree way because it's lerping the angle positively only. What you need to do is check where the player is aiming and then pick the closest direction to rotate back to 0 degrees.

alt text If the player is aiming in quadrants 1 or 2, then you can lerp back to 0 the way you already are.

If the player is aiming in quadrants 3 or 4, then you want to rotate the other way (just multiply Time.deltaTime by -6f instead of 6f).

A simple way to check which quadrant the the player is aiming in is to subtract the x and y coordinates of the touch point from the x and y coordinates of the player's location. The signs of the results will indicate the quadrant:

  • Both positive: 1

  • Negative x, positive y: 2

  • Both negative: 3

  • Positive x, negative y: 4

As a side note, this code always makes angle zero, so it's a bit redundant:

  if (angle > 0){
      angle = 0;
  }
  
  if (angle < 0){
      angle = 0;
  }

You could just replace it with:

 angle = 0;

Right now it looks like you lerp back towards zero whether or not you are detecting any touches. It seems to me like you should add some logic to check and only lerp towards zero when the user isn't touching the screen.

Okay, so here's an implementation that differs slightly from the description above by using Transform.RotateAround() to achieve the rotation and the cross product to calculate which direction to rotate.

 #pragma strict
 
 public var mainCamera : Camera;
 
 public var playerTransform : Transform;
 
 //The default position relative to the player
 public var defaultPosition : Vector3;
 
 public var rotationSpeed : float;
 public var threshold : float;
 
 private var mouse_pos : Vector3;
 private var object_pos : Vector3;
 private var angle : float;
 
 private var dir : int;
 
 private var xVector : Vector3 = Vector3(1.0f, 0.0f, 0.0f);
 private var zVector : Vector3 = Vector3(0.0f, 0.0f, 1.0f);
 
 function Update()
 {
     Rotate();
 }
 
 function Rotate()
 {
     //Calculate the position of the rotating object relative to the player
     object_pos = transform.position;
     object_pos.x = object_pos.x - playerTransform.position.x;
     object_pos.y = object_pos.y - playerTransform.position.y;
     object_pos.z = 0.0f;
 
     if (Input.GetMouseButton(0))
     {
         //Calculate the position of the mouse cursor relative to the player
         mouse_pos = Input.mousePosition;
         mouse_pos = mainCamera.ScreenToWorldPoint(mouse_pos);
         mouse_pos.x = mouse_pos.x - playerTransform.position.x;
         mouse_pos.y = mouse_pos.y - playerTransform.position.y;
         mouse_pos.z = 0.0f;
         
         //Calculate the rotation direction and perform the rotation
         dir = CalculateRotationDirection(object_pos, mouse_pos);
         transform.RotateAround(playerTransform.position, zVector, Time.deltaTime * rotationSpeed * dir);
     }
     else
     {
         //Calculate the rotation direction and rotate towards the default position
         dir = CalculateRotationDirection(object_pos, xVector);
         if (dir != 0)
         {
             transform.RotateAround(playerTransform.position, zVector, Time.deltaTime * rotationSpeed * dir);
         }
         else
         {
             transform.position = playerTransform.position + defaultPosition;
         }
     }
 }
 
 function CalculateRotationDirection(currentPoint : Vector3, targetPoint : Vector3)
 {    
     //Initialize some vectors
     var currentVector : Vector3 = Vector3.zero;
     var targetVector : Vector3 = Vector3.zero;
     
     //Handle scenarios where the cross product is equal to zero.
     if (Vector3.Angle(currentPoint, targetPoint) < threshold && Vector3.Angle(currentPoint, targetPoint) > -threshold)
     {
         return 0;
     }
     else if (Vector3.Angle(currentPoint, targetPoint) == 180)
     {
         return 1;
     }
     
     //Calculate the cross product - this tells us the relation between the vectors
     var cross = Vector3.Cross(currentPoint, targetPoint);
     
     //Return the direction multiplier based on the cross product
     if (cross.z > 0.0f)
     {
         return 1;
     }
     else
     {
         return -1;
     }
 }

This should now work using sprites in 2D with an arbitrary player position.

alt text

Hope this help!


setup2.png (53.2 kB)
quadrants.png (6.1 kB)
Comment
Add comment · Show 22 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image ZefanS · Jan 13, 2016 at 08:49 AM 0
Share

To follow up, I'm not sure if this technique would work with $$anonymous$$athf.lerp. It might make sense for you to look into Transform.Rotate() or Transform.RotateAround(), which is how I would normally go about such a problem.

avatar image S_Byrnes · Jan 13, 2016 at 08:51 AM 0
Share

Thank you for the comment, I really appreciate it!

I understand what you're saying conceptually, but I'm not entirely sure how to go about it code-wise.

Could you expand on this for me please?

avatar image ZefanS S_Byrnes · Jan 13, 2016 at 08:58 AM 0
Share

Sure, just taking a crack now.

avatar image S_Byrnes ZefanS · Jan 13, 2016 at 09:04 AM 0
Share

Okay thank you very much!

Show more comments
avatar image ZefanS S_Byrnes · Jan 14, 2016 at 02:36 AM 0
Share

It's definitely more complicated than I thought at first. Note this script makes some assumptions that will only work with the test setup I described, so it will need to be modified to handle a moving player.

avatar image S_Byrnes ZefanS · Jan 14, 2016 at 02:47 AM 0
Share

Thanks, that's alright, no wonder I got stuck then if you had a hard time with it. And the player can't exactly move except for jumping since the background will be scrolling.

I have considered using LerpAngle with my previous script, but can't work out how to do it, this is what I tried earlier:

 function Update ()
 {
     for (var touch: Touch in Input.touches) {
  
      mouse_pos = Input.mousePosition;
      if (touch.position.x > Screen.width / 2){
          mouse_pos = Input.touches[0].position;
          //mouse_pos.z = 5.23; //The distance between the camera and object
          object_pos = Camera.main.WorldToScreenPoint(target.position);
          angle = $$anonymous$$athf.Atan2(mouse_pos.y, mouse_pos.x) * $$anonymous$$athf.Rad2Deg;
          angle = $$anonymous$$athf.Clamp(angle, -22, 40);
          angle = $$anonymous$$athf.LerpAngle(-22, 40, Time.deltaTime);
          transform.eulerAngles = Vector3(0, 0, angle);
          //transform.rotation = Quaternion.Euler(0f, 0f, $$anonymous$$athf.Lerp(transform.rotation.eulerAngles.z, angle, Time.deltaTime * 80f));
          //transform.rotation = Quaternion.Euler(Vector3(0, 0, angle));
     }
 }
 
 angle = $$anonymous$$athf.LerpAngle(0, 0, Time.deltaTime);
 transform.eulerAngles = Vector3(0, 0, angle);
 
 }

It doesn't move at all right now for some reason.

Show more comments
Show more comments
avatar image ZefanS S_Byrnes · Jan 14, 2016 at 02:53 AM 0
Share

That probably explains the problem. I'm working on a fix now.

avatar image S_Byrnes ZefanS · Jan 14, 2016 at 03:16 AM 0
Share

Alright thanks, again I'm sorry this is so hard, I'm amazed there isn't some simple solution to it.

If there is I'm blind.

Show more comments
avatar image
1

Answer by hulahoolgames · Jan 13, 2016 at 08:31 AM

I think the problem might be in using Mathf.Lerp to lerp the angle. Say the current z value is 270 deg and you want it to go to 0 deg. Mathf.Lerp will do a linear interpolation from 270 to 0 and will return all the intermediate values. It does not know you are interpolating on angles. So instead try the following:

 Quaternion defaultRot = Quaternion.Euler(0.0f, 0.0f, 0.0f);    
 transform.rotation = Quaternion.Lerp(transform.rotation, defaultRot, Time.deltaTime * 6f);

I would suggest saving the default rotation as a quaternion and Lerp from current rotation to default using Quaternion.Lerp. Hope this fixes the issue.

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image S_Byrnes · Jan 13, 2016 at 08:39 AM 0
Share

Hey thanks a lot for the suggestion!

So if I understand you correctly, you're saying to remove my if (angle < 0) stuff and add the defaultRot Quaternion ins$$anonymous$$d?

avatar image hulahoolgames S_Byrnes · Jan 13, 2016 at 08:49 AM 0
Share

I dont know what was the intention of the if(angle < 0) check, since you anyways enforce the angle to be 0. You need to change transform.rotation = Quaternion.Euler(0f, 0f, $$anonymous$$athf.Lerp(transform.rotation.eulerAngles.z, angle, Time.deltaTime * 6f)); to transform.rotation = Quaternion.Lerp(transform.rotation, m_targetRot, Time.deltaTime * 6f);. Now m_targetRot can be defaultRot that i have shown in the example or any target rotation in Quaternion form you want to move towards. Just make sure you represent the target as a Quaternion and use Quaternion.Lerp to move towards the target.

avatar image hulahoolgames hulahoolgames · Jan 13, 2016 at 08:56 AM 0
Share

Just to be more clear here is what i am suggesting. Pardon me for using C#, I am not very good with Javascript:`for (var touch: Touch in Input.touches) {mouse_pos = Input.touches[0].position;mouse_pos.x = mouse_pos.x - object_pos.x;Quaternion target =Quaternion.Euler(0.0f, 0.0f, angle);transform.rotation = Quaternion.Lerp(transform.rotation, target, Time.deltaTime 80f);}}Quaternion default = Quaternion.Euler(0.0f, 0.0f, 0.0f);transform.rotation = Quaternion.Lerp(transform.rotation, default, Time.deltaTime 6f);}`

Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

46 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Get touch position? 0 Answers

Rotate player to LookAt a touch position 2 Answers

How to rotate object 180 degrees smoothly 2 Answers

How can ı rotate camera with touch? 5 Answers

Rotate 2D Texture negative positive degrees touch 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges