# limiting rotation to solid angle

 0 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? 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 . more ▼ asked Nov 01 '10 at 01:49 PM LeiterJakab 87 ● 3 ● 3 ● 12 add new comment (comments are locked) 10|3000 characters needed characters left ▼ Viewable by all users

 0 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); } `````` more ▼ answered Nov 03 '10 at 11:00 PM Atnas1010 1.1k ● 6 ● 10 ● 26 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? Nov 04 '10 at 10:51 AM LeiterJakab 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. Nov 04 '10 at 10:56 AM LeiterJakab 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 Nov 04 '10 at 12:32 PM Atnas1010 Thanks a lot very nice script. Nov 04 '10 at 07:20 PM LeiterJakab add new comment (comments are locked) 10|3000 characters needed characters left ▼ Viewable by all users
 0 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); } `````` more ▼ answered Nov 03 '10 at 09:29 PM LeiterJakab 87 ● 3 ● 3 ● 12 I'll have a look at it. Is this exactly how you want it to behave in the end? And radius gets inverted somewhere..? Nov 03 '10 at 09:57 PM Atnas1010 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? Nov 03 '10 at 10:19 PM Atnas1010 At first I used the limitRadius var, to check if currentRadius was bigger than this and I used it in the ClampMagnitude function to limit the movement to a circle area. Basically similar to what IJM 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. Nov 03 '10 at 10:37 PM LeiterJakab add new comment (comments are locked) 10|3000 characters needed characters left ▼ Viewable by all users
 0 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. more ▼ answered Nov 01 '10 at 02:00 PM IJM 1.4k ● 2 ● 5 ● 19 I can't try it right now, but doesn't this limit the rotation to +/-60 degrees around the 'x' axis? Nov 01 '10 at 04:14 PM LeiterJakab Yes, for the GameObjects local x axis. (Just try it) Nov 01 '10 at 06:44 PM IJM Sorry if my question wasn't clear enough, I've edited it. Nov 01 '10 at 10:52 PM LeiterJakab add new comment (comments are locked) 10|3000 characters needed characters left ▼ Viewable by all users
 0 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. more ▼ answered Dec 04 '12 at 10:32 PM add new comment (comments are locked) 10|3000 characters needed characters left ▼ Viewable by all users
 0 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 more ▼ answered Nov 24 '10 at 04:03 PM Quu 1 add new comment (comments are locked) 10|3000 characters needed characters left ▼ Viewable by all users

By Email:

Topics:

x2163
x322
x286
x133
x28

asked: Nov 01 '10 at 01:49 PM

Seen: 3001 times

Last Updated: Dec 04 '12 at 10:32 PM