Unity - 绕Y轴旋转object,同时不断设置朝向地面的不同旋转
Unity - rotating object around Y axis, while constantly setting up different rotation towards the ground
所以我不知道我是否在标题中正确解释了它,但我想做的是通过单击 Q 或 E 围绕 Y 轴旋转 object,但同时我正在向地面投射光线以检查点旋转以使其朝向正确的方向。
为了阐明这一点,这里有一个例子:
我正在尝试放置壁炉,我在山上。为了防止壁炉进入地形,我需要旋转它,以便我 "stick" 到它底部的地形,但我想将它围绕 Y 旋转几度..
这是我得到的代码:
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));
}
}
}
}
}
这里的问题是它面对地形没有任何问题,但我无法自己绕 Y 旋转它。我认为这是因为我不断更新轮换,但我不知道如何改变它。
是的,这是因为你用 prefabAsTransform.transform.up = hit.normal;
设置了每帧的旋转,而没有考虑当前的前进方向。
相反,您应该使用prefabAsTransform.rotation = LookRotation(newForward, newUp);
但是,您如何使用当前转发来确定newForward
?您可以为此使用叉积。这对我有用:
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));
}
}
}
}
所以我不知道我是否在标题中正确解释了它,但我想做的是通过单击 Q 或 E 围绕 Y 轴旋转 object,但同时我正在向地面投射光线以检查点旋转以使其朝向正确的方向。
为了阐明这一点,这里有一个例子: 我正在尝试放置壁炉,我在山上。为了防止壁炉进入地形,我需要旋转它,以便我 "stick" 到它底部的地形,但我想将它围绕 Y 旋转几度.. 这是我得到的代码:
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));
}
}
}
}
}
这里的问题是它面对地形没有任何问题,但我无法自己绕 Y 旋转它。我认为这是因为我不断更新轮换,但我不知道如何改变它。
是的,这是因为你用 prefabAsTransform.transform.up = hit.normal;
设置了每帧的旋转,而没有考虑当前的前进方向。
相反,您应该使用prefabAsTransform.rotation = LookRotation(newForward, newUp);
但是,您如何使用当前转发来确定newForward
?您可以为此使用叉积。这对我有用:
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));
}
}
}
}