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

Resolved Transform modification on child objects

Discussion in 'Editor & General Support' started by Chrotesque, May 4, 2021.

  1. Chrotesque

    Chrotesque

    Joined:
    Sep 7, 2019
    Posts:
    11
    Hey all!

    I'm working my way into understanding Unity, C# and how these two work together. I'm currently not understanding why Unity does what it does, specifically this is part of my objects structure:


    The script itself seems to work, the important part is this:
    Code (CSharp):
    1.     void LateUpdate() {
    2.         if (canTurn == true) {
    3.             meshTransform.transform.position = colliderTransform.transform.position;
    4.             meshTransform.transform.rotation = colliderTransform.transform.rotation;
    5.         }
    6.     }
    The mesh object contains only a mesh, nothing else.
    The collider object instead contains a collider, a rigidbody and "sadly" a script that I'd like to move to another object instead.

    1. if I have the script attached to collider, then everything works. In essence the collider object is a copy of the mesh object without the mesh rotating towards my mouse. IF it doesn't collide with another object, then it will also move the mesh to the same position
    2. if I have the script attached to the smallGunL object, then it won't work

    This is how smallGunL looks in the editor (with active script):


    This is collider instead (with active script):

    (note when I'm testing this on either object, I do deactivate the script on the other respectively)

    The Transform links for collider and mesh I double checked, they're correct. The idea behind this was quite simply that I would create a script that quite simply looks for children objects called collider and mesh and thus I can attach the script to various objects without having to manually link stuff in the editor.

    Part of the script is this:
    Code (CSharp):
    1. private void OnTriggerEnter(Collider thisCollision) {
    2.  
    3.         GameObject collisionObject = thisCollision.gameObject;
    4.         if (collisionObject.GetComponent<Rigidbody>() != null) {
    5.             canTurn = false;
    6.         }
    7.     }
    No matter what object I have the script attached to (and thus deactivated on the other!), the canTurn variable works in both cases flawlessly, yet on the smallGunL object it simply ignores the "if (canTurn == true)" requirement entirely.
    On collider the mesh (turret) moves only when the collider isn't colliding with stuff, on smallGunL is moving despite the colliding.

    I can easily move on with my project but I'd like to understand why this happens, as that might bite me in the back later on since I must not understand a fundamental principle I fear.

    Thanks in advance and kind regards!
     
  2. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,109
    I feel like you've combined a bunch of small issues here into one thread, and it's hard to know which to try to focus on... or whether they're all somehow related.

    Any chance you can try to reframe this to focus on one thing at a time?

    Is there any reason your mesh can't just be a child of the collider? Why are you trying to keep them synchronized, instead of just parenting them and not having to worry about it?
     
  3. bobisgod234

    bobisgod234

    Joined:
    Nov 15, 2016
    Posts:
    1,042
    So the canTurn variable isn't working flawlessly. How can you determine that canTurn is working correctly when it is clearly not? C# does not simply "ignore" if statements.

    OnTriggerEnter happens on components attached to the collider/rigidbody. If you attach this script to your smallGunL GameObject, OnTriggerEnter will never fire.
     
  4. Chrotesque

    Chrotesque

    Joined:
    Sep 7, 2019
    Posts:
    11
    Apologies for the late reply, I was waiting for an email and never signed up for email notifications if I get a response ... :p

    It is not only possible but likely that I'm not fully understanding each component and how they're interacting with each other, when I move the mesh onto the collider as child then both objects return at the same time.
    The collider (without a visible mesh) always looks towards the mouse pointer. The mesh is supposed to do the same as long as the collider does not trigger a collision with other objects, namely the space ships body. Having as parent child, I would then have to decouple their movements to only allow it to occur when there is no collision happening.
    So again, unless I am misunderstanding something, it's not solving any problems - or am I missing something?

    Here's a gif that might help making sense of my words and what I'm trying to accomplish, game and scene view: https://imgur.com/oAub76F
    Edit: watching that gif closely I also noticed that even the normally working turrets sometimes seem to clip into the model despite everything, probably related all in all.
    On the scene view you can see the invisible (meshless) collider going into the model and simply reporting back via canTurn variable, that the mesh cannot turn more.

    I then I moved the mesh onto the collider as child on the long turret in focus in the above gif, which is why one of them works and the other doesn't as intended. On the same kind of turret on the other side of the ship (including the bigger turret you can also see) I left it as is.

    Given that I went from:
    smallGunL
    - collider
    - mesh

    to:
    smallGunL
    - collider
    -- mesh

    and changed nothing else, I would have to change the code as outlined above and I don't see how that's going to help.

    Here's a quick rundown of the hierarchy:
    https://imgur.com/rFLls4H

    Does that help at all to specify the issue I'm struggling with?

    My wording was likely inadequate, I meant I found it in all of my testing to work flawlessly, without exception. So as soon as a turret would be clipping into the ships body, it would turn to false and once the turrets were outside (as judged by the collider object), then it would turn true. So there must be a logical issue with my code that this variable doesn't actually matter in certain circumstances, I just can't quite see why / how / what the issue is.

    I think in my previous test I simply had the script and not the collider/rigidbody on the smallGunL object, thus it makes perfect sense that this didn't work.
    Now in combination with the response from the first poster, it would suggest that I could simply use the mesh as as child to the parent (called collider, although then smallGunL) and change the code to have the child not move when canTurn returns false?
    This is how the hierarchy compares at least:


    Thanks to both of you <3
     
    Last edited: May 9, 2021
  5. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,109
    I don't really understand why you'd want it to work that way. That seems bad to me. For example, what if some space ship was flying around shooting at things, and shot at your turret while the collider was inside of a wall. Maybe the shot won't hit the turret, because the collider is behind the wall. So, that definitely doesn't sound ideal to me. That first gif you showed immediately seemed like a bug to me. But then I realized you don't consider that to be incorrect behavior. So, ultimately, do things how you want, but that seems pretty weird to me, and potentially hard to work with. But to me, I'd make sure you're not allowing invalid overlap at all.

    In my game, my turrets are created as a single model, which has an armature. (I use Blender to make my models, but it's the same in any modelling software, I think.)

    upload_2021-5-9_18-51-37.png

    upload_2021-5-9_18-49-38.png

    I attach colliders to the various bones at runtime, and I only ever move the bones. The "meshes" (the last four items you see in the hierarchy there) are automatically linked to the bones, and move as the bones move.

    This itself doesn't solve the collision problem. But it should be reasonably simple to have your "aim" script test whether overlap will occur among any of the child colliders if it tries to turn to face the target.
     
  6. Chrotesque

    Chrotesque

    Joined:
    Sep 7, 2019
    Posts:
    11
    It was actually a suggested solution to sort of the same problem I found somewhere, that's where I got the idea from.
    Hit detection, it actually took me a hot minute to understand what you mean with this. But you're right, the collider would be inside my ship possibly and thus the shot, while visually hitting the turret, would count as a ship body hit instead, in my specific case right now.

    If you disregard the aforementioned problem, then it does it's job flawlessly (well until it doesn't, which is why I am here).

    That's also how I got to where I am, since I don't know any other way. Without further help I'll be looking further into if I can do the same without an invisible collider model doing the forbidden and make it a single thing or separate it out like you do, as well as look into bones as a possible solution.

    To better imagine how it works in your specific example, could you provide a gif of that turret moving around possibly?
     
  7. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,109
    I have various objects in my game that have some dynamic movement on them, but there is code involved in preventing it from moving through other colliders. In your case, I imagine a rotation logic that works something like this:

    At any given time, you know the turret's current rotation, and you know where it should ideally be aiming. If there were no colliders involved, you'd just rotate to that ideal aiming position. Even in this case, I imagine you'd do this gradually over time, instead of instantly aiming at the target. So, we assume your turret has a rotation speed, and every frame it gradually adjusts the rotation to be closer to the "correct" rotation.

    So, every frame you're rotating a little bit more towards the correct rotation. Now, all you need to do is make sure that it's valid to perform that small rotation. For this, I'd probably start with Physics.OverlapBoxNonAlloc(). You'd determine the small rotation amount you want to make. Then you'd test whether your collider would overlap with any other colliders if it were rotated to that rotation. If it would cause overlap, you don't set the rotation; you just leave it the way it was. If it wouldn't cause overlap, you allow the rotation to occur.

    That's the general idea. Before rotation, see if that rotation would cause overlap, and then just don't rotate if it would. Your collider never overlaps the ship, and you don't need to worry about keeping two things sync'd up.

    Also, here's what the turret looks like when it's aiming, since you asked. It doesn't look like much, but there are a couple of colliders placed on each of the bones.

     
  8. Chrotesque

    Chrotesque

    Joined:
    Sep 7, 2019
    Posts:
    11
    You're right of course, there is a rotation speed. I was previously stuck on the idea of using OnTriggerEnter & OnTriggerExit which had its downsides (firing once each per collision).

    Lots to dig in, given how important this mechanic is to me, I'll focus on that right away. Thank you!