Search code examples
c#visual-studiounity-game-engineunify

Unity disable child rotation


I have one issue in unity 2d with my object , when i shoot the arrow to the box collider to the other element , and when it hit and go into child i mean arrow become child of parent (BOX) the child start to rotate to the left and to the right .. I really want to disable left and right rotation of the child .. the box (parent) still need to rotate as same as it was before.. i have code like this and my arrow in rigidbody2d is on kinematic mode...

this is script of the arrow ..

{
    public float flySpeed = 20f;
    private Rigidbody2D arrowBody;
    private bool shouldFly;


    // Start is called before the first frame update
    void Start()
    {
        shouldFly = true;
        arrowBody = GetComponent<Rigidbody2D>();
    }

    // Update is called once per frame
    void Update()
    {
        if (shouldFly == true)
        {
            //make our pin fly
            arrowBody.MovePosition(arrowBody.position + Vector2.up * flySpeed * Time.deltaTime);
        }
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.tag == "target")
        {

            shouldFly = false;
            transform.SetParent(collision.gameObject.transform);


        } else if(collision.tag == "arrow")
        {

            SceneManager.LoadScene("quickGameOverScene");
        }
    }
}

Solution

  • I am really confused what you are trying to do. I do not understand if you want to freeze rotation or movement so i will post answers for both. In order to prevent translations and rotations caused by parent object you can use LateUpdate like this:

    Quaternion InitRot;
    Vector3 InitPos;
    
    void Start () {
        InitRot = transform.rotation;
        InitPos = transform.position;
    }
    void Update()
    {
        //figuring out when to save position when attached to BOX
        if(gameObject.transform.parent == null)
        {
            InitRot = transform.rotation;
            InitPos = transform.position;
        }
    }
    void LateUpdate () {
        //If attached to box do not translate do not rotate
        if (gameObject.transform.parent != null)
        {
            transform.rotation = InitRot;
            transform.position = InitPos;
        }
    }
    

    You can have more information about this solution from here

    EDIT Since the answer above did not work out for OP. I figured out what the actual problem is. OP's code is perfectly fine for moving the arrow but the problem is most likely where he rotates the box.

    If he rotates the box using transform.Rotate(Vector3.forward* 90), there will be a distortion caused by same amount of rotation in each Update since frame times are not same in each Update. Therefore, he needs to rotate the box using Time.deltaTime for consistent rotation like this: transform.Rotate(Vector3.forward* 90*Time.deltaTime); This rotate the box same amount in each time interval and eliminate distortion. These are the scripts i used for the task and it works for me.

    Script for the arrow:

    public float flySpeed = 20f;
    private Rigidbody2D arrowBody;
    private bool shouldFly;
    private Vector2 initPos;
    private Quaternion initRot;
    // Start is called before the first frame update
    void Start()
    {
        shouldFly = true;
        arrowBody = GetComponent<Rigidbody2D>();
        //arrowBody.isKinematic = true;
        initPos = gameObject.transform.position;
        initRot = gameObject.transform.rotation;
    }
    
    // Update is called once per frame
    void Update()
    {
        if (shouldFly == true)
        {         
            //make our pin fly
            arrowBody.MovePosition(arrowBody.position + Vector2.up * flySpeed * Time.deltaTime);
        }
        if(gameObject.transform.parent == null)
        {
            initPos = gameObject.transform.position;
            initRot = gameObject.transform.rotation;
        }
    
    }
    void LateUpdate()
    {
        if (gameObject.transform.parent != null)
        {
            gameObject.transform.position = initPos;
            gameObject.transform.rotation = initRot;
        }
    }
    
    private void OnTriggerEnter2D(Collider2D collision)
    {
        Debug.Log("Collision happened");
        if (collision.tag == "target")
        {          
            shouldFly = false;          
            transform.SetParent(collision.gameObject.transform);
        }
        else if (collision.tag == "arrow")
        {
    
            SceneManager.LoadScene("quickGameOverScene");
        }
    }
    

    And The script for rotating the box:

    public float rotationSpeed = 70f;
    void Update()
    {
        transform.Rotate(Vector3.back, rotationSpeed * Time.deltaTime);
    }