Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Gears in Unity Physics Engine

Discussion in 'Scripting' started by ml1985, Jul 21, 2014.

  1. ml1985

    ml1985

    Joined:
    Dec 29, 2013
    Posts:
    22
    Hi Guys

    I was wondering if an expert can help a rookie here. I have created a gear from Cheetah3d and imported the mesh to Unity is an obj file. I am trying to create a system in Unity where one gear will turn the other. This has proved to be much harder than I thought. I have followed many tutorials from this website + the net but I cannot get over this obstacle. I'm starting to think it might not be possible to do this afterall. Is it the obj file perhaps?

    Whatever I try, the gear just passes through the other gear as if it is not there. I have uploaded a scene file if anyone is generous enough to help I would greatly appreciate it.
     

    Attached Files:

  2. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,716
    There is no such thing as "impossible" in code. Everything is possible, just might be much harder.

    As for gears, I would not use physic (if it is what you're using). I would connect gears by reference, with and share their ratio to each other.
     
    Unitay26 likes this.
  3. ml1985

    ml1985

    Joined:
    Dec 29, 2013
    Posts:
    22
    Thanks LightStriker, boy that was a quick reply. ;)

    I guess I was a bit naive about it being impossible. I would have thought though if the gears are accurately generated then the physics engine can do the rest.

    In terms of connecting the gears by reference I guess I would have to write a script. Is it possible to do it this way and still have the gear teeth physically interlocking rather than the gears turning based on an rpm calculation?

    Many thanks again for assisting mate.
     
  4. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,716
    Not physically interlocking, but if they are accurate, the rpm would give them to be "visually" interlocked.
     
  5. ml1985

    ml1985

    Joined:
    Dec 29, 2013
    Posts:
    22
    I'll definitely give it a try.

    Thanks for the advice.
     
  6. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,738
    The particular issue you're having with the physics engine right now is that concave mesh colliders cannot collide with each other (Unity/PhysX disables this because it's far too slow performance-wise for 99% of games); in Unity, concave mesh colliders are primarily useful only for static(ish) terrain, or for receiving raycasts. You can usually use convex mesh colliders (that is, a collider that has no "inside" angles; it'll turn a donut into a circle) (which DO collide with each other) to get around this, but the areas between the teeth of gears would make this a no-go for your purpose, as well.

    The other option is, you can create a compound collider by, for example, putting a cube on each "tooth"; if you parent all the cubes under one rigidbody, they will act as one.

    All that said, LightStriker is correct: using physics to have gears turn each other in a game is a bad choice. There are going to be all sorts of precision issues (especially if the gears ever move remotely quickly), and performance will be bad. Special coding for gears is the way to go, 99% of the time.
     
  7. ml1985

    ml1985

    Joined:
    Dec 29, 2013
    Posts:
    22
    Thank you for the advice StarManta,

    I'll let you guys know how I got on.
     
  8. ml1985

    ml1985

    Joined:
    Dec 29, 2013
    Posts:
    22
    Hi guys

    Just a quick question, once you have a gear rotating, how do you set the script so that a particular gear rotates inversely to its parent?

    Any help will be great.
     
  9. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,716
    What have you tried?
     
  10. ml1985

    ml1985

    Joined:
    Dec 29, 2013
    Posts:
    22
    Hi

    I've set up the parent gear with a script that makes the gear turn (transform.rotate) when the left arrow is keyed.

    Scriptwise now how can I make the child gear turn when the parent gear turns and inversely to it aswell.
    I have already calculated the speed it needs to rotate so I wouldn't need to incorporate a formula or anything.
    I know how to use the getcomponent to retrieve info from the parent script so I just need to connect the dots now.

    Thanks
     
  11. ml1985

    ml1985

    Joined:
    Dec 29, 2013
    Posts:
    22
    Hi guys

    I have also included the project file if anyone can check for me. I basically need a few pointers as to how to proceed.
    The project is basically a template for using gears. I need to update the scripts so that the child gear rotates when the parent gear rotates and also inversely to it.

    I'm at wits end and any help would be great

    Thanks
     

    Attached Files:

  12. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,716
    I think you got the logic backward... The parent is the one driving the child.

    Here's my go at it;

    Parent;
    Code (CSharp):
    1. public class Rotate : MonoBehaviour
    2. {
    3.     public float turnSpeed = 50f;
    4.     public float ToothCount;
    5.  
    6.     public Child child;
    7.  
    8.     private void Update()
    9.     {
    10.         float rotation = 0;
    11.         if (Input.GetKey(KeyCode.LeftArrow))
    12.             rotation = turnSpeed * Time.deltaTime;
    13.  
    14.         if (Input.GetKey(KeyCode.RightArrow))
    15.             rotation = -turnSpeed * Time.deltaTime;
    16.  
    17.         transform.Rotate(transform.forward, rotation);
    18.  
    19.         child.Rotate(-rotation * ToothCount);
    20.     }
    21. }
    and Child;

    Code (CSharp):
    1. public class Child : MonoBehaviour
    2. {
    3.     public float ToothCount;
    4.  
    5.     public void Rotate(float rotation)
    6.     {
    7.         rotation /= ToothCount;
    8.         transform.Rotate(transform.forward * rotation);
    9.     }
    10. }
    11.  
     
  13. ml1985

    ml1985

    Joined:
    Dec 29, 2013
    Posts:
    22
    Aha!!

    Worked a charm. Thank you bro! I might come back with other questions though if you don't mind.

    Thanks
     
  14. ml1985

    ml1985

    Joined:
    Dec 29, 2013
    Posts:
    22
    Hi LightStriker

    Suppose I add another gear to be driven by the child gear. How would I script the behaviour so the new gear rotates based on the child gear.

    Again I appreciate your help
     
  15. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    just curious - why wouldn't this be possible using a set of box colliders with fixed joints to represent the teeth? Is it representing some kind of axle that would be the problem?

    Doing it in simple code is almost certainly the right solution. But just out of curiosity...
     
  16. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,716
    One class to rule them all...

    Code (CSharp):
    1. public class Gear : MonoBehaviour
    2. {
    3.     public float turnSpeed = 50f;
    4.     public float ToothCount;
    5.  
    6.     public Gear[] children;
    7.  
    8.     private bool parented = false;
    9.  
    10.     private void Start()
    11.     {
    12.         for (int i = 0; i < children.Length; i++)
    13.             children[i].parented = true;
    14.     }
    15.  
    16.     private void Update()
    17.     {
    18.         if (parented)
    19.             return;
    20.  
    21.         float rotation = 0;
    22.         if (Input.GetKey(KeyCode.LeftArrow))
    23.             rotation = turnSpeed * Time.deltaTime;
    24.  
    25.         if (Input.GetKey(KeyCode.RightArrow))
    26.             rotation = -turnSpeed * Time.deltaTime;
    27.  
    28.         transform.Rotate(transform.forward, rotation);
    29.  
    30.         for (int i = 0; i < children.Length; i++)
    31.             children[i].Rotate(-rotation * ToothCount);
    32.     }
    33.  
    34.     public void Rotate(float rotation)
    35.     {
    36.         rotation /= ToothCount;
    37.         transform.Rotate(transform.forward * rotation);
    38.  
    39.         for (int i = 0; i < children.Length; i++)
    40.             children[i].Rotate(-rotation * ToothCount);
    41.     }
    42. }
     
  17. ml1985

    ml1985

    Joined:
    Dec 29, 2013
    Posts:
    22
    Hi

    I originally planned to do it this way but I had issues with the mesh and the physics engine. I actually found this way to be best if I get the scripting right :)
     
  18. ml1985

    ml1985

    Joined:
    Dec 29, 2013
    Posts:
    22
    Hi Light Striker

    the master class works perfectly too. Since I couldn't work it out before I was wondering if you could shed some light on it for me. Going back to the child script. Once you have added a parent that turns independantly, is there an "if parent rotates, then child rotates inversely"?

    Kind regards
     
  19. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,716
    There is no "if", since a child gear is driven by the parent. So the parent always move the child, even if that move is 0.