Search code examples
c#unity-game-enginegame-physicsgame-development

Aligning one game object to another for base building system considering different rotations based on raycast hit


I am creating base building system similiar to Valheim's one, but I have problems with aligning objects towards themselves. I want to be able to place object with different rotation at point my camera is looking and make them stick to other objects, like in classic base building system.

I tried to determine the distance I need to move the object from the raycast hit point based on mesh renderer bounds size like below:

visualization.transform.postion = currentHit.point + Vector3.Scale(visualization.Bounds.extents, currentHit.normal.normalized);

This works only for right and straight angles, and becomes a problem when there are different rotations: enter image description here enter image description here

Is there any way to know the distance based on renderer/collider size and object rotation, without using bounds?


Solution

  • The issue with the Bounds in general is they are world aligned (see e.g. MeshRenderer has wrong bounds when rotated)

    If you have Colliders you could use Physics.CalculatePenetration

    Translating the first collider by direction * distance will separate the colliders apart if the function returned true. Otherwise, direction and distance are not defined.

    That means you would first check if the blocks overlap at all e.g. using OnCollisionEnter and can then use the Physics.CalculatePenetration to separate the blocks and male the one you move "snap" outside of the one it collided with.

    If they are not overlapping then yes I would probably first use a BoxCast and assume you would move the object to a position where it definitely overlaps the hit and then separate again.

    If it needs to work for arbitrary meshes it will get complex as the CalculatePenetration requires at least one convex collider.


    If that's the case though then you can also use kinematic Rigidbody and do a Rigidbody.SweepTest