Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 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 MigLeader · Jul 08, 2012 at 12:29 AM · rotationquaternionangletargetturret

problems with quaternion rotations

hi there my friends i have a trouble in making the following:
1-i have a spaceship that is controlled by using (rigidbody.AddRelativeTorque) thats is getting info from the position of the mouse on screen.
2-i have a turret on top of the ship.
3-the turret uses the following script to lead the targets:

 #pragma strict
 #pragma implicit
 #pragma downcast
 
 var damping = 5.0;
 var Target : GameObject;
 var projSpeed : int;
 var fireHitRatio : float;
 var targetLead : GameObject;
 var enableFire : boolean;
 var rotation : Quaternion;
 
 function Start(){
  fireHitRatio = 1.15;
 } 
 
 function Update () {
  if (Target != null){
  TargetLead();
  }else if (Target == null){
  NoTargets();
  }
 }
 
 function TargetLead(){
  if (Target != null) {
    var TGV = Target.rigidbody.velocity;
       projectileSpeed = projSpeed;
       var distTarget = Vector3.Distance(Target.transform.position, transform.position);
       velocityPosition1 = Target.transform.position + ((TGV * fireHitRatio) * (distTarget/projectileSpeed));
       velocityDist1 = Vector3.Distance(velocityPosition1, transform.position);
       velocityPosition2 = Target.transform.position + ((TGV * fireHitRatio) * (velocityDist1/projectileSpeed));
       velocityDist2 = Vector3.Distance(velocityPosition2, transform.position);
       TargetInterceptPosition = Target.transform.position + ((TGV * fireHitRatio) * (velocityDist2/projectileSpeed));
       
       rotation = Quaternion.LookRotation((TargetInterceptPosition) - transform.position);
    transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * damping);
  }
  targetLead.transform.position = camera.main.WorldToViewportPoint(TargetInterceptPosition);
 }
 
 function NoTargets(){
  targetLead.transform.position = Vector3(0,0,0);
  transform.rotation = Quaternion.Slerp(transform.rotation, transform.parent.rotation, Time.deltaTime * damping / 5);
 }

 
 

4-the turret must be alinged with the ship at all times , but must also try to look at the target lead with the following:

the above script works the best if used on a turret made with 1 piece of geometry.

the turret is made up with 2 parts ,(turret) which moves only on Y Axis , (barrel) which moves only on X Axis but also follows the turret Y Axis.

the troubles i am having:
1-used many scripts , cant list them here but it always mess the rotation of the turret by a really weird rotations.
2-the following script is the best but it does not aim well , it aims little higher than it must be:

     var rotationInfo : ProcessingTargets;
 var displayedInfo : Quaternion;
 
 
 function Update (){
  displayedInfo = Quaternion.Slerp(transform.rotation, rotationInfo.rotation, Time.deltaTime * rotationInfo.damping);
  if (rotationInfo.Target != null){
  transform.rotation = Quaternion(displayedInfo.x,displayedInfo.y,displayedInfo.z,displayedInfo.w);
  Debug.DrawLine(transform.position,rotationInfo.Target.transform.position,Color(1,1,1,1));
  }
 }  



 var turretRotationsInfo : TurretTargeter;
 var angle = 0.0;
 var axis : Vector3;
 var isBarrel : boolean;
 
 function Update (){
  axis = turretRotationsInfo.displayedInfo.eulerAngles;
  if(isBarrel == false){
  transform.localEulerAngles.y = axis.y - 90;
  }else if(isBarrel == true){
  transform.localEulerAngles.y = axis.x + 1.5;
  }
 } 

please i wish someone really helps me with this because it have taken a long time in debugging , trying , scripting ....etc

and also i am having lot of troubles with (quaternions) i have read the documents on it but still didnt understand it fully and i think thats why i failed at fixing this.

thx in adv

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 MigLeader · Jul 09, 2012 at 12:18 AM 0
Share

anyone , i worked more on it but still failing to get at least a good results , hope i get help soon.

thx

4 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by aldonaletto · Jul 09, 2012 at 06:51 PM

I didn't understand exactly what your script should do, but you should not mix eulerAngles with localEulerAngles - localEulerAngles are the angles relative to the parent transform, and you should take the parent rotation into account before setting them. Furthermore, eulerAngles aren't too reliable - eulerAngles are actually the transform.rotation converted to 3-axes representation on the fly; since there are several XYZ combinations equivalent to any possible rotation, Unity sometimes selects a weird one to return, driving us crazy.

I think the simplest solution would be just to use transform.LookAt(target) in the turret script:

 var target: Transform;
 
 function Update(){
   transform.LookAt(target);
 }

If you want to follow the target with some delay, use this:

 var target: Transform;
 
 function Update(){
   var dir = target.position - transform.position;
   var rot = Quaternion.LookRotation(dir); // LookRotation takes a direction as argument
   transform.rotation = Quaternion.Slerp(transform.rotation, rot, damping * Time.deltaTime);
 }

EDITED: If you want to rotate the turret and the barrel around their local Y and X axes, respectively, there's a "dirty trick" that can split movements: for the turret, transform the target position in local space with InverseTransformPoint, zero its Y coordinate and convert it back to world space with TransformPoint - this will project the target position in the turret's local horizontal plane; you can then use Quaternion.LookRotation to find the desired rotation, and Slerp to it. You could also repeat the trick for the barrel (zeroing its X coordinate instead, so that the point would be projected in the barrel's vertical plane), but it's not advisable: errors accumulated over time will cause a deviation. It's better to just use LookRotation to find the necessary rotation to the target position and Slerp the barrel to it - the result is the same, but you'll not get accumulated errors:

EDITED2: You're right: the turret was using its local space to find the point, and gradually this reference was being lost, giving very weird rotations. I changed the things a little: created an empty object (let's call it Ref) at the turret position, added the script below to it, then childed the turret and the barrel to the Ref object - the hierarchy is as follows:

 Ship <- ship is parent of the Ref object
   Ref <- control script goes here
     Barrel <- barrel is childed to Ref
     Turret <- turret is childed to Ref

The script caches references to Barrel and Turret, and control both:

 var target: Transform;
 var damping: float = 5.0;
 
 private var turret: Transform;
 private var barrel: Transform;
 private var trf: Transform;
 
 function Start () { // the barrel is a turret's child:
   trf = transform;
   barrel = trf.Find("Barrel");
   turret = trf.Find("Turret");
 }
 
 function Update () {
   // convert target position to local space:
   var pos = trf.InverseTransformPoint(target.position);
   pos.y = 0; // project it in the horizontal plane
   // convert pos back to world space:
   pos = trf.TransformPoint(pos);
   // find the desired turret rotation and Slerp to it:
   var rot = Quaternion.LookRotation(pos-trf.position, trf.up);
   turret.rotation = Quaternion.Slerp(turret.rotation, rot, damping*Time.deltaTime); 
   // just point the barrel to the target:
   rot = Quaternion.LookRotation(target.position-barrel.position, trf.up);
   barrel.rotation = Quaternion.Slerp(barrel.rotation, rot, damping*Time.deltaTime); 
 }




Comment
Add comment · Show 7 · 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 MigLeader · Jul 09, 2012 at 07:14 PM 0
Share

ok thx for ur comment , but if u looked in my first post , u will find that i have a script that also leads the target depending on the speed or the bullet and the speed and range of the target. so if i used transform.LookAt(target) it will just look at the target without leading it.

the only problem i am facing now , is to align the turret and the barrel to the ship without ruining the targeting script or the angles of the turret.

thx for ur help anyway , anymore hints?

avatar image aldonaletto · Jul 09, 2012 at 07:44 PM 0
Share

Ok, I suppose to have understood your question now: your first script is good for a single piece turret, but you're having problems with a combination turret+barrel, where you want the turret to rotate around its local Y axis, and the barrel to rotate around its X axis - is it correct?

avatar image MigLeader · Jul 09, 2012 at 09:20 PM 0
Share

thats right good sir , but also i want them to align with the moving ship that they are on it.

as u said , i want them to rotate around their local axis only.

thx a lot for ur time

avatar image aldonaletto · Jul 09, 2012 at 10:52 PM 0
Share

Take a look at my answer: I made the turret rotate around its local Y axis in direction to the target, while the barrel follows it and rotate also around its X axis to point the target - and all of this with some delay. It doesn't matter if the turret is childed to the ship: it will rotate around its local Y axis.

avatar image MigLeader · Jul 09, 2012 at 11:32 PM 0
Share

i tried ur script but.... i still get the same problem, + another one:

1-the turret still gets really strange angle if the ship rotates to down or left for Ex...
2-the turret aims right at the target with no leading for the target (that means when i fire the bullet will just miss bcz the target moves)

i was thinking , can i take the rotation of my first script posted and split it in to angles so i can use whatever i want but convert them in to local angles.

as i said i am really bad with Quaternion , thats why i failed.

and sry for bad english or anything wrong , its 2:30A$$anonymous$$ here and i am really tired.

still i really thx u for ur time in helping me.

Show more comments
avatar image
1

Answer by captaincrunch80 · Jul 09, 2012 at 11:52 PM

I had the same freaking problem and worked around it like this.

Here the corpus and barrel are handled. Both transformations are reduced to a 1 or 2 dimensional rotation. I use a temp look-at vector to work around quaternions.

I stripped all the code for shooting particle control and some other stuff.

!! For this to work, the barrel must be an individual model and has to have it's origin at it's rotation point

If you only want to rotate the whole turret (corpus) then just stip the barrel code.

  // C#
  public Transform corpus;
  public float corpusTurnSpeed = 10.0f;
  public Transform barrel;
  public float barrelTurnSpeed = 10.0f;
  
  private GameObject currentTarget = null;
     
  void Update ()
  {
     // Stripped ....
              
     if (currentTarget != null) {
        Vector3 targetPoint = currentTarget.collider.bounds.center;

        // Calculate Corpus X-Y-Z Rotation and LERP it
        // then set Corpus Y Rotation to 0.0
        Vector3 newCorpusFwd 
           = Vector3.Lerp (corpus.forward, 
              (targetPoint - corpus.position).normalized,
              Time.deltaTime * corpusTurnSpeed);
        newCorpusFwd.y = 0.0f;
        corpus.transform.forward = newCorpusFwd;

        // Calculate Barrel Y Rotation and smoothStep it
        // Then align Barrel x-z rotation to the corpus again
        barrel.transform.LookAt (targetPoint);
        Vector3 newBarrelFwd = barrel.forward;
        float newBarrelY
           = Mathf.SmoothStep (barrel.forward.y, 
              (targetPoint - barrel.position).normalized.y,
              Time.deltaTime * barrelTurnSpeed);
        newBarrelFwd.x = newCorpusFwd.x;
        newBarrelFwd.y = newBarrelY;
        newBarrelFwd.z = newCorpusFwd.z;
        barrel.forward = newBarrelFwd;
  
        // Stripped ...
     
     } else {
        // Stripped ... 
     }
  }



As requested, here the javascript version, but not tested:

  // javascript
  var corpus : Transform;
  var corpusTurnSpeed : float = 10.0f;
  var barrel : Transform ;
  var barrelTurnSpeed : float = 10.0f;
  
  private var currentTarget : GameObject;
     
  void Update ()
  {
     // Stripped ....
              
     if (currentTarget != null) {
        var targetPoint : Vector3 = currentTarget.collider.bounds.center;

        // Calculate Corpus X-Y-Z Rotation and LERP it
        // then set Corpus Y Rotation to 0.0
        var newCorpusFwd : Vector3
           = Vector3.Lerp (corpus.forward, 
              (targetPoint - corpus.position).normalized,
              Time.deltaTime * corpusTurnSpeed);
        newCorpusFwd.y = 0.0f;
        corpus.transform.forward = newCorpusFwd;

        // Calculate Barrel Y Rotation and smoothStep it
        // Then align Barrel x-z rotation to the corpus again
        barrel.transform.LookAt (targetPoint);
        var newBarrelFwd : Vector3 = barrel.forward;
        var newBarrelY : float
           = Mathf.SmoothStep (barrel.forward.y, 
              (targetPoint - barrel.position).normalized.y,
              Time.deltaTime * barrelTurnSpeed);
        newBarrelFwd.x = newCorpusFwd.x;
        newBarrelFwd.y = newBarrelY;
        newBarrelFwd.z = newCorpusFwd.z;
        barrel.forward = newBarrelFwd;
  
        // Stripped ...
     
     } else {
        // Stripped ... 
     }
  }
Comment
Add comment · Show 2 · 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 MigLeader · Jul 10, 2012 at 12:22 AM 0
Share

can u good sir if u please , convert it to js , i am nothing in C#

avatar image captaincrunch80 · Jul 10, 2012 at 10:29 AM 0
Share

Hi there,

I tried to convert it to js, even if I am not often working with it. As you can see in this case only the variable declarations are a problem. (See above in my original post)

C# and js are not so different. The idea behind the code stays the same, it are mostly some syntax issues. I am not sure about using .NET in js though.

Anyways - learn C#, I can recommend it. It is very handy to have all that classes, inheritance (And all the other object oriented stuff) stuff on your side.

Best of luck!

avatar image
0

Answer by MigLeader · Jul 09, 2012 at 05:30 PM

ok this Script works semi fine:

 var turretRotationsInfo : TurretTargeter;
 var angle = 0.0;
 var axis : Vector3;
 var isBarrel : boolean;
 
 function Update (){
  axis = turretRotationsInfo.displayedInfo.eulerAngles;
  if(isBarrel == false){
  transform.localEulerAngles.y = axis.y - 90;
  }else if(isBarrel == true){
  transform.localEulerAngles.y = axis.x + 1.5;
  }
 }

but as soon as i move the ship , the turrets starts to inherit some added rotation from the ship so it starts missing the right point to aim to.

any fix for this?

please help me at least with a hint only.

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 MigLeader · Jul 24, 2012 at 10:07 PM

hi again , sigh , i tried everything above and trying to combine it with my code of lead targeting but nothing worked probably, so here i am asking a fix for it as the following:
i will have to write it in the answers cuz i didnt find how i can format the code using comments , if its wrong to do it like that then i am sorry , i will remove it.

i have this script:

 #pragma strict
 #pragma implicit
 #pragma downcast
 
 var damping = 5.0;
 var Target : GameObject;
 var projSpeed : int;
 var fireHitRatio : float;
 var targetLead : GameObject;
 var targetLead2 : GameObject;
 var targetLead3 : GameObject;
 var shiproty : Transform;
 
 function Start(){
  fireHitRatio = 1.15;
 } 
 
 function Update () {
  if (Target != null){
  TargetLead();
  }else if (Target == null){
  NoTargets();
  }
  
 }
 
 function TargetLead(){
  if (Target != null) {
    var TGV = Target.rigidbody.velocity;
       projectileSpeed = projSpeed;
       var distTarget = Vector3.Distance(Target.transform.position, transform.position);
       var velocityPosition1 = Target.transform.position + ((TGV * fireHitRatio) * (distTarget/projectileSpeed));
       var velocityDist1 = Vector3.Distance(velocityPosition1, transform.position);
       var velocityPosition2 = Target.transform.position + ((TGV * fireHitRatio) * (velocityDist1/projectileSpeed));
       var velocityDist2 = Vector3.Distance(velocityPosition2, transform.position);
       var TargetInterceptPosition = Target.transform.position + ((TGV * fireHitRatio) * (velocityDist2/projectileSpeed));
 
       var rotation = Quaternion.LookRotation((TargetInterceptPosition) - transform.position);
    transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * damping);
    
  }
  
  targetLead.transform.position = camera.main.WorldToViewportPoint(velocityPosition1);
  targetLead2.transform.position = camera.main.WorldToViewportPoint(velocityPosition2);
  targetLead3.transform.position = camera.main.WorldToViewportPoint(TargetInterceptPosition);
 }


all i want is to split the rotations from it in to X , Y , Z and store them in Vars , then convert them in to local rotations.

i prefer to not change the code of leading targets cuz its working the best and i couldn't find another way to do it.

please this problem have taken from me most of my Time , still i thank everyone who tried to help me with it.

thx in adv

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

8 People are following this question.

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

Related Questions

Rotate floor plane in-game via C# script 1 Answer

How to transmit the correct rotation (quaternion) to an configurable joint? 1 Answer

Rotation according to gravity 1 Answer

Rotate towards target around axis with limits 0 Answers

Make a side of an object LookAT another object 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