简体   繁体   English

沿它在 Unity 中移动的方向旋转 object

[英]Rotate object in the direction it's moving in Unity

I have a 2D object that simply moves straight forward until it hit's another object, in which the physics material causes the object to bounce off the other object.我有一个 2D object,它简单地向前移动,直到它撞到另一个 object,其中物理材料导致 object 从另一个 object 反弹。

I'm not the best at drawing but here's an illustration of what I want it to do: (The arrow in the sphere represents what direction the sphere is currently facing)我不是最擅长绘图的,但这是我想要它做的事情的说明:(球体中的箭头表示球体当前面向的方向)

在此处输入图像描述

在此处输入图像描述

I have the physics part of this down just fine, however the physics material does not rotate the gameobject so instead the actual result looks more like this:我把它的物理部分写得很好,但是物理材质不会旋转游戏对象,所以实际结果看起来更像这样:

在此处输入图像描述

I know you can set the rotation of the object pretty easily with transform, but how do you get the movement direction of the gameobject and then set the rotation to that direction?我知道你可以很容易地通过变换设置 object 的旋转,但是你如何获得游戏对象的移动方向,然后将旋转设置为该方向?

First, you need to know the local direction of the image should be pointing in the direction of movement.首先,你需要知道图像的局部方向应该指向运动的方向。 This depends on your setup and the question does not include enough information to know exactly.这取决于您的设置,并且问题不包含足够的信息来准确了解。 It's probably either Vector3.up or Vector3.right .它可能是Vector3.upVector3.right Of course, the world direction is known from the velocity.当然,世界方向是从速度得知的。

Vector3 worldDirectionToPointForward = rb2d.velocity.normalized;
Vector3 localDirectionToPointForward = Vector3.right;

Then, you want to rotate the sprite around the z axis so that the local direction points in that direction.然后,您想要围绕 z 轴旋转精灵,使局部方向指向该方向。 You can use transform.TransformDirection to find the current direction the ball is "pointing" and then calculate the angle using Vector3.SignedAngle :您可以使用transform.TransformDirection找到球“指向”的当前方向,然后使用Vector3.SignedAngle计算角度:

Vector3 currentWorldForwardDirection = transform.TransformDirection(
        localDirectionToPointForward);
float angleDiff = Vector3.SignedAngle(currentWorldForwardDirection, 
        worldDirectionToPointForward, Vector3.forward);

Then, rotate it by that amount around the z axis, using transform.Rotate .然后,使用transform.Rotate将其围绕 z 轴旋转该量。

transform.Rotate(Vector3.forward, angleDiff);

And I would do this after a collision with the wall.我会在与墙壁发生碰撞后这样做。 An alternative is to put it in LateUpdate , although that may interfere with other things occurring in LateUpdate in other monobehaviours.另一种方法是将它放在LateUpdate中,尽管这可能会干扰其他单一行为中LateUpdate中发生的其他事情。 However, the LateUpdate method is easiest to demonstrate so I will do that here:但是, 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);
}

I can't test this at the moment but the following should work.我目前无法对此进行测试,但以下应该有效。

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;
}

All we are doing is comparing the objects position last frame with it's position this frame, subtracting those positions to get a vector, then rotating to face along that vector.我们所做的就是比较最后一帧的对象 position 和这一帧的对象 position,减去这些位置得到一个向量,然后旋转以沿着该向量面对。

In the update method this is called every frame, no problem if you only have one ball, but if you've got thousands you might want to move into a method that is only called after a collision.在更新方法中,每一帧都会调用它,如果你只有一个球也没问题,但如果你有几千个,你可能想进入一个只在碰撞后调用的方法。

Manually rotating while physics are active may give you some wacky results, but here goes在物理处于活动状态时手动旋转可能会给您带来一些古怪的结果,但是这里有

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
    }
}

If your objects rotates while in contact with something (aka where it's most likely to) it may disort physics.如果你的物体在与某物接触时旋转(也就是它最有可能接触的地方),它可能会扰乱物理学。 It may be better to to use a parent object for physics and a child object for visuals.最好使用父 object 来学习物理,使用子 object 来学习视觉效果。

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
    }
}

Although to me it sounds like you don't even need rigidbodies and particle physics would be enough.虽然对我来说,听起来你甚至不需要刚体,粒子物理学就足够了。 If you do not use rigidbodies, calculate velocity direction yourself:如果不使用刚体,请自行计算速度方向:

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
        }
    }

I hope this script will help you我希望这个脚本能帮助你

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;
                }
            }
        }
    }
}

检查这个 还有这个

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM