Clapming rotation of child objects in unity
I have a game object that contains another game object that should be able to rotate towards target (imagine a tank turret). And so I've created the below script:
public class Rotator : MonoBehaviour
public GameObject _enemy;
void Update ()
var actualTarget = _enemy.transform.position;
var targetDir = actualTarget - transform.position;
var step = 2 * Time.deltaTime;
var target = Quaternion.LookRotation(targetDir.normalized, Vector3.up);
var actual = target * Quaternion.Inverse(transform.parent.rotation);
var targetRotation = Quaternion.Slerp(transform.localRotation, actual, step);
targetRotation.eulerAngles = ClampRotation(targetRotation.eulerAngles);
transform.localRotation = targetRotation;
private static Vector3 ClampRotation(Vector3 eulerAngles)
var x = Mathf.Clamp(eulerAngles.x > 180 ? eulerAngles.x - 360 : eulerAngles.x, -180, 180);
var y = Mathf.Clamp(eulerAngles.y > 180 ? eulerAngles.y - 360 : eulerAngles.y, -45, 45);
return new Vector3(x, y, 0);
Objects setup:
The rotation of the object named "parent" is 90deg on the Y axis, everything else is not rotated.
Clamping on the y axis works well - the rotation stays between -45 and 45 degrees. The rotation however doesn't work on the x axis (with, or without clamping).
So the goal here is that when I move the cube left or right, the red one rotates between [-45,45] degrees around the Y axis and when I move it top or down, the red one rotates between [-180,180] degrees around the X axis.
I had some success using the LookAt
method of the Transform
clas, but for some reason if I try to manually modify eulerAngles
of a localRotation
it suddenly looses the possibility to rotate backwards on the X axis even though I'm only doing something to the Y values...
c# unity3d math quaternions
add a comment |
I have a game object that contains another game object that should be able to rotate towards target (imagine a tank turret). And so I've created the below script:
public class Rotator : MonoBehaviour
public GameObject _enemy;
void Update ()
var actualTarget = _enemy.transform.position;
var targetDir = actualTarget - transform.position;
var step = 2 * Time.deltaTime;
var target = Quaternion.LookRotation(targetDir.normalized, Vector3.up);
var actual = target * Quaternion.Inverse(transform.parent.rotation);
var targetRotation = Quaternion.Slerp(transform.localRotation, actual, step);
targetRotation.eulerAngles = ClampRotation(targetRotation.eulerAngles);
transform.localRotation = targetRotation;
private static Vector3 ClampRotation(Vector3 eulerAngles)
var x = Mathf.Clamp(eulerAngles.x > 180 ? eulerAngles.x - 360 : eulerAngles.x, -180, 180);
var y = Mathf.Clamp(eulerAngles.y > 180 ? eulerAngles.y - 360 : eulerAngles.y, -45, 45);
return new Vector3(x, y, 0);
Objects setup:
The rotation of the object named "parent" is 90deg on the Y axis, everything else is not rotated.
Clamping on the y axis works well - the rotation stays between -45 and 45 degrees. The rotation however doesn't work on the x axis (with, or without clamping).
So the goal here is that when I move the cube left or right, the red one rotates between [-45,45] degrees around the Y axis and when I move it top or down, the red one rotates between [-180,180] degrees around the X axis.
I had some success using the LookAt
method of the Transform
clas, but for some reason if I try to manually modify eulerAngles
of a localRotation
it suddenly looses the possibility to rotate backwards on the X axis even though I'm only doing something to the Y values...
c# unity3d math quaternions
I think there is no answer yet because people are not clear on what the problem is. You say it rotates but what's the problem now? Any animated gif to show what's going on now and what you expect?
– Programmer
Nov 11 at 16:45
Is it clearer now?
– Marek M.
Nov 11 at 17:31
Yes, it doesn't move up. You also want to be able to add rotation limit for both axis?
– Programmer
Nov 11 at 17:32
If by moving up you mean that the red guy is not pointing at the moving cube when it moves up/down, then yes - that's the problem. And again - yes - I want to add rotation limit for X and Y axis. The Z one I'm just setting to 0, as I don't want it to be influenced at all.
– Marek M.
Nov 11 at 17:36
add a comment |
I have a game object that contains another game object that should be able to rotate towards target (imagine a tank turret). And so I've created the below script:
public class Rotator : MonoBehaviour
public GameObject _enemy;
void Update ()
var actualTarget = _enemy.transform.position;
var targetDir = actualTarget - transform.position;
var step = 2 * Time.deltaTime;
var target = Quaternion.LookRotation(targetDir.normalized, Vector3.up);
var actual = target * Quaternion.Inverse(transform.parent.rotation);
var targetRotation = Quaternion.Slerp(transform.localRotation, actual, step);
targetRotation.eulerAngles = ClampRotation(targetRotation.eulerAngles);
transform.localRotation = targetRotation;
private static Vector3 ClampRotation(Vector3 eulerAngles)
var x = Mathf.Clamp(eulerAngles.x > 180 ? eulerAngles.x - 360 : eulerAngles.x, -180, 180);
var y = Mathf.Clamp(eulerAngles.y > 180 ? eulerAngles.y - 360 : eulerAngles.y, -45, 45);
return new Vector3(x, y, 0);
Objects setup:
The rotation of the object named "parent" is 90deg on the Y axis, everything else is not rotated.
Clamping on the y axis works well - the rotation stays between -45 and 45 degrees. The rotation however doesn't work on the x axis (with, or without clamping).
So the goal here is that when I move the cube left or right, the red one rotates between [-45,45] degrees around the Y axis and when I move it top or down, the red one rotates between [-180,180] degrees around the X axis.
I had some success using the LookAt
method of the Transform
clas, but for some reason if I try to manually modify eulerAngles
of a localRotation
it suddenly looses the possibility to rotate backwards on the X axis even though I'm only doing something to the Y values...
c# unity3d math quaternions
I have a game object that contains another game object that should be able to rotate towards target (imagine a tank turret). And so I've created the below script:
public class Rotator : MonoBehaviour
public GameObject _enemy;
void Update ()
var actualTarget = _enemy.transform.position;
var targetDir = actualTarget - transform.position;
var step = 2 * Time.deltaTime;
var target = Quaternion.LookRotation(targetDir.normalized, Vector3.up);
var actual = target * Quaternion.Inverse(transform.parent.rotation);
var targetRotation = Quaternion.Slerp(transform.localRotation, actual, step);
targetRotation.eulerAngles = ClampRotation(targetRotation.eulerAngles);
transform.localRotation = targetRotation;
private static Vector3 ClampRotation(Vector3 eulerAngles)
var x = Mathf.Clamp(eulerAngles.x > 180 ? eulerAngles.x - 360 : eulerAngles.x, -180, 180);
var y = Mathf.Clamp(eulerAngles.y > 180 ? eulerAngles.y - 360 : eulerAngles.y, -45, 45);
return new Vector3(x, y, 0);
Objects setup:
The rotation of the object named "parent" is 90deg on the Y axis, everything else is not rotated.
Clamping on the y axis works well - the rotation stays between -45 and 45 degrees. The rotation however doesn't work on the x axis (with, or without clamping).
So the goal here is that when I move the cube left or right, the red one rotates between [-45,45] degrees around the Y axis and when I move it top or down, the red one rotates between [-180,180] degrees around the X axis.
I had some success using the LookAt
method of the Transform
clas, but for some reason if I try to manually modify eulerAngles
of a localRotation
it suddenly looses the possibility to rotate backwards on the X axis even though I'm only doing something to the Y values...
c# unity3d math quaternions
c# unity3d math quaternions
edited Nov 14 at 19:41
asked Nov 11 at 10:10
Marek M.
1,60832557
1,60832557
I think there is no answer yet because people are not clear on what the problem is. You say it rotates but what's the problem now? Any animated gif to show what's going on now and what you expect?
– Programmer
Nov 11 at 16:45
Is it clearer now?
– Marek M.
Nov 11 at 17:31
Yes, it doesn't move up. You also want to be able to add rotation limit for both axis?
– Programmer
Nov 11 at 17:32
If by moving up you mean that the red guy is not pointing at the moving cube when it moves up/down, then yes - that's the problem. And again - yes - I want to add rotation limit for X and Y axis. The Z one I'm just setting to 0, as I don't want it to be influenced at all.
– Marek M.
Nov 11 at 17:36
add a comment |
I think there is no answer yet because people are not clear on what the problem is. You say it rotates but what's the problem now? Any animated gif to show what's going on now and what you expect?
– Programmer
Nov 11 at 16:45
Is it clearer now?
– Marek M.
Nov 11 at 17:31
Yes, it doesn't move up. You also want to be able to add rotation limit for both axis?
– Programmer
Nov 11 at 17:32
If by moving up you mean that the red guy is not pointing at the moving cube when it moves up/down, then yes - that's the problem. And again - yes - I want to add rotation limit for X and Y axis. The Z one I'm just setting to 0, as I don't want it to be influenced at all.
– Marek M.
Nov 11 at 17:36
I think there is no answer yet because people are not clear on what the problem is. You say it rotates but what's the problem now? Any animated gif to show what's going on now and what you expect?
– Programmer
Nov 11 at 16:45
I think there is no answer yet because people are not clear on what the problem is. You say it rotates but what's the problem now? Any animated gif to show what's going on now and what you expect?
– Programmer
Nov 11 at 16:45
Is it clearer now?
– Marek M.
Nov 11 at 17:31
Is it clearer now?
– Marek M.
Nov 11 at 17:31
Yes, it doesn't move up. You also want to be able to add rotation limit for both axis?
– Programmer
Nov 11 at 17:32
Yes, it doesn't move up. You also want to be able to add rotation limit for both axis?
– Programmer
Nov 11 at 17:32
If by moving up you mean that the red guy is not pointing at the moving cube when it moves up/down, then yes - that's the problem. And again - yes - I want to add rotation limit for X and Y axis. The Z one I'm just setting to 0, as I don't want it to be influenced at all.
– Marek M.
Nov 11 at 17:36
If by moving up you mean that the red guy is not pointing at the moving cube when it moves up/down, then yes - that's the problem. And again - yes - I want to add rotation limit for X and Y axis. The Z one I'm just setting to 0, as I don't want it to be influenced at all.
– Marek M.
Nov 11 at 17:36
add a comment |
1 Answer
1
active
oldest
votes
After long hours of trial and error and browsing the internet frenzily, I managed to find an answer that I could tailor to my needs. Word of comment to the first if statement of the Clamp
method - this is useful if I want the object to also be clamped in it's inverted position (if the target is behind it):
void Update()
transform.LookAt(_target.transform);
var rotation = transform.localRotation;
var eulers = ClampRotation(rotation.eulerAngles);
transform.localEulerAngles = eulers;
private static Vector3 ClampRotation(Vector3 eulerAngles)
var x = Clamp(eulerAngles.x, -60, 60);
var y = Clamp(eulerAngles.y, -45, 45);
return new Vector3(x, y, 0);
private static float Clamp(float angle, float min, float max)
if ((angle <= 180 && angle >= 180 - Mathf.Abs(min))
EDIT:
As it turns out, sometimes it's better to create your own fine-grained solution, you can modify more easily, so to anyone who is interested, you can do what I wanted to do with the below code as well:
void Update()
var actualTarget = _enemy.transform.position;
var targetDir = actualTarget - transform.position;
var target = Quaternion.LookRotation(targetDir.normalized, transform.up);
var actual = Quaternion.Inverse(transform.parent.rotation) * target;
actual.eulerAngles = ClampRotation(actual.eulerAngles);
var targetRotation = Quaternion.Slerp(transform.localRotation, actual, 8 * Time.deltaTime);
transform.localRotation = targetRotation;
private static Vector3 ClampRotation(Vector3 newRotation)
var x = Clamp(newRotation.x, -179, 179);
var y = Clamp(newRotation.y, -45, 45);
return new Vector3(x, y, 0);
private static float Clamp(float angle, float min, float max)
if ((angle <= 180 && angle >= 180 - Mathf.Abs(min))
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53247671%2fclapming-rotation-of-child-objects-in-unity%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
After long hours of trial and error and browsing the internet frenzily, I managed to find an answer that I could tailor to my needs. Word of comment to the first if statement of the Clamp
method - this is useful if I want the object to also be clamped in it's inverted position (if the target is behind it):
void Update()
transform.LookAt(_target.transform);
var rotation = transform.localRotation;
var eulers = ClampRotation(rotation.eulerAngles);
transform.localEulerAngles = eulers;
private static Vector3 ClampRotation(Vector3 eulerAngles)
var x = Clamp(eulerAngles.x, -60, 60);
var y = Clamp(eulerAngles.y, -45, 45);
return new Vector3(x, y, 0);
private static float Clamp(float angle, float min, float max)
if ((angle <= 180 && angle >= 180 - Mathf.Abs(min))
EDIT:
As it turns out, sometimes it's better to create your own fine-grained solution, you can modify more easily, so to anyone who is interested, you can do what I wanted to do with the below code as well:
void Update()
var actualTarget = _enemy.transform.position;
var targetDir = actualTarget - transform.position;
var target = Quaternion.LookRotation(targetDir.normalized, transform.up);
var actual = Quaternion.Inverse(transform.parent.rotation) * target;
actual.eulerAngles = ClampRotation(actual.eulerAngles);
var targetRotation = Quaternion.Slerp(transform.localRotation, actual, 8 * Time.deltaTime);
transform.localRotation = targetRotation;
private static Vector3 ClampRotation(Vector3 newRotation)
var x = Clamp(newRotation.x, -179, 179);
var y = Clamp(newRotation.y, -45, 45);
return new Vector3(x, y, 0);
private static float Clamp(float angle, float min, float max)
if ((angle <= 180 && angle >= 180 - Mathf.Abs(min))
add a comment |
After long hours of trial and error and browsing the internet frenzily, I managed to find an answer that I could tailor to my needs. Word of comment to the first if statement of the Clamp
method - this is useful if I want the object to also be clamped in it's inverted position (if the target is behind it):
void Update()
transform.LookAt(_target.transform);
var rotation = transform.localRotation;
var eulers = ClampRotation(rotation.eulerAngles);
transform.localEulerAngles = eulers;
private static Vector3 ClampRotation(Vector3 eulerAngles)
var x = Clamp(eulerAngles.x, -60, 60);
var y = Clamp(eulerAngles.y, -45, 45);
return new Vector3(x, y, 0);
private static float Clamp(float angle, float min, float max)
if ((angle <= 180 && angle >= 180 - Mathf.Abs(min))
EDIT:
As it turns out, sometimes it's better to create your own fine-grained solution, you can modify more easily, so to anyone who is interested, you can do what I wanted to do with the below code as well:
void Update()
var actualTarget = _enemy.transform.position;
var targetDir = actualTarget - transform.position;
var target = Quaternion.LookRotation(targetDir.normalized, transform.up);
var actual = Quaternion.Inverse(transform.parent.rotation) * target;
actual.eulerAngles = ClampRotation(actual.eulerAngles);
var targetRotation = Quaternion.Slerp(transform.localRotation, actual, 8 * Time.deltaTime);
transform.localRotation = targetRotation;
private static Vector3 ClampRotation(Vector3 newRotation)
var x = Clamp(newRotation.x, -179, 179);
var y = Clamp(newRotation.y, -45, 45);
return new Vector3(x, y, 0);
private static float Clamp(float angle, float min, float max)
if ((angle <= 180 && angle >= 180 - Mathf.Abs(min))
add a comment |
After long hours of trial and error and browsing the internet frenzily, I managed to find an answer that I could tailor to my needs. Word of comment to the first if statement of the Clamp
method - this is useful if I want the object to also be clamped in it's inverted position (if the target is behind it):
void Update()
transform.LookAt(_target.transform);
var rotation = transform.localRotation;
var eulers = ClampRotation(rotation.eulerAngles);
transform.localEulerAngles = eulers;
private static Vector3 ClampRotation(Vector3 eulerAngles)
var x = Clamp(eulerAngles.x, -60, 60);
var y = Clamp(eulerAngles.y, -45, 45);
return new Vector3(x, y, 0);
private static float Clamp(float angle, float min, float max)
if ((angle <= 180 && angle >= 180 - Mathf.Abs(min))
EDIT:
As it turns out, sometimes it's better to create your own fine-grained solution, you can modify more easily, so to anyone who is interested, you can do what I wanted to do with the below code as well:
void Update()
var actualTarget = _enemy.transform.position;
var targetDir = actualTarget - transform.position;
var target = Quaternion.LookRotation(targetDir.normalized, transform.up);
var actual = Quaternion.Inverse(transform.parent.rotation) * target;
actual.eulerAngles = ClampRotation(actual.eulerAngles);
var targetRotation = Quaternion.Slerp(transform.localRotation, actual, 8 * Time.deltaTime);
transform.localRotation = targetRotation;
private static Vector3 ClampRotation(Vector3 newRotation)
var x = Clamp(newRotation.x, -179, 179);
var y = Clamp(newRotation.y, -45, 45);
return new Vector3(x, y, 0);
private static float Clamp(float angle, float min, float max)
if ((angle <= 180 && angle >= 180 - Mathf.Abs(min))
After long hours of trial and error and browsing the internet frenzily, I managed to find an answer that I could tailor to my needs. Word of comment to the first if statement of the Clamp
method - this is useful if I want the object to also be clamped in it's inverted position (if the target is behind it):
void Update()
transform.LookAt(_target.transform);
var rotation = transform.localRotation;
var eulers = ClampRotation(rotation.eulerAngles);
transform.localEulerAngles = eulers;
private static Vector3 ClampRotation(Vector3 eulerAngles)
var x = Clamp(eulerAngles.x, -60, 60);
var y = Clamp(eulerAngles.y, -45, 45);
return new Vector3(x, y, 0);
private static float Clamp(float angle, float min, float max)
if ((angle <= 180 && angle >= 180 - Mathf.Abs(min))
EDIT:
As it turns out, sometimes it's better to create your own fine-grained solution, you can modify more easily, so to anyone who is interested, you can do what I wanted to do with the below code as well:
void Update()
var actualTarget = _enemy.transform.position;
var targetDir = actualTarget - transform.position;
var target = Quaternion.LookRotation(targetDir.normalized, transform.up);
var actual = Quaternion.Inverse(transform.parent.rotation) * target;
actual.eulerAngles = ClampRotation(actual.eulerAngles);
var targetRotation = Quaternion.Slerp(transform.localRotation, actual, 8 * Time.deltaTime);
transform.localRotation = targetRotation;
private static Vector3 ClampRotation(Vector3 newRotation)
var x = Clamp(newRotation.x, -179, 179);
var y = Clamp(newRotation.y, -45, 45);
return new Vector3(x, y, 0);
private static float Clamp(float angle, float min, float max)
if ((angle <= 180 && angle >= 180 - Mathf.Abs(min))
edited Dec 2 at 17:56
answered Nov 11 at 20:15
Marek M.
1,60832557
1,60832557
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53247671%2fclapming-rotation-of-child-objects-in-unity%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
I think there is no answer yet because people are not clear on what the problem is. You say it rotates but what's the problem now? Any animated gif to show what's going on now and what you expect?
– Programmer
Nov 11 at 16:45
Is it clearer now?
– Marek M.
Nov 11 at 17:31
Yes, it doesn't move up. You also want to be able to add rotation limit for both axis?
– Programmer
Nov 11 at 17:32
If by moving up you mean that the red guy is not pointing at the moving cube when it moves up/down, then yes - that's the problem. And again - yes - I want to add rotation limit for X and Y axis. The Z one I'm just setting to 0, as I don't want it to be influenced at all.
– Marek M.
Nov 11 at 17:36