Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 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
3
Question by LeiterJakab · Nov 01, 2010 at 01:49 PM · rotationaxisanglelimitsolid

limiting rotation to solid angle

I have a Gun in my scene and I would like to limit its rotation, but not around two axes like the mouselook script does. Instead I'd like to limit it to a solid angle around a single axis. I'm working on a solution right now, but it seems to be way too complicated.

Does anyone know a simple reliable method for this?

alt text

would be the maximal allowed rotatin.

Edit: The object should be able to rotate around its pivot point, or the zero point of its local coordinate system, but its rotation in all the directions of its local xy plane should be limited to .

Comment
Add comment
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

5 Replies

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

Answer by Atnas1010 · Nov 03, 2010 at 11:00 PM

Made something that should act like the old code, but run faster, and use less code. You might also want to do a raycast where you set the target variable and find the actualdistance, instead of using 20.

Feel free to change the way limit is calculated back to your way. I just like that when limitRadius is larger, the circle is larger.

var crosshairTex : Texture2D; var sensitivity : float; var limitRadius : float;

private var limit : float; private var origo = Vector2(Screen.width / 2, Screen.height / 2); private var currentPoint = Vector2.zero; private var oldPoint = Vector2.zero; private var particleGun : Transform; private var crosshairPos : Rect; private var target : Vector3;

function Start () { particleGun = GameObject.Find("ParticleGun").transform; crosshairPos = Rect(origo.x - (crosshairTex.width / 2), (origo.y - (crosshairTex.height / 2)), crosshairTex.width, crosshairTex.height); limit = Screen.width * limitRadius; }

function Update () { oldPoint = currentPoint; currentPoint.x += Input.GetAxis ("Mouse X") sensitivity; currentPoint.y += Input.GetAxis ("Mouse Y") sensitivity; currentPoint = Vector2.ClampMagnitude(currentPoint, limit); crosshairPos.x += currentPoint.x-oldPoint.x; crosshairPos.y -= currentPoint.y-oldPoint.y;

 target = camera.ScreenToWorldPoint (Vector3(currentPoint.x+origo.x, currentPoint.y+origo.y, 20.0));
 particleGun.LookAt(target, transform.up);

}

function OnGUI () { GUI.DrawTexture (crosshairPos, crosshairTex); }

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 LeiterJakab · Nov 04, 2010 at 10:51 AM 0
Share

You basically limit movement around the (0, 0) scrren coordinates and than move the ponit to the coordinate system with the screen center as its zero point by additions and substractions, right?

avatar image LeiterJakab · Nov 04, 2010 at 10:56 AM 0
Share

origo = Vector2(Screen.width / 2, Screen.height / 2); limit = Screen.width * limitRadius; These lines should be in Update so that changing the resolution wouldn't effect the radius and center of the limt area.

avatar image Atnas1010 · Nov 04, 2010 at 12:32 PM 0
Share

I just tried to make the code run as fast as possible. I didn't think that that the user might fullscreen the game some time, so feel free to move them back to update(and I moved all the code to update because it gets called less frequently than OnGUI). And yes, that is basically what I do

avatar image LeiterJakab · Nov 04, 2010 at 07:20 PM 0
Share

Thanks a lot very nice script.

avatar image
0
Best Answer

Answer by LeiterJakab · Nov 03, 2010 at 09:29 PM

Well this is how I solved this problem. Since I needed a crosshair for the gun in my scene anyway, I just control the crosshair GUI instead of the gun. I limited its movement to a circle around the center of the screen, converted screen coordinates to world coordinates and used the transform.LookAt function to turn the gun towards that point.

There must be a better way to do it, or maybe there isn't. I'm still interested in ideas.

var crosshairTex : Texture2D; var sensitivity : float; var limitRadius : float;

private var limit : float; private var origo : Vector3; private var targetCenter : Vector3; private var crosshairPos : Rect; private var start : boolean = true;

function Start () { targetCenter = Vector3(Screen.width / 2, Screen.height / 2, 0); }

function Update () { target = camera.ScreenToWorldPoint (Vector3(targetCenter.x, targetCenter.y, 20.0)); GameObject.Find ("ParticleGun").transform.LookAt (target, transform.up); }

function OnGUI () { origo = Vector3(Screen.width / 2, Screen.height / 2, 0); limit = Screen.width / limitRadius;

 targetCenter.x += Input.GetAxis ("Mouse X") * sensitivity;
 targetCenter.y += Input.GetAxis ("Mouse Y") * sensitivity;

 var currentRadius = targetCenter - origo;

 if (currentRadius.sqrMagnitude > Mathf.Pow (limit, 2))
 {
     currentRadius = Vector3.ClampMagnitude (currentRadius, limit);
     targetCenter.x = origo.x + currentRadius.x;
     targetCenter.y = origo.y + currentRadius.y;
 }

 crosshairPos = Rect(targetCenter.x - (crosshairTex.width / 2), Screen.height - (targetCenter.y + (crosshairTex.height / 2)), crosshairTex.width, crosshairTex.height);

 GUI.DrawTexture (crosshairPos, crosshairTex);

}

Comment
Add comment · Show 3 · 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 Atnas1010 · Nov 03, 2010 at 09:57 PM 0
Share

I'll have a look at it. Is this exactly how you want it to behave in the end? And radius gets inverted somewhere..?

avatar image Atnas1010 · Nov 03, 2010 at 10:19 PM 0
Share

Or would you like the user to be able to move his mouse outside the circle, and then have to move it all the way back before the crosshair would leave the edge of the circle?

avatar image LeiterJakab · Nov 03, 2010 at 10:37 PM 0
Share

At first I used the limitRadius var, to check if currentRadius was bigger than this and I used it in the Clamp$$anonymous$$agnitude function to limit the movement to a circle area. Basically similar to what IJ$$anonymous$$ did so thanks for that idea. However I noticed that this would result in different movement angles with different resolutions. Thats why I used the line: limit = Screen.width / limitRadius; This way entering 2 will always result in the limit radius being half the screen width.

avatar image
0

Answer by IJM · Nov 01, 2010 at 02:00 PM

I think that this will work:

Vector3 CurRotation = transform.rotation.eulerAngles;

if(CurRotation.x > 60)//this will limit looking up to 60 transform.rotation = Quaternion.Euler(new Vector3(60,CurRotation.y,CurRotation.z)); else if(CurRotation.x < -60)//this will limit looking down to -60 transform.rotation = Quaternion.Euler(new Vector3(-60,CurRotation.y,CurRotation.z));

p.s.

I din't test this code.

p.p.s.

Yes it works ;) I just made a small test.

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 LeiterJakab · Nov 01, 2010 at 04:14 PM 0
Share

I can't try it right now, but doesn't this limit the rotation to +/-60 degrees around the 'x' axis?

avatar image IJM · Nov 01, 2010 at 06:44 PM 0
Share

Yes, for the GameObjects local x axis. (Just try it)

avatar image LeiterJakab · Nov 01, 2010 at 10:52 PM 0
Share

Sorry if my question wasn't clear enough, I've edited it.

avatar image Invertex · Sep 18, 2017 at 01:31 AM 0
Share

Super old post, but others might come across it like I did... I'm not sure how that's supposed to work unless something has changed in Unity since then. rotation.eulerAngles does not return negative values, they only look negative in the Inspector when you're modifying it by hand, but internally the negative value is simply being subtracted from 360 to wrap the value back around the 360 degrees to keep it a positive number.

What's really happening with your code is that the first condition is always going to be triggered if either the rotation is above 60, or has rotated below 0, in which case it would become 360 or less and again trigger the > 60 condition. So your true rotation lock range would become only 60, not 120, and going below 0 would pop your rotation back to the other side of the limit at a rotation of 60...

This type of solution can only work properly if your restricted range is kept within a positive value range between 0-360.

avatar image
0

Answer by Quu.du · Nov 24, 2010 at 04:03 PM

This worked well for me:

void Update () {
    float ang = Time.deltaTime * speed * Input.GetAxis("Horizontal");
    myTransform.RotateAround(myCamera.ScreenToWorldPoint(new Vector3(Screen.width * 0.5f, Screen.height * 0.5f, myCamera.nearClipPlane)), -myTransform.right, ang);
}

Note: In my case, -myTransform.right is the vector that faces the camera

Comment
Add comment · 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
0

Answer by rhgrant10 · Dec 04, 2012 at 10:32 PM

I just wrote this little ditty the other night. According to the diagram in your post, and if my understanding (that you want to limit the angle of deviation from a single axis/vector) is correct, this script should prove useful for you.

 using UnityEngine;
 using System.Collections;
 
 /**
  * ConeMouseLook.cs
  * 
  * Restricts the basic mouse look script to keep the view within a cone.  The cone 
  * is defined by the maxAngle and the rotation at the moment the look is frozen, 
  * unless one of the overloaded Restrict methods is used instead of the no-argument 
  * Restrict method.
  * 
  * Author: Robert Grant
  * Version: 11/22/2012
  */
 public class ConeMouseLook : MonoBehaviour {
     public float maxAngle = 45.0f;        // maximum deviation
     public float xSensitivity = 1.0f;    // horizontal sensitivity
     public float ySensitivity = -1.0f;    // vertical sensitivity
     
     private Quaternion baseRotation;
     private bool isRestricted;
     private Quaternion requestedRotation;
     
     void Start () {
         isRestricted = true;
         baseRotation = transform.rotation;
         requestedRotation = Quaternion.identity;
         if (rigidbody) {
             rigidbody.freezeRotation = true;
         }
     }
     
     void LateUpdate() {
         if (Time.timeScale != 0.0f) {
             // Save for correcting the roll later.
             float z = transform.localEulerAngles.z;
             
             // Find the requested rotation - we may not use it or all of it.
             requestedRotation = Quaternion.Euler(
                     Input.GetAxis("Mouse Y") * ySensitivity, 
                     Input.GetAxis("Mouse X") * xSensitivity, 
                     0
                 );
             float requestedAngle = Quaternion.Angle(
                     baseRotation, 
                     transform.rotation * requestedRotation
                 );
             
             // Do the rotation.
             if (isRestricted && requestedAngle > maxAngle) {
                 // Limit the rotation since too much was requested.
                 transform.rotation = Quaternion.RotateTowards(
                         transform.rotation * requestedRotation, 
                         baseRotation, 
                         requestedAngle - maxAngle
                     );
             } else {
                 // Just rotate freely!
                 transform.rotation = Quaternion.Slerp(
                         transform.rotation, 
                         transform.rotation * requestedRotation, 
                         .25f
                     );
             }
             
             // Correct any un-wanted roll.
             Vector3 angles = transform.localEulerAngles; 
             angles.z = z;
             transform.localEulerAngles = angles;
         }
     }
     
     /**
      *     Restricts the rotation to at most maxAngle degrees from the current rotation.
      */
     public void Restrict(float maxAngle) {
         this.maxAngle = maxAngle;
         isRestricted = true;
         baseRotation = transform.rotation;
     }
     
     /**
      *     Restricts the rotation to at most maxAngle degrees from the given direction.
      */
     public void Restrict(Vector3 direction, float maxAngle) {
         this.maxAngle = maxAngle;
         baseRotation = Quaternion.LookRotation(direction, Vector3.up);
         isRestricted = true;
     }
     
     /**
      *     Restricts the rotation relative to the given direction using the current maxAngle.
      */
     public void Restrict(Vector3 direction) {
         baseRotation = Quaternion.LookRotation(direction, Vector3.up);
         isRestricted = true;
     }
     
     /**
      *     Restricts the rotation using the current rotation and maxAngle.
      */
     public void Restrict() {
         baseRotation = transform.rotation;
         isRestricted = true;
     }
     
     /**
      *     Frees the rotation entirely.
      */
     public void Free() {
         isRestricted = false;
     }
 }

The rotation is restricted on Start(), so you might want to change that.

Comment
Add comment · 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

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

2 People are following this question.

avatar image avatar image

Related Questions

90 Degree stopping rotation on y-axis issue 0 Answers

Set angle of object around arbitrary axis by slider? 1 Answer

Problem with Clamping Values for Object's Rotation 1 Answer

2D : Rotation of Object With x-y Axis 2 Answers

Interpolate a rotation with angle axis 1 Answer


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