- Home /
Child object getting transformed out side the scene on collision?
I have a requirement to do Jigsaw Puzzle.When I connect adjacent pieces ,the colliding piece should become child and it should transform along with its parent piece. I have written collision script for piece 1 and attached the script to it. When piece 2 collide with piece 1 , piece 2 getting transformed as child but goes out of the scene.
Reverse collision works fine.(When piece 1 collides with piece 2,piece 2 getting transformed as child and remains connected).
And I have also tried writing script for Piece 2, even then the same happens.
I have used four box colliders for four sides.
Have uploaded images too.
Here is the code:
if(co.gameObject.collider.tag=="Piece2")
{
foreach (Transform child in transform)
{
if(child.gameObject.collider.name=="Right")
{
foreach (Transform child1 in piece2.transform)
{
if(child1.gameObject.collider.name=="Left")
{
i1=2;
if(i1==2)
{
i1=3;
piece2.transform.parent = transform;
piece2.GetComponent<OTSprite>().draggable = false;
child1.GetComponent<BoxCollider>().isTrigger=false;
child.GetComponent<BoxCollider().isTrigger=false;
piece2.transform.position = new Vector3(piece1.transform.position.x+80.0f,
piece1.transform.position.y, piece1.transform.position.z);
}
}
}
}
}
Please suggest any ideas.Thanks.
After setting up the parent, you might want to move the piece with localposition and not position.
@dorpeleg Have tried that too.Even though I got same result.
Here is the code:
piece2.transform.position = new Vector3(piece1.transform.position.x+80, piece1.transform.localPosition.y, piece1.transform.localPosition.z);
Thanks for your reply.
Try:
piece2.transform.localPosition = new Vector3(piece1.transform.localPosition.x+80, piece1.transform.localPosition.y, piece1.transform.localPosition.z);
@dorpeleg Have tried that too. But got the same result.
Thanks for your reply.
piece2.transform.localPosition = new Vector3(80, 0, 0);
If it's still not correct, then you need to change the value from 80 to something smaller.
Answer by rhys_vdw · Jul 29, 2013 at 01:06 PM
Okay, so firstly I just want to explain what's actually happening in your script.
void OnTriggerEnter(Collider co)
{
// Check if the collider that the piece is touching is tagged "Piece2".
if(co.gameObject.collider.tag=="Piece2")
{
// Step through *all four* children of this object.
foreach (Transform child in transform)
{
// Ignore all but the right collider. Note this does NOT check if
// the right collider is touching the other piece!
if(child.gameObject.collider.name=="Right")
{
// Step through all the children of 'piece2'.
foreach (Transform child1 in piece2.transform)
{
// This code will ALWAYS find the left collider, it doesn't
// matter which is touching.
if(child1.gameObject.collider.name=="Left")
{
// So some pointless math.
i1=2;
if(i1==2)
{
i1=3;
// Child piece2 to this object, and set its
// localPosition to (80,0,0).
piece2.transform.parent = transform;
piece2.GetComponent<OTSprite>().draggable = false;
piece2.transform.localPosition = new Vector3(80.0f, 0, 0);
}
}
}
}
}
}
}
So basically your script just will attach this "piece2" thing to itself, no matter which side it hits. I think you're making the mistake of thinking that when you do this foreach through all the children, you will only see children that are touching the other collider. This is not the case. Each of these foreach statements will step through all the children.
I've taken out a lot of the redundant code in your script and this is what is left:
void OnTriggerEnter( Collider collider )
{
if( collider.tag == "Piece2" )
{
// Get this pieces right child, and the other piece's left child.
Transform thisRight = transform.Find( "Right" );
Transform otherLeft = piece2.transform.Find( "Left" );
// Assign this number.
i1 = 3;
// Child to this.
piece2.transform.parent = transform;
piece2.GetComponent<OTSprite>().draggable = false;
piece2.transform.localPosition = new Vector3(80.0f, 0, 0);
}
}
Basically your script doesn't care about who is hitting it, or what is going on. I'm worried that you have a huge list of every single piece in this script.
I'm going to just write a script for you that will solve the problem correctly, because it seems like you're a bit lost. But I'll be happy to give you more feedback or explanation if you don't understand.
Attach this script to each of the four child objects:
using UnityEngine;
// This script should be attached to each of the four children of PuzzlePiece.
public class PuzzlePieceCollider : MonoBehaviour
{
void OnTriggerEnter( Collider collider )
{
// Get the parent of the collider that we've hit.
Transform otherPiece = collider.transform.parent;
// If it should be attached, do so. Otherwise ignore.
if( name == "Right" && collider.name == "Left" )
{
SendMessageUpwards( "AttachRight", collider.transform.parent );
}
else if( name == "Left" && collider.name == "Right" )
{
SendMessageUpwards( "AttachLeft", collider.transform.parent );
}
else if( name == "Top" && collider.name == "Bottom" )
{
SendMessageUpwards( "AttachTop", collider.transform.parent );
}
else if( name == "Bottom" && collider.name == "Top" )
{
SendMessageUpwards( "AttachBottom", collider.transform.parent );
}
}
}
And this one to the actual piece:
using UnityEngine;
public class PuzzlePiece : MonoBehaviour
{
public float size = 80f;
void AttachRight( Transform other )
{
Attach( other, Vector3.right * size );
}
void AttachLeft( Transform other )
{
Attach( other, Vector3.left * size );
}
void AttachTop( Transform other )
{
Attach( other, Vector3.up * size );
}
void AttachBottom( Transform other )
{
Attach( other, Vector3.down * size );
}
void Attach( Transform other, Vector3 offset )
{
// Check that the other piece is not already the parent of this piece!
// This will be called on both pieces so we only need to parent one of them.
if( transform.parent == other ) return;
// Parent the piece.
other.parent = transform;
other.localPosition = offset;
// Do this thing.
other.GetComponent<OTSprite>().draggable = false;
}
}
You should set "size" on the pieces to the width/height of the pieces.
Each of the four colliders should be set to trigger, and the puzzle piece will require a kinematic rigibody.
Tell me how you go.
I'm glad to hear that.
If you want to add checks in to see if the pieces are in the right place, I suggest adding public xPosition and yPosition integers to the PuzzlePiece script.
Then before you call "Attach" you will have to check something like this...
void AttachRight {
int otherX = other.GetComponent<PuzzlePiece>().XPosition;
if( otherX == XPosition + 1 ) {
Attach( other, Vector3.right * size );
}
}
Good luck!