Reputation: 23
so i don't know if i explained it properly in the title, but what i'm trying to do is by clicking Q or E rotate object around the Y axis, but at the same time i'm raycasting to the ground to check the point rotation to face it in to the right direction.
To clarify this, here is an example: I'm trying to place the fireplace, i'm on the hill. To prevent the fireplace go into the terrain, i need to rotate it so that i would "stick" to the terrain by it's bottom, but then i want to rotate it around the Y a couple of degrees.. Here is the code that i've got:
using UnityEngine;
public class Foobar : MonoBehaviour
{
Transform cam;
Transform prefabAsTransform;
Vector3 currentPos;
float addToY = 0.5f;
int mask;
void Start()
{
cam = Camera.main.transform;
prefabAsTransform = transform;
mask = LayerMask.GetMask("Default");
}
void Update()
{
RaycastHit hit;
if (Physics.Raycast(cam.position, cam.forward, out hit, Mathf.Infinity, mask))
{
currentPos = new Vector3(hit.point.x, hit.point.y + addToY, hit.point.z);
prefabAsTransform.position = currentPos;
prefabAsTransform.transform.up = hit.normal;
}
if (prefabAsTransform != null)
{
if (Input.GetKeyDown(KeyCode.Q))
{
if (Input.GetKey(KeyCode.LeftControl))
{
prefabAsTransform.Rotate(new Vector3(0, 1, 0));
}
else
{
prefabAsTransform.Rotate(new Vector3(0, 10, 0));
}
}
if (Input.GetKeyDown(KeyCode.E))
{
if (Input.GetKey(KeyCode.LeftControl))
{
prefabAsTransform.Rotate(new Vector3(0, -1, 0));
}
else
{
prefabAsTransform.Rotate(new Vector3(0, -10, 0));
}
}
}
}
}
The problem here is that it's facing the terrain without any issues, but i'm unable to rotate it around Y by myself. I assume that's due to the fact, that i'm constantly updating the rotation, but i have no idea how to change that.
Upvotes: 2
Views: 1523
Reputation: 20259
Yes, it's because you are setting the rotation every frame with prefabAsTransform.transform.up = hit.normal;
and not taking the current forward direction into account.
Instead, you should use prefabAsTransform.rotation = LookRotation(newForward, newUp);
But, how can you use the current forward to determine newForward
? You can use cross products for that. This worked for me:
void Update()
{
RaycastHit hit;
if (Physics.Raycast(cam.position, cam.forward, out hit, Mathf.Infinity, mask))
{
currentPos = new Vector3(hit.point.x, hit.point.y + addToY, hit.point.z);
prefabAsTransform.position = currentPos;
Vector3 newUp = hit.normal;
Vector3 oldForward = prefabAsTransform.forward;
Vector3 newRight = Vector3.Cross(newUp, oldForward);
Vector3 newForward = Vector3.Cross(newRight, newUp);
prefabAsTransform.rotation = Quaternion.LookRotation(newForward, newUp);
}
if (prefabAsTransform != null)
{
if (Input.GetKeyDown(KeyCode.Q))
{
if (Input.GetKey(KeyCode.LeftControl))
{
prefabAsTransform.Rotate(new Vector3(0, 1, 0));
}
else
{
prefabAsTransform.Rotate(new Vector3(0, 10, 0));
}
}
if (Input.GetKeyDown(KeyCode.E))
{
if (Input.GetKey(KeyCode.LeftControl))
{
prefabAsTransform.Rotate(new Vector3(0, -1, 0));
}
else
{
prefabAsTransform.Rotate(new Vector3(0, -10, 0));
}
}
}
}
Upvotes: 1