生成动态轮换

时间:2015-12-02 17:49:14

标签: c# unity3d rotation unity5

我目前有一个脚本,它使GameObject相对于另一个GameObject移动,如下面的.gif所示。

Dynamic Movement *Only*

我还没想到的是如何相对于另一个GameObject的位置制作相同的GameObject rotate ,使其始终以原始旋转结束,如图所示在下图中:

Dynamic Rotation

所以,现在我已经"动态运动" (如.gif中所示),如何创建"动态旋转" (如图中所示)?

我没有完成此类任务的经验,搜索Web也没有帮助,所以我非常感谢准备部署的脚本。谢谢你的回答。

3 个答案:

答案 0 :(得分:1)

如果我理解正确的话,你只是想确保物体在飞行中在空中飞行时间翻转。你可以使用这样的东西:

using UnityEngine;
using System.Collections;

public class RotaionManager : MonoBehaviour {

    // Motion start point
    public Transform origin;
    // Motion end point
    public Transform destination;

    // Start and en anle - 360 for single full rotation
    public float startAngle = 0;
    public float endAngle = 360;

    void Update () {

        // Distance to origin
        var dstOrigin = Vector3.Distance(origin.position, transform.position);
        // Distance to destination
        var dstDestination = Vector3.Distance(destination.position, transform.position);
        // Parameter
        float t = (dstDestination + dstOrigin == 0 ? 0 : (dstOrigin / (dstDestination + dstOrigin) ) );
        // The angle at current t
        float angle = Mathf.Lerp(startAngle, endAngle, t);

        // Rotate the object by the angle, then make sure it also faces destination
        transform.rotation = Quaternion.LookRotation(destination.position - origin.position) * Quaternion.Euler(angle, 0, 0);

    }
}

基于到起点和终点的距离,简单地线性插补旋转角度。您可以控制对象按开始和结束角度旋转的次数。使用旋转是为了除了围绕自己的轴旋转外,对象还将面向目标的大致方向。

看看示例项目: https://www.dropbox.com/s/g00srsjlqjx1jcz/RotationProj.zip?dl=0

修改

最好使用源 - 目标矢量上的物体投影距离而不是原始距离,它在陡峭的路径上看起来更好。更新功能如下所示:

void Update () {

    // Projection of object on line between origin and destination
    var projection = Vector3.Project(transform.position - origin.position, origin.position - destination.position) + origin.position;
    // Distance to origin
    var dstOrigin = Vector3.Distance(origin.position, projection);
    // Distance to destination
    var dstDestination = Vector3.Distance(destination.position, projection);
    // Parameter
    float t = (dstDestination + dstOrigin == 0 ? 0 : (dstOrigin / (dstDestination + dstOrigin) ) );
    // The angle at current t
    float angle = Mathf.Lerp(startAngle, endAngle, t);

    // Rotate the object by the angle, then make sure it also faces destination
    transform.rotation = Quaternion.LookRotation(destination.position - origin.position) * Quaternion.Euler(angle, 0, 0);

}

我还更新了示例项目

修改

另一种可能看起来更好的方法可能是忽略起点和终点的 Y 坐标,并进行投影。在一些极端情况下看起来好一点。代码看起来会这样:

void Update () {

    Vector3 op = origin.position; op.y = 0;
    Vector3 dp = destination.position; dp.y = 0;
    // Projection of object on line between origin and destination
    var projection = Vector3.Project(transform.position - origin.position, op - dp) + op;
    // Distance to origin
    var dstOrigin = Vector3.Distance(op, projection);
    // Distance to destination
    var dstDestination = Vector3.Distance(dp, projection);
    // Parameter
    float t = (dstDestination + dstOrigin == 0 ? 0 : (dstOrigin / (dstDestination + dstOrigin) ) );
    // The angle at current t
    float angle = Mathf.Lerp(startAngle, endAngle, t);

    // Rotate the object by the angle, then make sure it also faces destination
    transform.rotation = Quaternion.LookRotation(dp - op) * Quaternion.Euler(angle, 0, 0);

}

答案 1 :(得分:0)

在类似情况下帮助我的一种可能性是transform.LookAt功能。这使您可以始终面对目标。您可以在transform.LookAt(target.transform)方法中添加Update之类的内容,并始终面向目标。一旦达到目标,您可能希望将其设置为常数值,因为如果您与目标位置不完全相同,可能会出现奇怪旋转的问题。

答案 2 :(得分:0)

  • 我假设你的游戏中有一个投掷者,摇滚和目标。运动员 将岩石扔向目标,岩石应该旋转360度。

    private float mag = 0 ;//will be total distance
    private Vector3 throwerPos ;
    private Boolean isThrown = false;// you have to set this true whenever you throw a rock.
    
    void Update()
    {
     .
     .
     if(isThrown)
     {
      mag = (target.position -thrower.position).magnitude;//get distance whenever you throw it.
      throwerPos = thrower.position;
      rotateIt();
     }
    } 
    
    void rotateIt()
    {
     float currMag = (rock.position - throwerPos).magnitute ;//get current distance between rock and thrower and rotate it depends on distance at the throwing time
         angle= Mathf.MoveTowards(0,360,currMag / mag);
         rock.getComponent<Transform>().eulerAngles = new Vector3(
         rock.getComponent<Transform>().eulerAngles.x,
         rock.getComponent<Transform>().eulerAngles.y,
         angle);
        if(angle == 360)
        {
          rock.getComponent<Transform>().eulerAngles.z=0;
          isThrown = false;
        }
    }
    

    我没有执行此代码,这可能无效。这只是一个想法。我认为有很多方法可以达到这个目的。