沿 Unity 中移动的方向旋转对象
Rotate object in the direction it's moving in Unity
我有一个 2D 物体,它简单地向前移动直到它撞到另一个物体,其中物理 material 导致物体从另一个物体反弹。
我不是最擅长绘图的,但这是我想要它做什么的图示:(球体中的箭头表示球体当前面向的方向)
我把它的物理部分记下来就好了,但是物理 material 不会旋转游戏对象,所以实际结果看起来更像这样:
我知道你可以很容易地使用变换设置对象的旋转,但是你如何获得游戏对象的移动方向,然后将旋转设置为该方向?
我目前无法对此进行测试,但以下应该可行。
Vector3 prevPosition = Vector3.zero;
void Update()
{
if(prevPosition != Vector3.zero)
{
Vector3 movementDir = transform.position - prevPosition;
transform.rotation = Quaternion.LookRotation(movementDir, Vector3.Up);
}
prevPosition = transform.position;
}
我们所做的就是比较物体上一帧的位置和它在这一帧的位置,减去这些位置得到一个向量,然后沿着那个向量旋转面对面。
在更新方法中,每帧调用一次,如果你只有一个球,没问题,但如果你有几千个,你可能想进入一个只在碰撞后调用的方法。
在物理处于活动状态时手动旋转可能会给您带来一些古怪的结果,但这里是
public class FaceVelocity : MonoBehaviour
{
private Rigidbody rigidBody;
void Awake()
{
rigidBody = getComponent<RigidBody2D>();
}
//Apply rotation in late update to make sure it's not undone by physics
void LateUpdate()
{
transform.right = rigidBody.velocity.normalized
}
}
如果你的物体在与某物接触时旋转(也就是它最有可能接触的地方),它可能会扰乱物理学。最好为物理使用父对象,为视觉使用子对象。
public class FaceVelocity : MonoBehaviour
{
private Rigidbody rigidBody;
void Awake()
{
rigidBody = transform.parent.getComponent<RigidBody2D>();
}
//Apply rotation in late update to make sure it's not undone
void LateUpdate()
{
transform.right = rigidBody.velocity.normalized
}
}
虽然在我看来你甚至不需要刚体,粒子物理学就足够了。如果不使用刚体,请自行计算速度方向:
public class FaceVelocity : MonoBehaviour
{
private Vector3 prevPos;
void Awake()
{
prevPos = transform.position;
}
//Apply rotation in late update to make sure it's not undone
void LateUpdate()
{
transform.right = (transform.position - prevpos).normalized
}
}
首先你要知道图像的局部方向应该是指向运动的方向。这取决于您的设置,并且问题不包含足够的信息来准确了解。它可能是 Vector3.up
或 Vector3.right
。当然,世界方向是通过速度知道的。
Vector3 worldDirectionToPointForward = rb2d.velocity.normalized;
Vector3 localDirectionToPointForward = Vector3.right;
然后,您想要围绕 z 轴旋转精灵,使局部方向指向该方向。您可以使用 transform.TransformDirection
找到球的当前方向 "pointing" 然后使用 Vector3.SignedAngle
:
计算角度
Vector3 currentWorldForwardDirection = transform.TransformDirection(
localDirectionToPointForward);
float angleDiff = Vector3.SignedAngle(currentWorldForwardDirection,
worldDirectionToPointForward, Vector3.forward);
然后,使用 transform.Rotate
.
将其绕 z 轴旋转该量
transform.Rotate(Vector3.forward, angleDiff);
我会在撞墙后这样做。另一种方法是将它放在 LateUpdate
中,尽管这可能会干扰其他单一行为中发生在 LateUpdate
中的其他事情。但是,LateUpdate
方法最容易演示,因此我将在此处进行演示:
void LateUpdate()
{
Vector3 worldDirectionToPointForward = rb2d.velocity.normalized;
Vector3 localDirectionToPointForward = Vector3.right;
Vector3 currentWorldForwardDirection = transform.TransformDirection(
localDirectionToPointForward);
float angleDiff = Vector3.SignedAngle(currentWorldForwardDirection,
worldDirectionToPointForward, Vector3.forward);
transform.Rotate(Vector3.forward, angleDiff, Space.World);
}
希望这个脚本能帮到你
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Reflect : MonoBehaviour
{
//3d Project
public int reflections;
public float maxLenght;
private Ray ray;
private RaycastHit hit;
private Vector3 direction;
Vector3 pos;
private void Awake()
{
reflections = 5;
maxLenght = 200;
pos = gameObject.transform.position;
GetNextPoint(1);
}
private void Update()
{
if (Vector3.Distance(gameObject.transform.position, pos) >0.7f)
{
//move
transform.position += transform.forward/10;
}
else
{
GetNextPoint(2);
}
}
void GetNextPoint(int num)
{
ray = new Ray(transform.position, transform.forward);
float remaningLength = maxLenght;
int t = 0;
for (int i = 0; i < reflections; i++)
{
if (Physics.Raycast(ray.origin, ray.direction, out hit, remaningLength))
{
ray = new Ray(hit.point, Vector3.Reflect(ray.direction, hit.normal));
t++;
if (t == num)
{
gameObject.transform.LookAt(hit.point);
pos = hit.point;
break;
}
}
}
}
}
我有一个 2D 物体,它简单地向前移动直到它撞到另一个物体,其中物理 material 导致物体从另一个物体反弹。
我不是最擅长绘图的,但这是我想要它做什么的图示:(球体中的箭头表示球体当前面向的方向)
我把它的物理部分记下来就好了,但是物理 material 不会旋转游戏对象,所以实际结果看起来更像这样:
我知道你可以很容易地使用变换设置对象的旋转,但是你如何获得游戏对象的移动方向,然后将旋转设置为该方向?
我目前无法对此进行测试,但以下应该可行。
Vector3 prevPosition = Vector3.zero;
void Update()
{
if(prevPosition != Vector3.zero)
{
Vector3 movementDir = transform.position - prevPosition;
transform.rotation = Quaternion.LookRotation(movementDir, Vector3.Up);
}
prevPosition = transform.position;
}
我们所做的就是比较物体上一帧的位置和它在这一帧的位置,减去这些位置得到一个向量,然后沿着那个向量旋转面对面。
在更新方法中,每帧调用一次,如果你只有一个球,没问题,但如果你有几千个,你可能想进入一个只在碰撞后调用的方法。
在物理处于活动状态时手动旋转可能会给您带来一些古怪的结果,但这里是
public class FaceVelocity : MonoBehaviour
{
private Rigidbody rigidBody;
void Awake()
{
rigidBody = getComponent<RigidBody2D>();
}
//Apply rotation in late update to make sure it's not undone by physics
void LateUpdate()
{
transform.right = rigidBody.velocity.normalized
}
}
如果你的物体在与某物接触时旋转(也就是它最有可能接触的地方),它可能会扰乱物理学。最好为物理使用父对象,为视觉使用子对象。
public class FaceVelocity : MonoBehaviour
{
private Rigidbody rigidBody;
void Awake()
{
rigidBody = transform.parent.getComponent<RigidBody2D>();
}
//Apply rotation in late update to make sure it's not undone
void LateUpdate()
{
transform.right = rigidBody.velocity.normalized
}
}
虽然在我看来你甚至不需要刚体,粒子物理学就足够了。如果不使用刚体,请自行计算速度方向:
public class FaceVelocity : MonoBehaviour
{
private Vector3 prevPos;
void Awake()
{
prevPos = transform.position;
}
//Apply rotation in late update to make sure it's not undone
void LateUpdate()
{
transform.right = (transform.position - prevpos).normalized
}
}
首先你要知道图像的局部方向应该是指向运动的方向。这取决于您的设置,并且问题不包含足够的信息来准确了解。它可能是 Vector3.up
或 Vector3.right
。当然,世界方向是通过速度知道的。
Vector3 worldDirectionToPointForward = rb2d.velocity.normalized;
Vector3 localDirectionToPointForward = Vector3.right;
然后,您想要围绕 z 轴旋转精灵,使局部方向指向该方向。您可以使用 transform.TransformDirection
找到球的当前方向 "pointing" 然后使用 Vector3.SignedAngle
:
Vector3 currentWorldForwardDirection = transform.TransformDirection(
localDirectionToPointForward);
float angleDiff = Vector3.SignedAngle(currentWorldForwardDirection,
worldDirectionToPointForward, Vector3.forward);
然后,使用 transform.Rotate
.
transform.Rotate(Vector3.forward, angleDiff);
我会在撞墙后这样做。另一种方法是将它放在 LateUpdate
中,尽管这可能会干扰其他单一行为中发生在 LateUpdate
中的其他事情。但是,LateUpdate
方法最容易演示,因此我将在此处进行演示:
void LateUpdate()
{
Vector3 worldDirectionToPointForward = rb2d.velocity.normalized;
Vector3 localDirectionToPointForward = Vector3.right;
Vector3 currentWorldForwardDirection = transform.TransformDirection(
localDirectionToPointForward);
float angleDiff = Vector3.SignedAngle(currentWorldForwardDirection,
worldDirectionToPointForward, Vector3.forward);
transform.Rotate(Vector3.forward, angleDiff, Space.World);
}
希望这个脚本能帮到你
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Reflect : MonoBehaviour
{
//3d Project
public int reflections;
public float maxLenght;
private Ray ray;
private RaycastHit hit;
private Vector3 direction;
Vector3 pos;
private void Awake()
{
reflections = 5;
maxLenght = 200;
pos = gameObject.transform.position;
GetNextPoint(1);
}
private void Update()
{
if (Vector3.Distance(gameObject.transform.position, pos) >0.7f)
{
//move
transform.position += transform.forward/10;
}
else
{
GetNextPoint(2);
}
}
void GetNextPoint(int num)
{
ray = new Ray(transform.position, transform.forward);
float remaningLength = maxLenght;
int t = 0;
for (int i = 0; i < reflections; i++)
{
if (Physics.Raycast(ray.origin, ray.direction, out hit, remaningLength))
{
ray = new Ray(hit.point, Vector3.Reflect(ray.direction, hit.normal));
t++;
if (t == num)
{
gameObject.transform.LookAt(hit.point);
pos = hit.point;
break;
}
}
}
}
}