Are you mostly interested in the Math or the result?
If you’re only interested in being able to rotate an object around a pivot of your choice then creating a parent object and using that as the pivot would be a much easier solution.
I’ve made an example.
If people really want me to post the code here I will, but it’s kind of a lot. Also, for this to work properly you cannot simply copy the code. The code requires a certain object hierarchy and references to be in place. At the bottom of my post you’ll find links to the zip file. The project was created in Unity 2018.1.
The post is an empty gameobject which contains a tall, thin cube that is placed so that the bottom of the cube touches the center of its parent to make it easier to place the posts on a surface.
The post also contains an empty object called “paling Position”. It determines where the connected paling will be positioned.
The paling is an empty object which contains a long, thin cube that is placed so that one end of the cube touches the center of the paling object. The cube is longest on the Z axis (I’ll explain why that’s important later).
Placing the first post
To place the first post, I simply use Camera.ScreenToWorldPoint and then raycast to find the point in the world that I clicked on. Once I have the point, I instantiate a post and set its position to the raycast point. No position adjustments required because I made sure that the center of the post object is at the bottom of the 3D model (the simple, stretched cube in my case).
Placing another post
Again, I use raycast to determine the position of the click in the world.
This time, I cannot simply create a post at the clicked position because the paling has a fixed size that I should avoid changing (as requested by dan_wipf). The terrain could be very uneven and unpredictable, so I can’t solve this with a bit of simple math.
Instead, I chose to solve this problem by doing a series of raycasts in a circular motion. Imagine standing by the last post, lifting the new post up about 80 degrees with your arm stretched and then lowering the post (while keeping your arm stretched) until the post touches the ground. In this case, your arm would be the length of the paling. This way I ensure that the length of the paling can remain unchanged. The distance (on the X and Z axes) between the two posts will of course vary which means that if the fence is placed on a hill, the steeper the hill the closer the posts will be to each other.
As an extra feature, instead of always creating the new post relative to the one created before it, I chose to check which post is closest to the position I clicked: The very first post created or the very last post. All posts between those two have no effect on the placement of the new post. Using two variables of the type Transform, I keep track of the two ends of the fence. Every time I create a new post, I determine whether to overwrite the FirstPost reference or LastPost.
Connecting the posts by a paling
Now I have two posts to work with:
The newly created post and the post closest to the where I clicked (I’ll call it the “last post” while explaining).
I instantiate a paling and set its position to the same as the last post. Remember, that the center of the post object is at the foot of its 3D model and the center of the paling is at one end of its 3D model, which means that one end of the paling is touching the bottom of the post.
While the paling is at the foot of the last post, I use paling.transform.LookAt (newPost). I now have two posts connected by a paling at the bottom. When I was creating the paling prefab, the LookAt method is the reason why I specifically chose to stretch the paling’s cube along the Z-axis instead of, say, the X-axis
The paling is a the foot of the post. I need to raise it, but I don’t want to hardcode the height. Therefore, I use Transform.Find() to look inside the last post for an object called “Paling Position” and use that object’s localPosition to raise the paling to the correct height. Because all posts have the same height, we now have two posts connected by a paling at the top.
- An indicator (different colored post) shows the exact position where the post will be placed. It changes color depending on whether the position is valid or not.
- You can control the camera. The controls are displayed on-screen (see the screenshot).
- There are public fields available that let you limit how steep you can build the fence.
You can download the project files here. The zip-file contains the “Assets” and “ProjectSettings” folders. No executables. I used Unity v2018.1.
Just a heads up: I use an unorthodox naming convention which is explained at the top of the scripts.