简体   繁体   中英

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.

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?

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 . 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. You can use transform.TransformDirection to find the current direction the ball is "pointing" and then calculate the angle using 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(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. However, the LateUpdate method is easiest to demonstrate so I will do that here:

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.

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.

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

检查这个 还有这个

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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